src/Pure/codegen.ML
changeset 22749 189efc4a9f54
parent 22680 31a2303f4283
child 22845 5f9138bcb3d7
equal deleted inserted replaced
22748:474f92c32348 22749:189efc4a9f54
   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)) =>