src/HOL/Library/code_test.ML
author wenzelm
Fri, 04 Oct 2019 15:30:52 +0200
changeset 70784 799437173553
parent 69950 dbc2426a600d
child 72272 6931ab4f1a47
permissions -rw-r--r--
Term_XML.Encode/Decode.term uses Const "typargs";
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
59720
f893472fff31 proper headers;
wenzelm
parents: 59323
diff changeset
     1
(*  Title:      HOL/Library/code_test.ML
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
     2
    Author:     Andreas Lochbihler, ETH Zürich
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
     3
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
     4
Test infrastructure for the code generator.
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
     5
*)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
     6
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
     7
signature CODE_TEST =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
     8
sig
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
     9
  val add_driver:
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    10
    string * ((Proof.context -> (string * string) list * string -> Path.T -> string) * string) ->
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    11
    theory -> theory
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    12
  val overlord: bool Config.T
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    13
  val successN: string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    14
  val failureN: string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    15
  val start_markerN: string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    16
  val end_markerN: string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    17
  val test_terms: Proof.context -> term list -> string -> unit
64578
wenzelm
parents: 64577
diff changeset
    18
  val test_targets: Proof.context -> term list -> string list -> unit
64580
wenzelm
parents: 64579
diff changeset
    19
  val test_code_cmd: string list -> string list -> Proof.context -> unit
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    20
  val eval_term: string -> Proof.context -> term -> term
64581
ee4b9cea7fb5 tuned signature -- suppress pointless exports;
wenzelm
parents: 64580
diff changeset
    21
  val evaluate:
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    22
   (theory -> Path.T -> string list -> string ->
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
    23
     {files: (Path.T * string) list,
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
    24
       compile_cmd: string option,
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
    25
       run_cmd: string,
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
    26
       mk_code_file: string -> Path.T}) -> (string * string) option -> string -> theory ->
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
    27
     (string * string) list * string -> Path.T -> string
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    28
  val evaluate_in_polyml: Proof.context -> (string * string) list * string -> Path.T -> string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    29
  val evaluate_in_mlton: Proof.context -> (string * string) list * string -> Path.T -> string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    30
  val evaluate_in_smlnj: Proof.context -> (string * string) list * string -> Path.T -> string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    31
  val evaluate_in_ocaml: Proof.context -> (string * string) list * string -> Path.T -> string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    32
  val ghc_options: string Config.T
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    33
  val evaluate_in_ghc: Proof.context -> (string * string) list * string -> Path.T -> string
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    34
  val evaluate_in_scala: Proof.context -> (string * string) list * string -> Path.T -> string
66284
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
    35
  val target_Scala: string
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
    36
  val target_Haskell: string
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    37
end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    38
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    39
structure Code_Test: CODE_TEST =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    40
struct
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    41
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    42
(* convert a list of terms into nested tuples and back *)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    43
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
    44
fun mk_tuples [] = \<^term>\<open>()\<close>
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    45
  | mk_tuples [t] = t
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    46
  | mk_tuples (t :: ts) = HOLogic.mk_prod (t, mk_tuples ts)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    47
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
    48
