189 val with_dir = if debug then with_overlord_dir else Isabelle_System.with_tmp_dir |
186 val with_dir = if debug then with_overlord_dir else Isabelle_System.with_tmp_dir |
190 fun evaluate f = with_dir "Code_Test" (driver ctxt f) |> parse_result compiler |
187 fun evaluate f = with_dir "Code_Test" (driver ctxt f) |> parse_result compiler |
191 fun evaluator program _ vs_ty deps = |
188 fun evaluator program _ vs_ty deps = |
192 Exn.interruptible_capture evaluate |
189 Exn.interruptible_capture evaluate |
193 (Code_Target.computation_text ctxt target program deps true vs_ty) |
190 (Code_Target.computation_text ctxt target program deps true vs_ty) |
194 fun postproc f = map (apsnd (map_option (map f))) |
191 fun postproc f = map (apsnd (Option.map (map f))) |
195 in Exn.release (Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) evaluator t) end |
192 in Exn.release (Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) evaluator t) end |
196 |
193 |
197 |
194 |
198 (* term preprocessing *) |
195 (* term preprocessing *) |
199 |
196 |
231 fun ensure_bool t = |
228 fun ensure_bool t = |
232 (case fastype_of t of |
229 (case fastype_of t of |
233 @{typ bool} => () |
230 @{typ bool} => () |
234 | _ => error ("Test case not of type bool: " ^ Pretty.string_of (Syntax.pretty_term ctxt t))) |
231 | _ => error ("Test case not of type bool: " ^ Pretty.string_of (Syntax.pretty_term ctxt t))) |
235 |
232 |
236 val _ = map ensure_bool ts |
233 val _ = List.app ensure_bool ts |
237 |
234 |
238 val evals = map (fn t => filter term_of (add_eval t [])) ts |
235 val evals = map (fn t => filter term_of (add_eval t [])) ts |
239 val eval = map mk_term_of evals |
236 val eval = map mk_term_of evals |
240 |
237 |
241 val T = |
238 val t = |
242 HOLogic.mk_prodT (@{typ bool}, |
239 HOLogic.mk_list @{typ "bool \<times> (unit \<Rightarrow> yxml_of_term) option"} |
243 Type (@{type_name option}, [@{typ unit} --> @{typ yxml_of_term}])) |
240 (map HOLogic.mk_prod (ts ~~ eval)) |
244 val t = HOLogic.mk_list T (map HOLogic.mk_prod (ts ~~ eval)) |
|
245 |
241 |
246 val result = dynamic_value_strict ctxt t target |
242 val result = dynamic_value_strict ctxt t target |
247 |
243 |
248 val failed = |
244 val failed = |
249 filter_out (fst o fst o fst) (result ~~ ts ~~ evals) |
245 filter_out (fst o fst o fst) (result ~~ ts ~~ evals) |
250 handle ListPair.UnequalLengths => |
246 handle ListPair.UnequalLengths => |
251 error ("Evaluation failed!\nWrong number of test results: " ^ Int.toString (length result)) |
247 error ("Evaluation failed!\nWrong number of test results: " ^ Int.toString (length result)) |
252 val _ = case failed of [] => () |
248 in |
253 | _ => error (Pretty.string_of (pretty_failures ctxt target failed)) |
249 (case failed of [] => |
254 in |
250 () |
255 () |
251 | _ => error (Pretty.string_of (pretty_failures ctxt target failed))) |
256 end |
252 end |
257 |
253 |
258 fun test_targets ctxt = map o test_terms ctxt |
254 fun test_targets ctxt = List.app o test_terms ctxt |
259 |
255 |
260 fun test_code_cmd raw_ts targets state = |
256 fun test_code_cmd raw_ts targets state = |
261 let |
257 let |
262 val ctxt = Toplevel.context_of state |
258 val ctxt = Toplevel.context_of state |
263 val ts = Syntax.read_terms ctxt raw_ts |
259 val ts = Syntax.read_terms ctxt raw_ts |
264 val frees = fold Term.add_free_names ts [] |
260 val frees = fold Term.add_free_names ts [] |
265 val _ = if frees = [] then () else |
261 val _ = |
266 error ("Terms contain free variables: " ^ |
262 if null frees then () |
267 Pretty.string_of (Pretty.block (Pretty.commas (map Pretty.str frees)))) |
263 else error ("Terms contain free variables: " ^ |
268 in |
264 Pretty.string_of (Pretty.block (Pretty.commas (map Pretty.str frees)))) |
269 test_targets ctxt ts targets; () |
265 in test_targets ctxt ts targets end |
270 end |
|
271 |
266 |
272 fun eval_term target ctxt t = |
267 fun eval_term target ctxt t = |
273 let |
268 let |
274 val frees = Term.add_free_names t [] |
269 val frees = Term.add_free_names t [] |
275 val _ = if frees = [] then () else |
270 val _ = |
276 error ("Term contains free variables: " ^ |
271 if null frees then () |
277 Pretty.string_of (Pretty.block (Pretty.commas (map Pretty.str frees)))) |
272 else error ("Term contains free variables: " ^ |
|
273 Pretty.string_of (Pretty.block (Pretty.commas (map Pretty.str frees)))) |
278 |
274 |
279 val thy = Proof_Context.theory_of ctxt |
275 val thy = Proof_Context.theory_of ctxt |
280 |
276 |
281 val T_t = fastype_of t |
277 val T_t = fastype_of t |
282 val _ = if Sign.of_sort thy (T_t, @{sort term_of}) then () else error |
278 val _ = |
283 ("Type " ^ Pretty.string_of (Syntax.pretty_typ ctxt T_t) ^ |
279 if Sign.of_sort thy (T_t, @{sort term_of}) then () |
|
280 else error ("Type " ^ Pretty.string_of (Syntax.pretty_typ ctxt T_t) ^ |
284 " of term not of sort " ^ Pretty.string_of (Syntax.pretty_sort ctxt @{sort term_of})) |
281 " of term not of sort " ^ Pretty.string_of (Syntax.pretty_sort ctxt @{sort term_of})) |
285 |
282 |
286 val T = HOLogic.mk_prodT (@{typ bool}, Type (@{type_name option}, [@{typ unit} --> @{typ yxml_of_term}])) |
283 val t' = |
287 val t' = HOLogic.mk_list T [HOLogic.mk_prod (@{term "False"}, mk_term_of [t])] |
284 HOLogic.mk_list @{typ "bool \<times> (unit \<Rightarrow> yxml_of_term) option"} |
|
285 [HOLogic.mk_prod (@{term "False"}, mk_term_of [t])] |
288 |
286 |
289 val result = dynamic_value_strict ctxt t' target |
287 val result = dynamic_value_strict ctxt t' target |
290 in (case result of [(_, SOME [t])] => t | _ => error "Evaluation failed") end |
288 in (case result of [(_, SOME [t])] => t | _ => error "Evaluation failed") end |
291 |
289 |
292 |
290 |
296 let |
294 let |
297 val compiler = getenv env_var |
295 val compiler = getenv env_var |
298 val _ = |
296 val _ = |
299 if compiler <> "" then () |
297 if compiler <> "" then () |
300 else error (Pretty.string_of (Pretty.para |
298 else error (Pretty.string_of (Pretty.para |
301 ("Environment variable " ^ env_var ^ " is not set. To test code generation with " ^ |
299 ("Environment variable " ^ env_var ^ " is not set. To test code generation with " ^ |
302 compilerN ^ ", set this variable to your " ^ env_var_dest ^ " in the settings file."))) |
300 compilerN ^ ", set this variable to your " ^ env_var_dest ^ " in the settings file."))) |
303 |
301 |
304 fun compile NONE = () |
302 fun compile NONE = () |
305 | compile (SOME cmd) = |
303 | compile (SOME cmd) = |
306 let |
304 let |
307 val (out, ret) = Isabelle_System.bash_output cmd |
305 val (out, ret) = Isabelle_System.bash_output cmd |
308 in |
306 in |
309 if ret = 0 then () else error |
307 if ret = 0 then () |
310 ("Compilation with " ^ compilerN ^ " failed:\n" ^ cmd ^ "\n" ^ out) |
308 else error ("Compilation with " ^ compilerN ^ " failed:\n" ^ cmd ^ "\n" ^ out) |
311 end |
309 end |
312 |
310 |
313 fun run path = |
311 fun run path = |
314 let |
312 let |
315 val modules = map fst code_files |
313 val modules = map fst code_files |
316 val {files, compile_cmd, run_cmd, mk_code_file} = mk_driver ctxt path modules value_name |
314 val {files, compile_cmd, run_cmd, mk_code_file} = mk_driver ctxt path modules value_name |
317 |
315 |
318 val _ = map (fn (name, code) => File.write (mk_code_file name) code) code_files |
316 val _ = List.app (fn (name, code) => File.write (mk_code_file name) code) code_files |
319 val _ = map (fn (name, content) => File.write name content) files |
317 val _ = List.app (fn (name, content) => File.write name content) files |
320 |
318 |
321 val _ = compile compile_cmd |
319 val _ = compile compile_cmd |
322 |
320 |
323 val (out, res) = Isabelle_System.bash_output run_cmd |
321 val (out, res) = Isabelle_System.bash_output run_cmd |
324 val _ = if res = 0 then () else error |
322 val _ = |
325 ("Evaluation for " ^ compilerN ^ " terminated with error code " ^ Int.toString res ^ |
323 if res = 0 then () |
326 "\nBash output:\n" ^ out) |
324 else error ("Evaluation for " ^ compilerN ^ " terminated with error code " ^ |
|
325 Int.toString res ^ "\nBash output:\n" ^ out) |
327 in out end |
326 in out end |
328 in run end |
327 in run end |
329 |
328 |
330 |
329 |
331 (* driver for PolyML *) |
330 (* driver for PolyML *) |