| author | wenzelm | 
| Tue, 18 Jul 2023 12:55:43 +0200 | |
| changeset 78393 | a2d22d519bf2 | 
| parent 76884 | a004c5322ea4 | 
| child 78705 | fde0b195cb7d | 
| permissions | -rw-r--r-- | 
| 59720 | 1  | 
(* Title: HOL/Library/code_test.ML  | 
| 64577 | 2  | 
Author: Andreas Lochbihler, ETH Zürich  | 
| 58039 | 3  | 
|
| 64577 | 4  | 
Test infrastructure for the code generator.  | 
| 58039 | 5  | 
*)  | 
6  | 
||
| 64577 | 7  | 
signature CODE_TEST =  | 
8  | 
sig  | 
|
9  | 
val add_driver:  | 
|
10  | 
string * ((Proof.context -> (string * string) list * string -> Path.T -> string) * string) ->  | 
|
11  | 
theory -> theory  | 
|
| 72284 | 12  | 
val debug: bool Config.T  | 
| 64577 | 13  | 
val test_terms: Proof.context -> term list -> string -> unit  | 
| 64580 | 14  | 
val test_code_cmd: string list -> string list -> Proof.context -> unit  | 
| 64577 | 15  | 
val eval_term: string -> Proof.context -> term -> term  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
16  | 
val check_settings: string -> string -> string -> unit  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
17  | 
val compile: string -> string -> unit  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
18  | 
val evaluate: string -> string -> string  | 
| 64577 | 19  | 
val evaluate_in_polyml: Proof.context -> (string * string) list * string -> Path.T -> string  | 
20  | 
val evaluate_in_mlton: Proof.context -> (string * string) list * string -> Path.T -> string  | 
|
21  | 
val evaluate_in_smlnj: Proof.context -> (string * string) list * string -> Path.T -> string  | 
|
22  | 
val evaluate_in_ocaml: Proof.context -> (string * string) list * string -> Path.T -> string  | 
|
23  | 
val ghc_options: string Config.T  | 
|
24  | 
val evaluate_in_ghc: Proof.context -> (string * string) list * string -> Path.T -> string  | 
|
25  | 
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
 | 
26  | 
val target_Scala: string  | 
| 
 
378895354604
new derived targets for evaluating Haskell and Scala programs
 
Andreas Lochbihler 
parents: 
65905 
diff
changeset
 | 
27  | 
val target_Haskell: string  | 
| 58039 | 28  | 
end  | 
29  | 
||
| 64577 | 30  | 
structure Code_Test: CODE_TEST =  | 
31  | 
struct  | 
|
| 58039 | 32  | 
|
33  | 
(* convert a list of terms into nested tuples and back *)  | 
|
| 64577 | 34  | 
|
| 74636 | 35  | 
fun mk_tuples [] = \<^Const>\<open>Unity\<close>  | 
| 58039 | 36  | 
| mk_tuples [t] = t  | 
37  | 
| mk_tuples (t :: ts) = HOLogic.mk_prod (t, mk_tuples ts)  | 
|
38  | 
||
| 74636 | 39  | 
fun dest_tuples \<^Const_>\<open>Pair _ _ for l r\<close> = l :: dest_tuples r  | 
| 58039 | 40  | 
| dest_tuples t = [t]  | 
41  | 
||
42  | 
||
43  | 
fun last_field sep str =  | 
|
44  | 
let  | 
|
| 64577 | 45  | 
val n = size sep  | 
46  | 
val len = size str  | 
|
| 58039 | 47  | 
fun find i =  | 
48  | 
if i < 0 then NONE  | 
|
49  | 
else if String.substring (str, i, n) = sep then SOME i  | 
|
| 64577 | 50  | 
else find (i - 1)  | 
| 58039 | 51  | 
in  | 
52  | 
(case find (len - n) of  | 
|
53  | 
NONE => NONE  | 
|
54  | 
| SOME i => SOME (String.substring (str, 0, i), String.extract (str, i + n, NONE)))  | 
|
| 64577 | 55  | 
end  | 
| 58039 | 56  | 
|
57  | 
fun split_first_last start stop s =  | 
|
| 64577 | 58  | 
(case first_field start s of  | 
59  | 
NONE => NONE  | 
|
60  | 
| SOME (initial, rest) =>  | 
|
61  | 
(case last_field stop rest of  | 
|
62  | 
NONE => NONE  | 
|
63  | 
| SOME (middle, tail) => SOME (initial, middle, tail)))  | 
|
| 58039 | 64  | 
|
| 64577 | 65  | 
|
66  | 
(* data slot for drivers *)  | 
|
| 58039 | 67  | 
|
68  | 
structure Drivers = Theory_Data  | 
|
69  | 
(  | 
|
| 64577 | 70  | 
type T =  | 
71  | 
(string * ((Proof.context -> (string * string) list * string -> Path.T -> string) * string)) list  | 
|
72  | 
val empty = []  | 
|
73  | 
fun merge data : T = AList.merge (op =) (K true) data  | 
|
| 58039 | 74  | 
)  | 
75  | 
||
| 64577 | 76  | 
val add_driver = Drivers.map o AList.update (op =)  | 
77  | 
val get_driver = AList.lookup (op =) o Drivers.get  | 
|
| 58039 | 78  | 
|
79  | 
(*  | 
|
80  | 
Test drivers must produce output of the following format:  | 
|
| 64577 | 81  | 
|
| 72307 | 82  | 
The start of the relevant data is marked with start_marker,  | 
83  | 
its end with end_marker.  | 
|
| 58039 | 84  | 
|
85  | 
Between these two markers, every line corresponds to one test.  | 
|
| 72307 | 86  | 
Lines of successful tests start with success, failures start with failure.  | 
87  | 
The failure failure may continue with the YXML encoding of the evaluated term.  | 
|
| 58039 | 88  | 
There must not be any additional whitespace in between.  | 
89  | 
*)  | 
|
90  | 
||
| 64577 | 91  | 
|
92  | 
(* parsing of results *)  | 
|
| 58039 | 93  | 
|
| 72307 | 94  | 
val success = "True"  | 
95  | 
val failure = "False"  | 
|
96  | 
val start_marker = "*@*Isabelle/Code_Test-start*@*"  | 
|
97  | 
val end_marker = "*@*Isabelle/Code_Test-end*@*"  | 
|
| 58039 | 98  | 
|
99  | 
fun parse_line line =  | 
|
| 72307 | 100  | 
if String.isPrefix success line then (true, NONE)  | 
101  | 
else if String.isPrefix failure line then (false,  | 
|
102  | 
if size line > size failure then  | 
|
103  | 
String.extract (line, size failure, NONE)  | 
|
| 58039 | 104  | 
|> YXML.parse_body  | 
| 
70784
 
799437173553
Term_XML.Encode/Decode.term uses Const "typargs";
 
wenzelm 
parents: 
69950 
diff
changeset
 | 
105  | 
|> Term_XML.Decode.term_raw  | 
| 58039 | 106  | 
|> dest_tuples  | 
107  | 
|> SOME  | 
|
108  | 
else NONE)  | 
|
109  | 
  else raise Fail ("Cannot parse result of evaluation:\n" ^ line)
 | 