fun dest_tuples (Const (\<^const_name>\<open>Pair\<close>, _) $ l $ r) = l :: dest_tuples r
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    49
  | dest_tuples t = [t]
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    50
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    51
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    52
fun last_field sep str =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    53
  let
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    54
    val n = size sep
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    55
    val len = size str
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    56
    fun find i =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    57
      if i < 0 then NONE
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    58
      else if String.substring (str, i, n) = sep then SOME i
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    59
      else find (i - 1)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    60
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    61
    (case find (len - n) of
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    62
      NONE => NONE
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    63
    | SOME i => SOME (String.substring (str, 0, i), String.extract (str, i + n, NONE)))
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    64
  end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    65
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    66
fun split_first_last start stop s =
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    67
  (case first_field start s of
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    68
    NONE => NONE
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    69
  | SOME (initial, rest) =>
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    70
      (case last_field stop rest of
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    71
        NONE => NONE
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    72
      | SOME (middle, tail) => SOME (initial, middle, tail)))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    73
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    74
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    75
(* data slot for drivers *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    76
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    77
structure Drivers = Theory_Data
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    78
(
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    79
  type T =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    80
    (string * ((Proof.context -> (string * string) list * string -> Path.T -> string) * string)) list
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    81
  val empty = []
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    82
  val extend = I
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    83
  fun merge data : T = AList.merge (op =) (K true) data
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    84
)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    85
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    86
val add_driver = Drivers.map o AList.update (op =)
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    87
val get_driver = AList.lookup (op =) o Drivers.get
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    88
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    89
(*
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    90
  Test drivers must produce output of the following format:
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
    91
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    92
  The start of the relevant data is marked with start_markerN,
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    93
  its end with end_markerN.
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    94
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    95
  Between these two markers, every line corresponds to one test.
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    96
  Lines of successful tests start with successN, failures start with failureN.
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    97
  The failure failureN may continue with the YXML encoding of the evaluated term.
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    98
  There must not be any additional whitespace in between.
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
    99
*)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   100
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   101
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   102
(* parsing of results *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   103
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   104
val successN = "True"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   105
val failureN = "False"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   106
val start_markerN = "*@*Isabelle/Code_Test-start*@*"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   107
val end_markerN = "*@*Isabelle/Code_Test-end*@*"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   108
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   109
fun parse_line line =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   110
  if String.isPrefix successN line then (true, NONE)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   111
  else if String.isPrefix failureN line then (false,
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   112
    if size line > size failureN then
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   113
      String.extract (line, size failureN, NONE)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   114
      |> YXML.parse_body
70784
799437173553 Term_XML.Encode/Decode.term uses Const "typargs";
wenzelm
parents: 69950
diff changeset
   115
      |> Term_XML.Decode.term_raw
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   116
      |> dest_tuples
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   117
      |> SOME
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   118
    else NONE)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   119
  else raise Fail ("Cannot parse result of evaluation:\n" ^ line)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   120
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   121
fun parse_result target out =
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   122
  (case split_first_last start_markerN end_markerN out of
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   123
    NONE => error ("Evaluation failed for " ^ target ^ "!\nBash output:\n" ^ out)
65904
8411f1a2272c permissive trim_line as in Scala, e.g. relevant for poly/TextIO.print output on Windows;
wenzelm
parents: 65901
diff changeset
   124
  | SOME (_, middle, _) => middle |> trim_split_lines |> map parse_line)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   125
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   126
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   127
(* pretty printing of test results *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   128
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   129
fun pretty_eval _ NONE _ = []
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   130
  | pretty_eval ctxt (SOME evals) ts =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   131
      [Pretty.fbrk,
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   132
       Pretty.big_list "Evaluated terms"
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   133
         (map (fn (t, eval) => Pretty.block
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   134
           [Syntax.pretty_term ctxt t, Pretty.brk 1, Pretty.str "=", Pretty.brk 1,
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   135
            Syntax.pretty_term ctxt eval])
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   136
         (ts ~~ evals))]
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   137
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   138
fun pretty_failure ctxt target (((_, evals), query), eval_ts) =
60022
ea987317a785 tuned whitespace;
wenzelm
parents: 59936
diff changeset
   139
  Pretty.block (Pretty.text ("Test in " ^ target ^ " failed for")
ea987317a785 tuned whitespace;
wenzelm
parents: 59936
diff changeset
   140
    @ [Pretty.brk 1, Pretty.quote (Syntax.pretty_term ctxt query)]
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   141
    @ pretty_eval ctxt evals eval_ts)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   142
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   143
fun pretty_failures ctxt target failures =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   144
  Pretty.blk (0, Pretty.fbreaks (map (pretty_failure ctxt target) failures))
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   145
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   146
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   147
(* driver invocation *)
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   148
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   149
val overlord = Attrib.setup_config_bool \<^binding>\<open>code_test_overlord\<close> (K false)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   150
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   151
fun with_overlord_dir name f =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   152
  let
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   153
    val path =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   154
      Path.append (Path.explode "$ISABELLE_HOME_USER") (Path.basic (name ^ serial_string ()))
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   155
    val _ = Isabelle_System.mkdirs path
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   156
  in Exn.release (Exn.capture f path) end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   157
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   158
fun dynamic_value_strict ctxt t compiler =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   159
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   160
    val thy = Proof_Context.theory_of ctxt
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   161
    val (driver, target) =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   162
      (case get_driver thy compiler of
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   163
        NONE => error ("No driver for target " ^ compiler)
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   164
      | SOME f => f)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   165
    val debug = Config.get (Proof_Context.init_global thy) overlord
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   166
    val with_dir = if debug then with_overlord_dir else Isabelle_System.with_tmp_dir
69623
ef02c5e051e5 explicit model concerning files of generated code
haftmann
parents: 69597
diff changeset
   167
    fun evaluate result =
ef02c5e051e5 explicit model concerning files of generated code
haftmann
parents: 69597
diff changeset
   168
      with_dir "Code_Test" (driver ctxt ((apfst o map o apfst) Long_Name.implode result))
ef02c5e051e5 explicit model concerning files of generated code
haftmann
parents: 69597
diff changeset
   169
      |> parse_result compiler
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   170
    fun evaluator program _ vs_ty deps =
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   171
      Exn.interruptible_capture evaluate
64957
3faa9b31ff78 tuned structure and terminology
haftmann
parents: 64901
diff changeset
   172
        (Code_Target.compilation_text ctxt target program deps true vs_ty)
64578
wenzelm
parents: 64577
diff changeset
   173
    fun postproc f = map (apsnd (Option.map (map f)))
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   174
  in Exn.release (Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) evaluator t) end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   175
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   176
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   177
(* term preprocessing *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   178
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   179
fun add_eval (Const (\<^const_name>\<open>Trueprop\<close>, _) $ t) = add_eval t
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   180
  | add_eval (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ lhs $ rhs) = (fn acc =>
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   181
      acc
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   182
      |> add_eval rhs
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   183
      |> add_eval lhs
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   184
      |> cons rhs
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   185
      |> cons lhs)
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   186
  | add_eval (Const (\<^const_name>\<open>Not\<close>, _) $ t) = add_eval t
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   187
  | add_eval (Const (\<^const_name>\<open>Orderings.ord_class.less_eq\<close>, _) $ lhs $ rhs) = (fn acc =>
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   188
      lhs :: rhs :: acc)
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   189
  | add_eval (Const (\<^const_name>\<open>Orderings.ord_class.less\<close>, _) $ lhs $ rhs) = (fn acc =>
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   190
      lhs :: rhs :: acc)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   191
  | add_eval _ = I
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   192
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   193
fun mk_term_of [] = \<^term>\<open>None :: (unit \<Rightarrow> yxml_of_term) option\<close>
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   194
  | mk_term_of ts =
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   195
      let
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   196
        val tuple = mk_tuples ts
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   197
        val T = fastype_of tuple
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   198
      in
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   199
        \<^term>\<open>Some :: (unit \<Rightarrow> yxml_of_term) \<Rightarrow> (unit \<Rightarrow> yxml_of_term) option\<close> $
69597
ff784d5a5bfb isabelle update -u control_cartouches;
wenzelm
parents: 69593
diff changeset
   200
          (absdummy \<^typ>\<open>unit\<close> (\<^const>\<open>yxml_string_of_term\<close> $
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   201
            (Const (\<^const_name>\<open>Code_Evaluation.term_of\<close>, T --> \<^typ>\<open>term\<close>) $ tuple)))
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   202
      end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   203
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   204
fun test_terms ctxt ts target =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   205
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   206
    val thy = Proof_Context.theory_of ctxt
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   207
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   208
    fun term_of t = Sign.of_sort thy (fastype_of t, \<^sort>\<open>term_of\<close>)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   209
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   210
    fun ensure_bool t =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   211
      (case fastype_of t of
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   212
        \<^typ>\<open>bool\<close> => ()
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   213
      | _ =>
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   214
        error (Pretty.string_of
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   215
          (Pretty.block [Pretty.str "Test case not of type bool:", Pretty.brk 1,
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   216
            Syntax.pretty_term ctxt t])))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   217
64578
wenzelm
parents: 64577
diff changeset
   218
    val _ = List.app ensure_bool ts
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   219
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   220
    val evals = map (fn t => filter term_of (add_eval t [])) ts
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   221
    val eval = map mk_term_of evals
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   222
64578
wenzelm
parents: 64577
diff changeset
   223
    val t =
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   224
      HOLogic.mk_list \<^typ>\<open>bool \<times> (unit \<Rightarrow> yxml_of_term) option\<close>
64578
wenzelm
parents: 64577
diff changeset
   225
        (map HOLogic.mk_prod (ts ~~ eval))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   226
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   227
    val result = dynamic_value_strict ctxt t target
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   228
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   229
    val failed =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   230
      filter_out (fst o fst o fst) (result ~~ ts ~~ evals)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   231
      handle ListPair.UnequalLengths =>
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   232
        error ("Evaluation failed!\nWrong number of test results: " ^ Int.toString (length result))
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   233
  in
64578
wenzelm
parents: 64577
diff changeset
   234
    (case failed of [] =>
wenzelm
parents: 64577
diff changeset
   235
      ()
wenzelm
parents: 64577
diff changeset
   236
    | _ => error (Pretty.string_of (pretty_failures ctxt target failed)))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   237
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   238
64578
wenzelm
parents: 64577
diff changeset
   239
fun test_targets ctxt = List.app o test_terms ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   240
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   241
fun pretty_free ctxt = Syntax.pretty_term ctxt o Free
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   242
64580
wenzelm
parents: 64579
diff changeset
   243
fun test_code_cmd raw_ts targets ctxt =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   244
  let
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   245
    val ts = Syntax.read_terms ctxt raw_ts
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   246
    val frees = fold Term.add_frees ts []
64578
wenzelm
parents: 64577
diff changeset
   247
    val _ =
wenzelm
parents: 64577
diff changeset
   248
      if null frees then ()
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   249
      else error (Pretty.string_of
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   250
        (Pretty.block (Pretty.str "Terms contain free variables:" :: Pretty.brk 1 ::
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   251
          Pretty.commas (map (pretty_free ctxt) frees))))
64578
wenzelm
parents: 64577
diff changeset
   252
  in test_targets ctxt ts targets end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   253
58348
2d47c7d10b62 add target language evaluators for the value command;
Andreas Lochbihler
parents: 58039
diff changeset
   254
fun eval_term target ctxt t =
2d47c7d10b62 add target language evaluators for the value command;
Andreas Lochbihler
parents: 58039
diff changeset
   255
  let
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   256
    val frees = Term.add_frees t []
64578
wenzelm
parents: 64577
diff changeset
   257
    val _ =
wenzelm
parents: 64577
diff changeset
   258
      if null frees then ()
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   259
      else
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   260
        error (Pretty.string_of
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   261
          (Pretty.block (Pretty.str "Term contains free variables:" :: Pretty.brk 1 ::
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   262
            Pretty.commas (map (pretty_free ctxt) frees))))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   263
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   264
    val T = fastype_of t
64578
wenzelm
parents: 64577
diff changeset
   265
    val _ =
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   266
      if Sign.of_sort (Proof_Context.theory_of ctxt) (T, \<^sort>\<open>term_of\<close>) then ()
64579
38a1d8b41189 more standard pretty printing;
wenzelm
parents: 64578
diff changeset
   267
      else error ("Type " ^ Syntax.string_of_typ ctxt T ^
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   268
       " of term not of sort " ^ Syntax.string_of_sort ctxt \<^sort>\<open>term_of\<close>)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   269
64578
wenzelm
parents: 64577
diff changeset
   270
    val t' =
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   271
      HOLogic.mk_list \<^typ>\<open>bool \<times> (unit \<Rightarrow> yxml_of_term) option\<close>
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   272
        [HOLogic.mk_prod (\<^term>\<open>False\<close>, mk_term_of [t])]
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   273
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   274
    val result = dynamic_value_strict ctxt t' target
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   275
  in (case result of [(_, SOME [t])] => t | _ => error "Evaluation failed") end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   276
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   277
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   278
(* generic driver *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   279
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   280
fun evaluate mk_driver opt_env_var compilerN ctxt (code_files, value_name) =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   281
  let
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   282
    val _ =
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   283
      (case opt_env_var of
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   284
        NONE => ()
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   285
      | SOME (env_var, env_var_dest) =>
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   286
          (case getenv env_var of
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   287
            "" =>
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   288
              error (Pretty.string_of (Pretty.para
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   289
                ("Environment variable " ^ env_var ^ " is not set. To test code generation with " ^
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   290
                  compilerN ^ ", set this variable to your " ^ env_var_dest ^
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   291
                  " in the $ISABELLE_HOME_USER/etc/settings file.")))
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   292
          | _ => ()))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   293
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   294
    fun compile NONE = ()
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   295
      | compile (SOME cmd) =
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   296
          let
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   297
            val (out, ret) = Isabelle_System.bash_output cmd
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   298
          in
64578
wenzelm
parents: 64577
diff changeset
   299
            if ret = 0 then ()
wenzelm
parents: 64577
diff changeset
   300
            else error ("Compilation with " ^ compilerN ^ " failed:\n" ^ cmd ^ "\n" ^ out)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   301
          end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   302
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   303
    fun run path =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   304
      let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   305
        val modules = map fst code_files
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   306
        val {files, compile_cmd, run_cmd, mk_code_file} = mk_driver ctxt path modules value_name
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   307
64578
wenzelm
parents: 64577
diff changeset
   308
        val _ = List.app (fn (name, code) => File.write (mk_code_file name) code) code_files
wenzelm
parents: 64577
diff changeset
   309
        val _ = List.app (fn (name, content) => File.write name content) files
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   310
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   311
        val _ = compile compile_cmd
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   312
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   313
        val (out, res) = Isabelle_System.bash_output run_cmd
64578
wenzelm
parents: 64577
diff changeset
   314
        val _ =
wenzelm
parents: 64577
diff changeset
   315
          if res = 0 then ()
wenzelm
parents: 64577
diff changeset
   316
          else error ("Evaluation for " ^ compilerN ^ " terminated with error code " ^
wenzelm
parents: 64577
diff changeset
   317
            Int.toString res ^ "\nBash output:\n" ^ out)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   318
      in out end
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   319
  in run end
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   320
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   321
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   322
(* driver for PolyML *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   323
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   324
val polymlN = "PolyML"
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   325
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   326
fun mk_driver_polyml _ path _ value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   327
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   328
    val generatedN = "generated.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   329
    val driverN = "driver.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   330
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   331
    val code_path = Path.append path (Path.basic generatedN)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   332
    val driver_path = Path.append path (Path.basic driverN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   333
    val driver =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   334
      "fun main prog_name = \n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   335
      "  let\n" ^
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   336
      "    fun format_term NONE = \"\"\n" ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   337
      "      | format_term (SOME t) = t ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   338
      "    fun format (true, _) = \"" ^ successN ^ "\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   339
      "      | format (false, to) = \"" ^ failureN ^ "\" ^ format_term to ^ \"\\n\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   340
      "    val result = " ^ value_name ^ " ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   341
      "    val _ = print \"" ^ start_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   342
      "    val _ = map (print o format) result;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   343
      "    val _ = print \"" ^ end_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   344
      "  in\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   345
      "    ()\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   346
      "  end;\n"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   347
    val cmd =
67101
60126738b2d0 prefer formal $POLYML_EXE;
wenzelm
parents: 66783
diff changeset
   348
      "\"$POLYML_EXE\" --use " ^ Bash.string (File.platform_path code_path) ^
65898
f02a1289e2c6 proper File.platform_path for poly on Windows;
wenzelm
parents: 65531
diff changeset
   349
      " --use " ^ Bash.string (File.platform_path driver_path) ^
f02a1289e2c6 proper File.platform_path for poly on Windows;
wenzelm
parents: 65531
diff changeset
   350
      " --eval " ^ Bash.string "main ()"
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   351
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   352
    {files = [(driver_path, driver)], compile_cmd = NONE, run_cmd = cmd, mk_code_file = K code_path}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   353
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   354
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   355
fun evaluate_in_polyml ctxt = evaluate mk_driver_polyml NONE polymlN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   356
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   357
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   358
(* driver for mlton *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   359
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   360
val mltonN = "MLton"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   361
val ISABELLE_MLTON = "ISABELLE_MLTON"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   362
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   363
fun mk_driver_mlton _ path _ value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   364
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   365
    val generatedN = "generated.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   366
    val driverN = "driver.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   367
    val projectN = "test"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   368
    val ml_basisN = projectN ^ ".mlb"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   369
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   370
    val code_path = Path.append path (Path.basic generatedN)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   371
    val driver_path = Path.append path (Path.basic driverN)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   372
    val ml_basis_path = Path.append path (Path.basic ml_basisN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   373
    val driver =
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   374
      "fun format_term NONE = \"\"\n" ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   375
      "  | format_term (SOME t) = t ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   376
      "fun format (true, _) = \"" ^ successN ^ "\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   377
      "  | format (false, to) = \"" ^ failureN ^ "\" ^ format_term to ^ \"\\n\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   378
      "val result = " ^ value_name ^ " ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   379
      "val _ = print \"" ^ start_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   380
      "val _ = map (print o format) result;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   381
      "val _ = print \"" ^ end_markerN ^ "\";\n"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   382
    val ml_basis =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   383
      "$(SML_LIB)/basis/basis.mlb\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   384
      generatedN ^ "\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   385
      driverN
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   386
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   387
    val compile_cmd =
62549
9498623b27f0 File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
wenzelm
parents: 61077
diff changeset
   388
      File.bash_path (Path.variable ISABELLE_MLTON) ^
9498623b27f0 File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
wenzelm
parents: 61077
diff changeset
   389
      " -default-type intinf " ^ File.bash_path ml_basis_path
9498623b27f0 File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
wenzelm
parents: 61077
diff changeset
   390
    val run_cmd = File.bash_path (Path.append path (Path.basic projectN))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   391
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   392
    {files = [(driver_path, driver), (ml_basis_path, ml_basis)],
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   393
     compile_cmd = SOME compile_cmd, run_cmd = run_cmd, mk_code_file = K code_path}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   394
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   395
58832
ec9550bd5fd7 make SML/NJ more happy;
wenzelm
parents: 58626
diff changeset
   396
fun evaluate_in_mlton ctxt =
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   397
  evaluate mk_driver_mlton (SOME (ISABELLE_MLTON, "MLton executable")) mltonN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   398
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   399
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   400
(* driver for SML/NJ *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   401
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   402
val smlnjN = "SMLNJ"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   403
val ISABELLE_SMLNJ = "ISABELLE_SMLNJ"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   404
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   405
fun mk_driver_smlnj _ path _ value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   406
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   407
    val generatedN = "generated.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   408
    val driverN = "driver.sml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   409
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   410
    val code_path = Path.append path (Path.basic generatedN)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   411
    val driver_path = Path.append path (Path.basic driverN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   412
    val driver =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   413
      "structure Test = struct\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   414
      "fun main prog_name =\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   415
      "  let\n" ^
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   416
      "    fun format_term NONE = \"\"\n" ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   417
      "      | format_term (SOME t) = t ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   418
      "    fun format (true, _) = \"" ^ successN ^ "\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   419
      "      | format (false, to) = \"" ^ failureN ^ "\" ^ format_term to ^ \"\\n\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   420
      "    val result = " ^ value_name ^ " ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   421
      "    val _ = print \"" ^ start_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   422
      "    val _ = map (print o format) result;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   423
      "    val _ = print \"" ^ end_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   424
      "  in\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   425
      "    0\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   426
      "  end;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   427
      "end;"
65901
e896db33d4ce more robust treatment of generated strings;
wenzelm
parents: 65900
diff changeset
   428
    val ml_source =
e896db33d4ce more robust treatment of generated strings;
wenzelm
parents: 65900
diff changeset
   429
      "Control.MC.matchRedundantError := false; Control.MC.matchRedundantWarn := false;" ^
66783
bbe87f1b5e5d proper File.platform_path for SML/NJ on Windows;
wenzelm
parents: 66284
diff changeset
   430
      "use " ^ ML_Syntax.print_string (Bash.string (File.platform_path code_path)) ^
bbe87f1b5e5d proper File.platform_path for SML/NJ on Windows;
wenzelm
parents: 66284
diff changeset
   431
      "; use " ^ ML_Syntax.print_string (Bash.string (File.platform_path driver_path)) ^
65901
e896db33d4ce more robust treatment of generated strings;
wenzelm
parents: 65900
diff changeset
   432
      "; Test.main ();"
e896db33d4ce more robust treatment of generated strings;
wenzelm
parents: 65900
diff changeset
   433
    val cmd = "echo " ^ Bash.string ml_source ^ " | \"$ISABELLE_SMLNJ\""
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   434
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   435
    {files = [(driver_path, driver)], compile_cmd = NONE, run_cmd = cmd, mk_code_file = K code_path}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   436
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   437
58832
ec9550bd5fd7 make SML/NJ more happy;
wenzelm
parents: 58626
diff changeset
   438
fun evaluate_in_smlnj ctxt =
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   439
  evaluate mk_driver_smlnj (SOME (ISABELLE_SMLNJ, "SMLNJ executable")) smlnjN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   440
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   441
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   442
(* driver for OCaml *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   443
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   444
val ocamlN = "OCaml"
69926
110fff287217 access OCaml tools and libraries via ISABELLE_OCAMLFIND;
wenzelm
parents: 69925
diff changeset
   445
val ISABELLE_OCAMLFIND = "ISABELLE_OCAMLFIND"
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   446
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   447
fun mk_driver_ocaml _ path _ value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   448
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   449
    val generatedN = "generated.ml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   450
    val driverN = "driver.ml"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   451
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   452
    val code_path = Path.append path (Path.basic generatedN)
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   453
    val driver_path = Path.append path (Path.basic driverN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   454
    val driver =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   455
      "let format_term = function\n" ^
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   456
      "  | None -> \"\"\n" ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   457
      "  | Some t -> t ();;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   458
      "let format = function\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   459
      "  | (true, _) -> \"" ^ successN ^ "\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   460
      "  | (false, x) -> \"" ^ failureN ^ "\" ^ format_term x ^ \"\\n\";;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   461
      "let result = " ^ ("Generated." ^ value_name) ^ " ();;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   462
      "let main x =\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   463
      "  let _ = print_string \"" ^ start_markerN ^ "\" in\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   464
      "  let _ = List.map (fun x -> print_string (format x)) result in\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   465
      "  print_string \"" ^ end_markerN ^ "\";;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   466
      "main ();;"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   467
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   468
    val compiled_path = Path.append path (Path.basic "test")
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   469
    val compile_cmd =
69950
dbc2426a600d workaround for the sake of Windows;
wenzelm
parents: 69926
diff changeset
   470
      "\"$ISABELLE_OCAMLFIND\" ocamlopt -w pu -package zarith -linkpkg" ^
69906
55534affe445 migrated from Nums to Zarith as library for OCaml integer arithmetic
haftmann
parents: 69626
diff changeset
   471
      " -o " ^ File.bash_path compiled_path ^ " -I " ^ File.bash_path path ^ " " ^
69950
dbc2426a600d workaround for the sake of Windows;
wenzelm
parents: 69926
diff changeset
   472
      File.bash_path code_path ^ " " ^ File.bash_path driver_path ^ " </dev/null"
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   473
62549
9498623b27f0 File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
wenzelm
parents: 61077
diff changeset
   474
    val run_cmd = File.bash_path compiled_path
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   475
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   476
    {files = [(driver_path, driver)],
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   477
     compile_cmd = SOME compile_cmd, run_cmd = run_cmd, mk_code_file = K code_path}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   478
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   479
58832
ec9550bd5fd7 make SML/NJ more happy;
wenzelm
parents: 58626
diff changeset
   480
fun evaluate_in_ocaml ctxt =
69926
110fff287217 access OCaml tools and libraries via ISABELLE_OCAMLFIND;
wenzelm
parents: 69925
diff changeset
   481
  evaluate mk_driver_ocaml (SOME (ISABELLE_OCAMLFIND, "ocamlfind executable")) ocamlN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   482
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   483
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   484
(* driver for GHC *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   485
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   486
val ghcN = "GHC"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   487
val ISABELLE_GHC = "ISABELLE_GHC"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   488
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   489
val ghc_options = Attrib.setup_config_string \<^binding>\<open>code_test_ghc\<close> (K "")
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   490
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   491
fun mk_driver_ghc ctxt path modules value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   492
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   493
    val driverN = "Main.hs"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   494
69626
0631421c6d6a restored test_code for GHC, which got accidentally broken in ef02c5e051e5
haftmann
parents: 69623
diff changeset
   495
    fun mk_code_file name = Path.append path (Path.basic name)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   496
    val driver_path = Path.append path (Path.basic driverN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   497
    val driver =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   498
      "module Main where {\n" ^
69626
0631421c6d6a restored test_code for GHC, which got accidentally broken in ef02c5e051e5
haftmann
parents: 69623
diff changeset
   499
      String.concat (map (fn module => "import qualified " ^ unsuffix ".hs" module ^ ";\n") modules) ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   500
      "main = do {\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   501
      "    let {\n" ^
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   502
      "      format_term Nothing = \"\";\n" ^
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   503
      "      format_term (Just t) = t ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   504
      "      format (True, _) = \"" ^ successN ^ "\\n\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   505
      "      format (False, to) = \"" ^ failureN ^ "\" ++ format_term to ++ \"\\n\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   506
      "      result = " ^ value_name ^ " ();\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   507
      "    };\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   508
      "    Prelude.putStr \"" ^ start_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   509
      "    Prelude.mapM_ (putStr . format) result;\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   510
      "    Prelude.putStr \"" ^ end_markerN ^ "\";\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   511
      "  }\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   512
      "}\n"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   513
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   514
    val compiled_path = Path.append path (Path.basic "test")
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   515
    val compile_cmd =
65901
e896db33d4ce more robust treatment of generated strings;
wenzelm
parents: 65900
diff changeset
   516
      "\"$ISABELLE_GHC\" " ^ Code_Haskell.language_params ^ " " ^
65905
6181ccb4ec8c support for ISABELLE_GHC on Windows, using the native version (mingw32);
wenzelm
parents: 65904
diff changeset
   517
      Config.get ctxt ghc_options ^ " -o " ^ Bash.string (File.platform_path compiled_path) ^ " " ^
6181ccb4ec8c support for ISABELLE_GHC on Windows, using the native version (mingw32);
wenzelm
parents: 65904
diff changeset
   518
      Bash.string (File.platform_path driver_path) ^ " -i" ^ Bash.string (File.platform_path path)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   519
62549
9498623b27f0 File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
wenzelm
parents: 61077
diff changeset
   520
    val run_cmd = File.bash_path compiled_path
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   521
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   522
    {files = [(driver_path, driver)],
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   523
     compile_cmd = SOME compile_cmd, run_cmd = run_cmd, mk_code_file = mk_code_file}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   524
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   525
58832
ec9550bd5fd7 make SML/NJ more happy;
wenzelm
parents: 58626
diff changeset
   526
fun evaluate_in_ghc ctxt =
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   527
  evaluate mk_driver_ghc (SOME (ISABELLE_GHC, "GHC executable")) ghcN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   528
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   529
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   530
(* driver for Scala *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   531
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   532
val scalaN = "Scala"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   533
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   534
fun mk_driver_scala _ path _ value_name =
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   535
  let
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   536
    val generatedN = "Generated_Code"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   537
    val driverN = "Driver.scala"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   538
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   539
    val code_path = Path.append path (Path.basic (generatedN ^ ".scala"))
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   540
    val driver_path = Path.append path (Path.basic driverN)
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   541
    val driver =
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   542
      "import " ^ generatedN ^ "._\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   543
      "object Test {\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   544
      "  def format_term(x : Option[Unit => String]) : String = x match {\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   545
      "    case None => \"\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   546
      "    case Some(x) => x(())\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   547
      "  }\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   548
      "  def format(term : (Boolean, Option[Unit => String])) : String = term match {\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   549
      "      case (true, _) => \"True\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   550
      "      case (false, x) => \"False\" + format_term(x) + \"\\n\"\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   551
      "  }\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   552
      "  def main(args:Array[String]) = {\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   553
      "    val result = " ^ value_name ^ "(());\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   554
      "    print(\"" ^ start_markerN ^ "\");\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   555
      "    result.map{test:(Boolean, Option[Unit => String]) => print(format(test))};\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   556
      "    print(\"" ^ end_markerN ^ "\");\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   557
      "  }\n" ^
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   558
      "}\n"
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   559
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   560
    val compile_cmd =
65900
d82d1a2e8a4b proper File.platform_path for scala on Windows;
wenzelm
parents: 65898
diff changeset
   561
      "isabelle_scala scalac $ISABELLE_SCALAC_OPTIONS -d " ^ Bash.string (File.platform_path path) ^
d82d1a2e8a4b proper File.platform_path for scala on Windows;
wenzelm
parents: 65898
diff changeset
   562
      " -classpath " ^ Bash.string (File.platform_path path) ^ " " ^
d82d1a2e8a4b proper File.platform_path for scala on Windows;
wenzelm
parents: 65898
diff changeset
   563
      Bash.string (File.platform_path code_path) ^ " " ^
d82d1a2e8a4b proper File.platform_path for scala on Windows;
wenzelm
parents: 65898
diff changeset
   564
      Bash.string (File.platform_path driver_path)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   565
65900
d82d1a2e8a4b proper File.platform_path for scala on Windows;
wenzelm
parents: 65898
diff changeset
   566
    val run_cmd = "isabelle_scala scala -cp " ^ Bash.string (File.platform_path path) ^ " Test"
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   567
  in
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   568
    {files = [(driver_path, driver)],
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   569
     compile_cmd = SOME compile_cmd, run_cmd = run_cmd, mk_code_file = K code_path}
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   570
  end
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   571
64582
3d20ded18f14 unconditional Code_Test_PolyML and Code_Test_Scala: compiler is always present;
wenzelm
parents: 64581
diff changeset
   572
fun evaluate_in_scala ctxt = evaluate mk_driver_scala NONE scalaN ctxt
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   573
64580
wenzelm
parents: 64579
diff changeset
   574
wenzelm
parents: 64579
diff changeset
   575
(* command setup *)
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   576
64577
0288a566c966 tuned whitespace;
wenzelm
parents: 63806
diff changeset
   577
val _ =
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   578
  Outer_Syntax.command \<^command_keyword>\<open>test_code\<close>
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   579
    "compile test cases to target languages, execute them and report results"
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67330
diff changeset
   580
      (Scan.repeat1 Parse.prop -- (\<^keyword>\<open>in\<close> |-- Scan.repeat1 Parse.name)
64580
wenzelm
parents: 64579
diff changeset
   581
        >> (fn (ts, targets) => Toplevel.keep (test_code_cmd ts targets o Toplevel.context_of)))
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   582
66284
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   583
val target_Scala = "Scala_eval"
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   584
val target_Haskell = "Haskell_eval"
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   585
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   586
val _ = Theory.setup 
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   587
   (Code_Target.add_derived_target (target_Scala, [(Code_Scala.target, I)])
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   588
    #> Code_Target.add_derived_target (target_Haskell, [(Code_Haskell.target, I)]))
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   589
64580
wenzelm
parents: 64579
diff changeset
   590
val _ =
wenzelm
parents: 64579
diff changeset
   591
  Theory.setup (fold add_driver
wenzelm
parents: 64579
diff changeset
   592
    [(polymlN, (evaluate_in_polyml, Code_ML.target_SML)),
wenzelm
parents: 64579
diff changeset
   593
     (mltonN, (evaluate_in_mlton, Code_ML.target_SML)),
wenzelm
parents: 64579
diff changeset
   594
     (smlnjN, (evaluate_in_smlnj, Code_ML.target_SML)),
wenzelm
parents: 64579
diff changeset
   595
     (ocamlN, (evaluate_in_ocaml, Code_ML.target_OCaml)),
66284
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   596
     (ghcN, (evaluate_in_ghc, target_Haskell)),
378895354604 new derived targets for evaluating Haskell and Scala programs
Andreas Lochbihler
parents: 65905
diff changeset
   597
     (scalaN, (evaluate_in_scala, target_Scala))]
67330
2505cabfc515 proper namespace for evaluators
haftmann
parents: 67101
diff changeset
   598
  #> fold (fn target => Value_Command.add_evaluator (Binding.name target, eval_term target) #> snd)
64580
wenzelm
parents: 64579
diff changeset
   599
      [polymlN, mltonN, smlnjN, ocamlN, ghcN, scalaN])
59323
468bd3aedfa1 modernized and more uniform style
haftmann
parents: 58832
diff changeset
   600
58039
469a375212c1 add testing framework for generated code
Andreas Lochbihler
parents:
diff changeset
   601
end