199 {size = size, iterations = iterations, |
199 {size = size, iterations = iterations, |
200 default_type = SOME (Sign.read_typ thy s)}; |
200 default_type = SOME (Sign.read_typ thy s)}; |
201 |
201 |
202 (* data kind 'Pure/codegen' *) |
202 (* data kind 'Pure/codegen' *) |
203 |
203 |
|
204 structure CodeData = CodegenData; |
|
205 |
204 structure CodegenData = TheoryDataFun |
206 structure CodegenData = TheoryDataFun |
205 (struct |
207 (struct |
206 val name = "Pure/codegen"; |
208 val name = "Pure/codegen"; |
207 type T = |
209 type T = |
208 {codegens : (string * term codegen) list, |
210 {codegens : (string * term codegen) list, |
295 test_params = test_params} thy |
297 test_params = test_params} thy |
296 | SOME _ => error ("Code generator " ^ name ^ " already declared")) |
298 | SOME _ => error ("Code generator " ^ name ^ " already declared")) |
297 end; |
299 end; |
298 |
300 |
299 |
301 |
|
302 (**** preprocessors ****) |
|
303 |
|
304 fun add_preprocessor p thy = |
|
305 let val {codegens, tycodegens, consts, types, attrs, preprocs, modules, test_params} = |
|
306 CodegenData.get thy |
|
307 in CodegenData.put {tycodegens = tycodegens, |
|
308 codegens = codegens, consts = consts, types = types, |
|
309 attrs = attrs, preprocs = (stamp (), p) :: preprocs, |
|
310 modules = modules, test_params = test_params} thy |
|
311 end; |
|
312 |
|
313 fun preprocess thy = |
|
314 let val {preprocs, ...} = CodegenData.get thy |
|
315 in fold (fn (_, f) => f thy) preprocs end; |
|
316 |
|
317 fun preprocess_term thy t = |
|
318 let |
|
319 val x = Free (Name.variant (add_term_names (t, [])) "x", fastype_of t); |
|
320 (* fake definition *) |
|
321 val eq = setmp quick_and_dirty true (SkipProof.make_thm thy) |
|
322 (Logic.mk_equals (x, t)); |
|
323 fun err () = error "preprocess_term: bad preprocessor" |
|
324 in case map prop_of (preprocess thy [eq]) of |
|
325 [Const ("==", _) $ x' $ t'] => if x = x' then t' else err () |
|
326 | _ => err () |
|
327 end; |
|
328 |
|
329 fun add_unfold eqn = |
|
330 let |
|
331 val thy = Thm.theory_of_thm eqn; |
|
332 val ctxt = ProofContext.init thy; |
|
333 val eqn' = LocalDefs.meta_rewrite_rule ctxt eqn; |
|
334 val names = term_consts (fst (Logic.dest_equals (prop_of eqn'))); |
|
335 fun prep thy = map (fn th => |
|
336 let val prop = prop_of th |
|
337 in |
|
338 if forall (fn name => exists_Const (equal name o fst) prop) names |
|
339 then rewrite_rule [eqn'] (Thm.transfer thy th) |
|
340 else th |
|
341 end) |
|
342 in add_preprocessor prep end; |
|
343 |
|
344 |
300 (**** code attribute ****) |
345 (**** code attribute ****) |
301 |
346 |
302 fun add_attribute name att thy = |
347 fun add_attribute name att thy = |
303 let val {codegens, tycodegens, consts, types, attrs, preprocs, modules, test_params} = |
348 let val {codegens, tycodegens, consts, types, attrs, preprocs, modules, test_params} = |
304 CodegenData.get thy |
349 CodegenData.get thy |
318 (#attrs (CodegenData.get (Context.theory_of context)))))); |
363 (#attrs (CodegenData.get (Context.theory_of context)))))); |
319 |
364 |
320 val _ = Context.add_setup |
365 val _ = Context.add_setup |
321 (Attrib.add_attributes [("code", code_attr, "declare theorems for code generation")]); |
366 (Attrib.add_attributes [("code", code_attr, "declare theorems for code generation")]); |
322 |
367 |
323 |
368 local |
324 (**** preprocessors ****) |
369 fun add_simple_attribute (name, f) = |
325 |
370 (add_attribute name o (Scan.succeed o Thm.declaration_attribute)) |
326 fun add_preprocessor p thy = |
371 (fn th => Context.mapping (f th) I); |
327 let val {codegens, tycodegens, consts, types, attrs, preprocs, modules, test_params} = |
372 in |
328 CodegenData.get thy |
373 val _ = map (Context.add_setup o add_simple_attribute) [ |
329 in CodegenData.put {tycodegens = tycodegens, |
374 ("func", CodeData.add_func true), |
330 codegens = codegens, consts = consts, types = types, |
375 ("nofunc", CodeData.del_func), |
331 attrs = attrs, preprocs = (stamp (), p) :: preprocs, |
376 ("unfold", (fn thm => add_unfold thm #> CodeData.add_inline thm)), |
332 modules = modules, test_params = test_params} thy |
377 ("inline", CodeData.add_inline), |
333 end; |
378 ("noinline", CodeData.del_inline) |
334 |
379 ] |
335 fun preprocess thy = |
380 end; (*local*) |
336 let val {preprocs, ...} = CodegenData.get thy |
|
337 in fold (fn (_, f) => f thy) preprocs end; |
|
338 |
|
339 fun preprocess_term thy t = |
|
340 let |
|
341 val x = Free (Name.variant (add_term_names (t, [])) "x", fastype_of t); |
|
342 (* fake definition *) |
|
343 val eq = setmp quick_and_dirty true (SkipProof.make_thm thy) |
|
344 (Logic.mk_equals (x, t)); |
|
345 fun err () = error "preprocess_term: bad preprocessor" |
|
346 in case map prop_of (preprocess thy [eq]) of |
|
347 [Const ("==", _) $ x' $ t'] => if x = x' then t' else err () |
|
348 | _ => err () |
|
349 end; |
|
350 |
|
351 fun add_unfold eqn = |
|
352 let |
|
353 val names = term_consts (fst (Logic.dest_equals (prop_of eqn))); |
|
354 fun prep thy = map (fn th => |
|
355 let val prop = prop_of th |
|
356 in |
|
357 if forall (fn name => exists_Const (equal name o fst) prop) names |
|
358 then rewrite_rule [eqn] (Thm.transfer thy th) |
|
359 else th |
|
360 end) |
|
361 in add_preprocessor prep end; |
|
362 |
|
363 |
381 |
364 |
382 |
365 (**** associate constants with target language code ****) |
383 (**** associate constants with target language code ****) |
366 |
384 |
367 fun gen_assoc_consts prep_type xs thy = Library.foldl (fn (thy, (s, tyopt, syn)) => |
385 fun gen_assoc_consts prep_type xs thy = Library.foldl (fn (thy, (s, tyopt, syn)) => |