|
110  | 
||
111  | 
fun parse_result target out =  | 
|
| 72307 | 112  | 
(case split_first_last start_marker end_marker out of  | 
| 72273 | 113  | 
    NONE => error ("Evaluation failed for " ^ target ^ "!\nCompiler 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
 | 
114  | 
| SOME (_, middle, _) => middle |> trim_split_lines |> map parse_line)  | 
| 58039 | 115  | 
|
| 64577 | 116  | 
|
117  | 
(* pretty printing of test results *)  | 
|
| 58039 | 118  | 
|
119  | 
fun pretty_eval _ NONE _ = []  | 
|
| 64577 | 120  | 
| pretty_eval ctxt (SOME evals) ts =  | 
121  | 
[Pretty.fbrk,  | 
|
122  | 
Pretty.big_list "Evaluated terms"  | 
|
123  | 
(map (fn (t, eval) => Pretty.block  | 
|
124  | 
[Syntax.pretty_term ctxt t, Pretty.brk 1, Pretty.str "=", Pretty.brk 1,  | 
|
125  | 
Syntax.pretty_term ctxt eval])  | 
|
126  | 
(ts ~~ evals))]  | 
|
| 58039 | 127  | 
|
128  | 
fun pretty_failure ctxt target (((_, evals), query), eval_ts) =  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
129  | 
  Pretty.block (Pretty.text ("Test in " ^ target ^ " failed for") @
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
130  | 
[Pretty.brk 1, Pretty.quote (Syntax.pretty_term ctxt query)] @  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
131  | 
pretty_eval ctxt evals eval_ts)  | 
| 58039 | 132  | 
|
133  | 
fun pretty_failures ctxt target failures =  | 
|
134  | 
Pretty.blk (0, Pretty.fbreaks (map (pretty_failure ctxt target) failures))  | 
|
135  | 
||
136  | 
||
| 64577 | 137  | 
(* driver invocation *)  | 
138  | 
||
| 72293 | 139  | 
val debug = Attrib.setup_config_bool \<^binding>\<open>test_code_debug\<close> (K false)  | 
| 58039 | 140  | 
|
| 72284 | 141  | 
fun with_debug_dir name f =  | 
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
142  | 
(Path.explode "$ISABELLE_HOME_USER" + Path.basic (name ^ serial_string ()))  | 
| 72376 | 143  | 
|> Isabelle_System.make_directory  | 
144  | 
|> Exn.capture f  | 
|
145  | 
|> Exn.release;  | 
|
| 58039 | 146  | 
|
147  | 
fun dynamic_value_strict ctxt t compiler =  | 
|
148  | 
let  | 
|
149  | 
val thy = Proof_Context.theory_of ctxt  | 
|
| 64577 | 150  | 
val (driver, target) =  | 
151  | 
(case get_driver thy compiler of  | 
|
152  | 
        NONE => error ("No driver for target " ^ compiler)
 | 
|
| 72272 | 153  | 
| SOME drv => drv)  | 
| 72285 | 154  | 
val with_dir = if Config.get ctxt debug then with_debug_dir else Isabelle_System.with_tmp_dir  | 
| 72274 | 155  | 
fun eval result =  | 
| 
75604
 
39df30349778
more scalable generated files and code export, using Bytes.T;
 
wenzelm 
parents: 
74636 
diff
changeset
 | 
156  | 
with_dir "Code_Test"  | 
| 
 
39df30349778
more scalable generated files and code export, using Bytes.T;
 
wenzelm 
parents: 
74636 
diff
changeset
 | 
157  | 
(driver ctxt ((apfst o map) (apfst Long_Name.implode #> apsnd Bytes.content) result))  | 
| 
69623
 
ef02c5e051e5
explicit model concerning files of generated code
 
haftmann 
parents: 
69597 
diff
changeset
 | 
158  | 
|> parse_result compiler  | 
| 58039 | 159  | 
fun evaluator program _ vs_ty deps =  | 
| 72274 | 160  | 
Exn.interruptible_capture eval  | 
| 64957 | 161  | 
(Code_Target.compilation_text ctxt target program deps true vs_ty)  | 
| 64578 | 162  | 
fun postproc f = map (apsnd (Option.map (map f)))  | 
| 64577 | 163  | 
in Exn.release (Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) evaluator t) end  | 
| 58039 | 164  | 
|
| 64577 | 165  | 
|
166  | 
(* term preprocessing *)  | 
|
| 58039 | 167  | 
|
| 74636 | 168  | 
fun add_eval \<^Const_>\<open>Trueprop for t\<close> = add_eval t  | 
169  | 
| add_eval \<^Const_>\<open>HOL.eq _ for lhs rhs\<close> = (fn acc =>  | 
|
| 64577 | 170  | 
acc  | 
171  | 
|> add_eval rhs  | 
|
172  | 
|> add_eval lhs  | 
|
173  | 
|> cons rhs  | 
|
174  | 
|> cons lhs)  | 
|
| 74636 | 175  | 
| add_eval \<^Const_>\<open>Not for t\<close> = add_eval t  | 
176  | 
| add_eval \<^Const_>\<open>less_eq _ for lhs rhs\<close> = (fn acc => lhs :: rhs :: acc)  | 
|
177  | 
| add_eval \<^Const_>\<open>less _ for lhs rhs\<close> = (fn acc => lhs :: rhs :: acc)  | 
|
| 58039 | 178  | 
| add_eval _ = I  | 
179  | 
||
| 74383 | 180  | 
fun mk_term_of [] = \<^Const>\<open>None \<^typ>\<open>unit \<Rightarrow> yxml_of_term\<close>\<close>  | 
| 58039 | 181  | 
| mk_term_of ts =  | 
| 64577 | 182  | 
let  | 
183  | 
val tuple = mk_tuples ts  | 
|
184  | 
val T = fastype_of tuple  | 
|
185  | 
in  | 
|
| 74636 | 186  | 
\<^Const>\<open>Some \<^typ>\<open>unit \<Rightarrow> yxml_of_term\<close> for  | 
187  | 
\<open>absdummy \<^Type>\<open>unit\<close>  | 
|
188  | 
\<^Const>\<open>yxml_string_of_term for \<^Const>\<open>Code_Evaluation.term_of T for tuple\<close>\<close>\<close>\<close>  | 
|
| 64577 | 189  | 
end  | 
| 58039 | 190  | 
|
191  | 
fun test_terms ctxt ts target =  | 
|
192  | 
let  | 
|
193  | 
val thy = Proof_Context.theory_of ctxt  | 
|
194  | 
||
| 69593 | 195  | 
fun term_of t = Sign.of_sort thy (fastype_of t, \<^sort>\<open>term_of\<close>)  | 
| 58039 | 196  | 
|
| 64577 | 197  | 
fun ensure_bool t =  | 
198  | 
(case fastype_of t of  | 
|
| 74636 | 199  | 
\<^Type>\<open>bool\<close> => ()  | 
| 64579 | 200  | 
| _ =>  | 
201  | 
error (Pretty.string_of  | 
|
202  | 
(Pretty.block [Pretty.str "Test case not of type bool:", Pretty.brk 1,  | 
|
203  | 
Syntax.pretty_term ctxt t])))  | 
|
| 58039 | 204  | 
|
| 64578 | 205  | 
val _ = List.app ensure_bool ts  | 
| 58039 | 206  | 
|
207  | 
val evals = map (fn t => filter term_of (add_eval t [])) ts  | 
|
208  | 
val eval = map mk_term_of evals  | 
|
209  | 
||
| 64578 | 210  | 
val t =  | 
| 69593 | 211  | 
HOLogic.mk_list \<^typ>\<open>bool \<times> (unit \<Rightarrow> yxml_of_term) option\<close>  | 
| 64578 | 212  | 
(map HOLogic.mk_prod (ts ~~ eval))  | 
| 58039 | 213  | 
|
| 64577 | 214  | 
val result = dynamic_value_strict ctxt t target  | 
| 58039 | 215  | 
|
216  | 
val failed =  | 
|
217  | 
filter_out (fst o fst o fst) (result ~~ ts ~~ evals)  | 
|
| 64577 | 218  | 
handle ListPair.UnequalLengths =>  | 
| 72272 | 219  | 
        error ("Evaluation failed!\nWrong number of test results: " ^ string_of_int (length result))
 | 
| 58039 | 220  | 
in  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
221  | 
(case failed of  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
222  | 
[] => ()  | 
| 64578 | 223  | 
| _ => error (Pretty.string_of (pretty_failures ctxt target failed)))  | 
| 58039 | 224  | 
end  | 
225  | 
||
| 64580 | 226  | 
fun test_code_cmd raw_ts targets ctxt =  | 
| 58039 | 227  | 
let  | 
| 64577 | 228  | 
val ts = Syntax.read_terms ctxt raw_ts  | 
| 64579 | 229  | 
val frees = fold Term.add_frees ts []  | 
| 64578 | 230  | 
val _ =  | 
231  | 
if null frees then ()  | 
|
| 64579 | 232  | 
else error (Pretty.string_of  | 
233  | 
(Pretty.block (Pretty.str "Terms contain free variables:" :: Pretty.brk 1 ::  | 
|
| 72283 | 234  | 
Pretty.commas (map (Syntax.pretty_term ctxt o Free) frees))))  | 
235  | 
in List.app (test_terms ctxt ts) targets end  | 
|
| 58039 | 236  | 
|
| 
58348
 
2d47c7d10b62
add target language evaluators for the value command;
 
Andreas Lochbihler 
parents: 
58039 
diff
changeset
 | 
237  | 
fun eval_term target ctxt t =  | 
| 
 
2d47c7d10b62
add target language evaluators for the value command;
 
Andreas Lochbihler 
parents: 
58039 
diff
changeset
 | 
238  | 
let  | 
| 64579 | 239  | 
val frees = Term.add_frees t []  | 
| 64578 | 240  | 
val _ =  | 
241  | 
if null frees then ()  | 
|
| 64579 | 242  | 
else  | 
243  | 
error (Pretty.string_of  | 
|
244  | 
(Pretty.block (Pretty.str "Term contains free variables:" :: Pretty.brk 1 ::  | 
|
| 72283 | 245  | 
Pretty.commas (map (Syntax.pretty_term ctxt o Free) frees))))  | 
| 58039 | 246  | 
|
| 64579 | 247  | 
val T = fastype_of t  | 
| 64578 | 248  | 
val _ =  | 
| 69593 | 249  | 
if Sign.of_sort (Proof_Context.theory_of ctxt) (T, \<^sort>\<open>term_of\<close>) then ()  | 
| 64579 | 250  | 
      else error ("Type " ^ Syntax.string_of_typ ctxt T ^
 | 
| 69593 | 251  | 
" of term not of sort " ^ Syntax.string_of_sort ctxt \<^sort>\<open>term_of\<close>)  | 
| 58039 | 252  | 
|
| 64578 | 253  | 
val t' =  | 
| 69593 | 254  | 
HOLogic.mk_list \<^typ>\<open>bool \<times> (unit \<Rightarrow> yxml_of_term) option\<close>  | 
| 74636 | 255  | 
[HOLogic.mk_prod (\<^Const>\<open>False\<close>, mk_term_of [t])]  | 
| 58039 | 256  | 
|
| 64577 | 257  | 
val result = dynamic_value_strict ctxt t' target  | 
258  | 
in (case result of [(_, SOME [t])] => t | _ => error "Evaluation failed") end  | 
|
| 58039 | 259  | 
|
| 64577 | 260  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
261  | 
(* check and invoke compiler *)  | 
| 58039 | 262  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
263  | 
fun check_settings compiler var descr =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
264  | 
if getenv var = "" then  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
265  | 
error (Pretty.string_of (Pretty.para  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
266  | 
      ("Environment variable " ^ var ^ " is not set. To test code generation with " ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
267  | 
compiler ^ ", set this variable to your " ^ descr ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
268  | 
" in the $ISABELLE_HOME_USER/etc/settings file.")))  | 
| 72306 | 269  | 
else ()  | 
| 58039 | 270  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
271  | 
fun compile compiler cmd =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
272  | 
let val (out, ret) = Isabelle_System.bash_output cmd in  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
273  | 
if ret = 0 then ()  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
274  | 
    else error ("Compilation with " ^ compiler ^ " failed:\n" ^ cmd ^ "\n" ^ out)
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
275  | 
end  | 
| 58039 | 276  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
277  | 
fun evaluate compiler cmd =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
278  | 
let val (out, res) = Isabelle_System.bash_output cmd in  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
279  | 
if res = 0 then out  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
280  | 
    else error ("Evaluation for " ^ compiler ^ " terminated with error code " ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
281  | 
string_of_int res ^ "\nCompiler output:\n" ^ out)  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
282  | 
end  | 
| 58039 | 283  | 
|
| 64577 | 284  | 
|
285  | 
(* driver for PolyML *)  | 
|
| 58039 | 286  | 
|
| 64577 | 287  | 
val polymlN = "PolyML"  | 
| 58039 | 288  | 
|
| 72297 | 289  | 
fun evaluate_in_polyml (_: Proof.context) (code_files, value_name) dir =  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
290  | 
let  | 
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
291  | 
val code_path = dir + Path.basic "generated.sml"  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
292  | 
val driver_path = dir + Path.basic "driver.sml"  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
293  | 
val out_path = dir + Path.basic "out"  | 
| 72297 | 294  | 
|
| 72306 | 295  | 
val code = #2 (the_single code_files)  | 
| 72286 | 296  | 
val driver = \<^verbatim>\<open>  | 
| 72290 | 297  | 
fun main () =  | 
| 72286 | 298  | 
let  | 
| 72307 | 299  | 
fun format (true, _) = \<close> ^ ML_Syntax.print_string success ^ \<^verbatim>\<open> ^ "\n"  | 
300  | 
| format (false, NONE) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ "\n"  | 
|
301  | 
| format (false, SOME t) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ t () ^ "\n"  | 
|
| 72286 | 302  | 
val result = \<close> ^ value_name ^ \<^verbatim>\<open> ()  | 
303  | 
val result_text = \<close> ^  | 
|
| 72307 | 304  | 
ML_Syntax.print_string start_marker ^  | 
| 72286 | 305  | 
\<^verbatim>\<open> ^ String.concat (map format result) ^ \<close> ^  | 
| 72307 | 306  | 
ML_Syntax.print_string end_marker ^ \<^verbatim>\<open>  | 
| 72288 | 307  | 
val out = BinIO.openOut \<close> ^ ML_Syntax.print_platform_path out_path ^ \<^verbatim>\<open>  | 
| 72286 | 308  | 
val _ = BinIO.output (out, Byte.stringToBytes result_text)  | 
309  | 
val _ = BinIO.closeOut out  | 
|
310  | 
in () end;  | 
|
311  | 
\<close>  | 
|
| 72306 | 312  | 
val _ = File.write code_path code  | 
313  | 
val _ = File.write driver_path driver  | 
|
314  | 
val _ =  | 
|
315  | 
ML_Context.eval  | 
|
316  | 
        {environment = ML_Env.SML, redirect = false, verbose = false, debug = NONE,
 | 
|
317  | 
writeln = writeln, warning = warning}  | 
|
318  | 
Position.none  | 
|
| 76884 | 319  | 
(ML_Lex.read_text (code, Position.file (File.symbolic_path code_path)) @  | 
320  | 
ML_Lex.read_text (driver, Position.file (File.symbolic_path driver_path)) @  | 
|
| 72306 | 321  | 
ML_Lex.read "main ()")  | 
| 72308 | 322  | 
      handle ERROR msg => error ("Evaluation for " ^ polymlN ^ " failed:\n" ^ msg)
 | 
| 72306 | 323  | 
in File.read out_path end  | 
| 58039 | 324  | 
|
| 64577 | 325  | 
|
326  | 
(* driver for mlton *)  | 
|
| 58039 | 327  | 
|
328  | 
val mltonN = "MLton"  | 
|
329  | 
val ISABELLE_MLTON = "ISABELLE_MLTON"  | 
|
330  | 
||
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
331  | 
fun evaluate_in_mlton (_: Proof.context) (code_files, value_name) dir =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
332  | 
let  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
333  | 
val compiler = mltonN  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
334  | 
val generatedN = "generated.sml"  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
335  | 
val driverN = "driver.sml"  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
336  | 
val projectN = "test"  | 
| 58039 | 337  | 
|
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
338  | 
val code_path = dir + Path.basic generatedN  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
339  | 
val driver_path = dir + Path.basic driverN  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
340  | 
val basis_path = dir + Path.basic (projectN ^ ".mlb")  | 
| 72291 | 341  | 
val driver = \<^verbatim>\<open>  | 
| 72307 | 342  | 
fun format (true, _) = \<close> ^ ML_Syntax.print_string success ^ \<^verbatim>\<open> ^ "\n"  | 
343  | 
| format (false, NONE) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ "\n"  | 
|
344  | 
| format (false, SOME t) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ t () ^ "\n"  | 
|
| 72291 | 345  | 
val result = \<close> ^ value_name ^ \<^verbatim>\<open> ()  | 
| 72307 | 346  | 
val _ = print \<close> ^ ML_Syntax.print_string start_marker ^ \<^verbatim>\<open>  | 
| 72291 | 347  | 
val _ = List.app (print o format) result  | 
| 72307 | 348  | 
val _ = print \<close> ^ ML_Syntax.print_string end_marker ^ \<^verbatim>\<open>  | 
| 72291 | 349  | 
\<close>  | 
| 72306 | 350  | 
val _ = check_settings compiler ISABELLE_MLTON "MLton executable"  | 
351  | 
val _ = List.app (File.write code_path o snd) code_files  | 
|
352  | 
val _ = File.write driver_path driver  | 
|
353  | 
    val _ = File.write basis_path ("$(SML_LIB)/basis/basis.mlb\n" ^ generatedN ^ "\n" ^ driverN)
 | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
354  | 
in  | 
| 
76181
 
d27ed188e0c4
support for ISABELLE_MLTON_OPTIONS, notably for Ubuntu 22.04 with external mlton executable;
 
wenzelm 
parents: 
75654 
diff
changeset
 | 
355  | 
compile compiler  | 
| 
 
d27ed188e0c4
support for ISABELLE_MLTON_OPTIONS, notably for Ubuntu 22.04 with external mlton executable;
 
wenzelm 
parents: 
75654 
diff
changeset
 | 
356  | 
(\<^verbatim>\<open>"$ISABELLE_MLTON" $ISABELLE_MLTON_OPTIONS -default-type intinf \<close> ^  | 
| 
 
d27ed188e0c4
support for ISABELLE_MLTON_OPTIONS, notably for Ubuntu 22.04 with external mlton executable;
 
wenzelm 
parents: 
75654 
diff
changeset
 | 
357  | 
File.bash_platform_path basis_path);  | 
| 
 
d27ed188e0c4
support for ISABELLE_MLTON_OPTIONS, notably for Ubuntu 22.04 with external mlton executable;
 
wenzelm 
parents: 
75654 
diff
changeset
 | 
358  | 
evaluate compiler (File.bash_platform_path (dir + Path.basic projectN))  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
359  | 
end  | 
| 58039 | 360  | 
|
| 64577 | 361  | 
|
362  | 
(* driver for SML/NJ *)  | 
|
| 58039 | 363  | 
|
364  | 
val smlnjN = "SMLNJ"  | 
|
365  | 
val ISABELLE_SMLNJ = "ISABELLE_SMLNJ"  | 
|
366  | 
||
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
367  | 
fun evaluate_in_smlnj (_: Proof.context) (code_files, value_name) dir =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
368  | 
let  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
369  | 
val compiler = smlnjN  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
370  | 
val generatedN = "generated.sml"  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
371  | 
val driverN = "driver.sml"  | 
| 58039 | 372  | 
|
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
373  | 
val code_path = dir + Path.basic generatedN  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
374  | 
val driver_path = dir + Path.basic driverN  | 
| 72291 | 375  | 
val driver = \<^verbatim>\<open>  | 
376  | 
structure Test =  | 
|
377  | 
struct  | 
|
378  | 
fun main () =  | 
|
379  | 
let  | 
|
| 72307 | 380  | 
fun format (true, _) = \<close> ^ ML_Syntax.print_string success ^ \<^verbatim>\<open> ^ "\n"  | 
381  | 
| format (false, NONE) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ "\n"  | 
|
382  | 
| format (false, SOME t) = \<close> ^ ML_Syntax.print_string failure ^ \<^verbatim>\<open> ^ t () ^ "\n"  | 
|
| 72291 | 383  | 
val result = \<close> ^ value_name ^ \<^verbatim>\<open> ()  | 
| 72307 | 384  | 
val _ = print \<close> ^ ML_Syntax.print_string start_marker ^ \<^verbatim>\<open>  | 
| 72291 | 385  | 
val _ = List.app (print o format) result  | 
| 72307 | 386  | 
val _ = print \<close> ^ ML_Syntax.print_string end_marker ^ \<^verbatim>\<open>  | 
| 72291 | 387  | 
in 0 end  | 
388  | 
end  | 
|
389  | 
\<close>  | 
|
| 72306 | 390  | 
val _ = check_settings compiler ISABELLE_SMLNJ "SMLNJ executable"  | 
391  | 
val _ = List.app (File.write code_path o snd) code_files  | 
|
392  | 
val _ = File.write driver_path driver  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
393  | 
val ml_source =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
394  | 
"Control.MC.matchRedundantError := false; Control.MC.matchRedundantWarn := false;" ^  | 
| 72277 | 395  | 
"use " ^ ML_Syntax.print_string (File.platform_path code_path) ^  | 
396  | 
"; use " ^ ML_Syntax.print_string (File.platform_path driver_path) ^  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
397  | 
"; Test.main ();"  | 
| 72306 | 398  | 
  in evaluate compiler ("echo " ^ Bash.string ml_source ^ " | \"$ISABELLE_SMLNJ\"") end
 | 
| 58039 | 399  | 
|
| 64577 | 400  | 
|
401  | 
(* driver for OCaml *)  | 
|
| 58039 | 402  | 
|
403  | 
val ocamlN = "OCaml"  | 
|
| 
69926
 
110fff287217
access OCaml tools and libraries via ISABELLE_OCAMLFIND;
 
wenzelm 
parents: 
69925 
diff
changeset
 | 
404  | 
val ISABELLE_OCAMLFIND = "ISABELLE_OCAMLFIND"  | 
| 58039 | 405  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
406  | 
fun evaluate_in_ocaml (_: Proof.context) (code_files, value_name) dir =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
407  | 
let  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
408  | 
val compiler = ocamlN  | 
| 58039 | 409  | 
|
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
410  | 
val code_path = dir + Path.basic "generated.ml"  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
411  | 
val driver_path = dir + Path.basic "driver.ml"  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
412  | 
val driver =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
413  | 
"let format_term = function\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
414  | 
" | None -> \"\"\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
415  | 
" | Some t -> t ();;\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
416  | 
"let format = function\n" ^  | 
| 72307 | 417  | 
" | (true, _) -> \"" ^ success ^ "\\n\"\n" ^  | 
418  | 
" | (false, x) -> \"" ^ failure ^ "\" ^ format_term x ^ \"\\n\";;\n" ^  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
419  | 
      "let result = " ^ ("Generated." ^ value_name) ^ " ();;\n" ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
420  | 
"let main x =\n" ^  | 
| 72307 | 421  | 
" let _ = print_string \"" ^ start_marker ^ "\" in\n" ^  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
422  | 
" let _ = List.map (fun x -> print_string (format x)) result in\n" ^  | 
| 72307 | 423  | 
" print_string \"" ^ end_marker ^ "\";;\n" ^  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
424  | 
"main ();;"  | 
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
425  | 
val compiled_path = dir + Path.basic "test"  | 
| 72306 | 426  | 
|
427  | 
val _ = check_settings compiler ISABELLE_OCAMLFIND "ocamlfind executable"  | 
|
428  | 
val _ = List.app (File.write code_path o snd) code_files  | 
|
429  | 
val _ = File.write driver_path driver  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
430  | 
val cmd =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
431  | 
"\"$ISABELLE_OCAMLFIND\" ocamlopt -w pu -package zarith -linkpkg" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
432  | 
" -o " ^ File.bash_path compiled_path ^ " -I " ^ File.bash_path dir ^ " " ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
433  | 
File.bash_path code_path ^ " " ^ File.bash_path driver_path ^ " </dev/null"  | 
| 72306 | 434  | 
in compile compiler cmd; evaluate compiler (File.bash_path compiled_path) end  | 
| 58039 | 435  | 
|
| 64577 | 436  | 
|
437  | 
(* driver for GHC *)  | 
|
| 58039 | 438  | 
|
439  | 
val ghcN = "GHC"  | 
|
440  | 
val ISABELLE_GHC = "ISABELLE_GHC"  | 
|
441  | 
||
| 69593 | 442  | 
val ghc_options = Attrib.setup_config_string \<^binding>\<open>code_test_ghc\<close> (K "")  | 
| 58039 | 443  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
444  | 
fun evaluate_in_ghc ctxt (code_files, value_name) dir =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
445  | 
let  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
446  | 
val compiler = ghcN  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
447  | 
val modules = map fst code_files  | 
| 58039 | 448  | 
|
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
449  | 
val driver_path = dir + Path.basic "Main.hs"  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
450  | 
val driver =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
451  | 
      "module Main where {\n" ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
452  | 
implode (map (fn module => "import qualified " ^ unsuffix ".hs" module ^ ";\n") modules) ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
453  | 
      "main = do {\n" ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
454  | 
      "    let {\n" ^
 | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
455  | 
" format_term Nothing = \"\";\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
456  | 
" format_term (Just t) = t ();\n" ^  | 
| 72307 | 457  | 
" format (True, _) = \"" ^ success ^ "\\n\";\n" ^  | 
458  | 
" format (False, to) = \"" ^ failure ^ "\" ++ format_term to ++ \"\\n\";\n" ^  | 
|
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
459  | 
" result = " ^ value_name ^ " ();\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
460  | 
" };\n" ^  | 
| 72307 | 461  | 
" Prelude.putStr \"" ^ start_marker ^ "\";\n" ^  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
462  | 
" Prelude.mapM_ (putStr . format) result;\n" ^  | 
| 72307 | 463  | 
" Prelude.putStr \"" ^ end_marker ^ "\";\n" ^  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
464  | 
" }\n" ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
465  | 
"}\n"  | 
| 58039 | 466  | 
|
| 72306 | 467  | 
val _ = check_settings compiler ISABELLE_GHC "GHC executable"  | 
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
468  | 
val _ = List.app (fn (name, code) => File.write (dir + Path.basic name) code) code_files  | 
| 72306 | 469  | 
val _ = File.write driver_path driver  | 
470  | 
||
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
471  | 
val compiled_path = dir + Path.basic "test"  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
472  | 
val cmd =  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
473  | 
"\"$ISABELLE_GHC\" " ^ Code_Haskell.language_params ^ " " ^  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
474  | 
Config.get ctxt ghc_options ^ " -o " ^  | 
| 72278 | 475  | 
File.bash_platform_path compiled_path ^ " " ^  | 
476  | 
File.bash_platform_path driver_path ^ " -i" ^  | 
|
477  | 
File.bash_platform_path dir  | 
|
| 72306 | 478  | 
in compile compiler cmd; evaluate compiler (File.bash_path compiled_path) end  | 
| 58039 | 479  | 
|
| 64577 | 480  | 
|
481  | 
(* driver for Scala *)  | 
|
| 58039 | 482  | 
|
483  | 
val scalaN = "Scala"  | 
|
484  | 
||
| 72297 | 485  | 
fun evaluate_in_scala (_: Proof.context) (code_files, value_name) dir =  | 
| 
72276
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
486  | 
let  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
487  | 
val generatedN = "Generated_Code"  | 
| 
 
dfe150a246e6
misc tuning and clarification: prefer functions over data;
 
wenzelm 
parents: 
72275 
diff
changeset
 | 
488  | 
val driverN = "Driver.scala"  | 
| 58039 | 489  | 
|
| 
72511
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
490  | 
val code_path = dir + Path.basic (generatedN ^ ".scala")  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
491  | 
val driver_path = dir + Path.basic driverN  | 
| 
 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 
wenzelm 
parents: 
72376 
diff
changeset
 | 
492  | 
val out_path = dir + Path.basic "out"  | 
| 72297 | 493  | 
|
| 72306 | 494  | 
val code = #2 (the_single code_files)  | 
| 72296 | 495  | 
val driver = \<^verbatim>\<open>  | 
496  | 
{
 | 
|
497  | 
val result = \<close> ^ value_name ^ \<^verbatim>\<open>(())  | 
|
498  | 
val result_text =  | 
|
499  | 
result.map(  | 
|
500  | 
      {
 | 
|
501  | 
case (true, _) => "True\n"  | 
|
502  | 
case (false, None) => "False\n"  | 
|
503  | 
case (false, Some(t)) => "False" + t(()) + "\n"  | 
|
504  | 
}).mkString  | 
|
505  | 
isabelle.File.write(  | 
|
| 76882 | 506  | 
isabelle.Path.explode(\<close> ^ quote (File.standard_path out_path) ^ \<^verbatim>\<open>),  | 
| 72307 | 507  | 
\<close> ^ quote start_marker ^ \<^verbatim>\<open> + result_text + \<close> ^ quote end_marker ^ \<^verbatim>\<open>)  | 
| 72296 | 508  | 
}\<close>  | 
| 72306 | 509  | 
val _ = File.write code_path code  | 
510  | 
val _ = File.write driver_path driver  | 
|
| 75654 | 511  | 
val _ = Scala_Compiler.toplevel (code ^ driver)  | 
| 72308 | 512  | 
      handle ERROR msg => error ("Evaluation for " ^ scalaN ^ " failed:\n" ^ msg)
 | 
| 72306 | 513  | 
in File.read out_path end  | 
| 58039 | 514  | 
|
| 64580 | 515  | 
|
516  | 
(* command setup *)  | 
|
| 58039 | 517  | 
|
| 64577 | 518  | 
val _ =  | 
| 69593 | 519  | 
Outer_Syntax.command \<^command_keyword>\<open>test_code\<close>  | 
| 58039 | 520  | 
"compile test cases to target languages, execute them and report results"  | 
| 69593 | 521  | 
(Scan.repeat1 Parse.prop -- (\<^keyword>\<open>in\<close> |-- Scan.repeat1 Parse.name)  | 
| 64580 | 522  | 
>> (fn (ts, targets) => Toplevel.keep (test_code_cmd ts targets o Toplevel.context_of)))  | 
| 58039 | 523  | 
|
| 
66284
 
378895354604
new derived targets for evaluating Haskell and Scala programs
 
Andreas Lochbihler 
parents: 
65905 
diff
changeset
 | 
524  | 
val target_Scala = "Scala_eval"  | 
| 
 
378895354604
new derived targets for evaluating Haskell and Scala programs
 
Andreas Lochbihler 
parents: 
65905 
diff
changeset
 | 
525  | 
val target_Haskell = "Haskell_eval"  | 
| 
 
378895354604
new derived targets for evaluating Haskell and Scala programs
 
Andreas Lochbihler 
parents: 
65905 
diff
changeset
 | 
526  | 
|
| 64580 | 527  | 
val _ =  | 
| 72306 | 528  | 
Theory.setup  | 
529  | 
(Code_Target.add_derived_target (target_Scala, [(Code_Scala.target, I)]) #>  | 
|
530  | 
Code_Target.add_derived_target (target_Haskell, [(Code_Haskell.target, I)]) #>  | 
|
531  | 
fold add_driver  | 
|
532  | 
[(polymlN, (evaluate_in_polyml, Code_ML.target_SML)),  | 
|
533  | 
(mltonN, (evaluate_in_mlton, Code_ML.target_SML)),  | 
|
534  | 
(smlnjN, (evaluate_in_smlnj, Code_ML.target_SML)),  | 
|
535  | 
(ocamlN, (evaluate_in_ocaml, Code_ML.target_OCaml)),  | 
|
536  | 
(ghcN, (evaluate_in_ghc, target_Haskell)),  | 
|
537  | 
(scalaN, (evaluate_in_scala, target_Scala))] #>  | 
|
538  | 
fold (fn target => Value_Command.add_evaluator (Binding.name target, eval_term target) #> #2)  | 
|
| 64580 | 539  | 
[polymlN, mltonN, smlnjN, ocamlN, ghcN, scalaN])  | 
| 59323 | 540  | 
|
| 58039 | 541  | 
end  |