src/Pure/Tools/codegen_package.ML
author haftmann
Tue, 10 Oct 2006 09:17:17 +0200
changeset 20931 19d9b78218fd
parent 20896 1484c7af6d68
child 20976 e324808e9f1f
permissions -rw-r--r--
added code_abstype and code_constsubst
     1 (*  Title:      Pure/Tools/codegen_package.ML
     2     ID:         $Id$
     3     Author:     Florian Haftmann, TU Muenchen
     4 
     5 Code generator extraction kernel. Code generator Isar setup.
     6 *)
     7 
     8 signature CODEGEN_PACKAGE =
     9 sig
    10   include BASIC_CODEGEN_THINGOL;
    11   val codegen_term: theory -> term -> thm * iterm;
    12   val eval_term: theory -> (string (*reference name!*) * 'a option ref) * term -> 'a;
    13   val const_of_idf: theory -> string -> string * typ;
    14   val get_root_module: theory -> CodegenThingol.code;
    15 
    16   type appgen;
    17   val add_appconst: string * appgen -> theory -> theory;
    18   val appgen_numeral: (theory -> term -> IntInf.int) -> appgen;
    19   val appgen_char: (term -> int option) -> appgen;
    20   val appgen_case: (theory -> term
    21     -> ((string * typ) list * ((term * typ) * (term * term) list)) option)
    22     -> appgen;
    23   val appgen_let: appgen;
    24 end;
    25 
    26 structure CodegenPackage : CODEGEN_PACKAGE =
    27 struct
    28 
    29 open BasicCodegenThingol;
    30 val tracing = CodegenThingol.tracing;
    31 val succeed = CodegenThingol.succeed;
    32 val fail = CodegenThingol.fail;
    33 
    34 (** code extraction **)
    35 
    36 (* theory data *)
    37 
    38 structure Code = CodeDataFun
    39 (struct
    40   val name = "Pure/code";
    41   type T = CodegenThingol.code;
    42   val empty = CodegenThingol.empty_code;
    43   fun merge _ = CodegenThingol.merge_code;
    44   fun purge _ NONE _ = CodegenThingol.empty_code
    45     | purge NONE _ _ = CodegenThingol.empty_code
    46     | purge (SOME thy) (SOME cs) code =
    47         let
    48           val cs_exisiting =
    49             map_filter (CodegenNames.const_rev thy) (Graph.keys code);
    50         in
    51           Graph.del_nodes
    52             ((Graph.all_succs code
    53               o map (CodegenNames.const thy)
    54               o filter (member CodegenConsts.eq_const cs_exisiting)
    55               ) cs)
    56             code
    57         end;
    58 end);
    59 
    60 type appgen = theory -> ((sort -> sort) * Sorts.algebra) * Consts.T
    61   -> CodegenFuncgr.T
    62   -> bool * string list option
    63   -> (string * typ) * term list -> CodegenThingol.transact -> iterm * CodegenThingol.transact;
    64 
    65 type appgens = (int * (appgen * stamp)) Symtab.table;
    66 val merge_appgens : appgens * appgens -> appgens =
    67   Symtab.merge (fn ((bounds1, (_, stamp1)), (bounds2, (_, stamp2))) =>
    68     bounds1 = bounds2 andalso stamp1 = stamp2);
    69 
    70 structure Consttab = CodegenConsts.Consttab;
    71 type abstypes = typ Symtab.table * CodegenConsts.const Consttab.table;
    72 fun merge_abstypes ((typs1, consts1) : abstypes, (typs2, consts2) : abstypes) =
    73   (Symtab.merge (Type.eq_type Vartab.empty) (typs1, typs2),
    74     Consttab.merge CodegenConsts.eq_const (consts1, consts2));
    75 
    76 structure CodegenPackageData = TheoryDataFun
    77 (struct
    78   val name = "Pure/codegen_package";
    79   type T = appgens * abstypes;
    80   val empty = (Symtab.empty, (Symtab.empty, Consttab.empty));
    81   val copy = I;
    82   val extend = I;
    83   fun merge _ ((appgens1, abstypes1), (appgens2, abstypes2)) =
    84     (merge_appgens (appgens1, appgens2), merge_abstypes (abstypes1, abstypes2));
    85   fun print _ _ = ();
    86 end);
    87 
    88 val _ = Context.add_setup (Code.init #> CodegenPackageData.init);
    89 
    90 
    91 (* extraction kernel *)
    92 
    93 fun check_strict (false, _) has_seri x =
    94       false
    95   | check_strict (_, SOME targets) has_seri x =
    96       not (has_seri targets x)
    97   | check_strict (true, _) has_seri x =
    98       true;
    99 
   100 fun get_abstype thy (tyco, tys) = case Symtab.lookup ((fst o snd o CodegenPackageData.get) thy) tyco
   101  of SOME ty => SOME ((map_atyps (fn TFree (n, _) => nth tys (the (Int.fromString n)))) ty)
   102   | NONE => NONE;
   103 
   104 fun ensure_def_class thy (algbr as ((proj_sort, _), _)) funcgr strct class trns =
   105   let
   106     val (v, cs) = (ClassPackage.the_consts_sign thy) class;
   107     val superclasses = (proj_sort o Sign.super_classes thy) class;
   108     val classops' = map (CodegenNames.const thy o CodegenConsts.norm_of_typ thy) cs;
   109     val class' = CodegenNames.class thy class;
   110     fun defgen_class trns =
   111       trns
   112       |> fold_map (ensure_def_class thy algbr funcgr strct) superclasses
   113       ||>> (fold_map (exprgen_type thy algbr funcgr strct) o map snd) cs
   114       |-> (fn (superclasses, classoptyps) => succeed
   115         (CodegenThingol.Class (superclasses,
   116           (unprefix "'" v, classops' ~~ classoptyps))))
   117   in
   118     trns
   119     |> tracing (fn _ => "generating class " ^ quote class)
   120     |> CodegenThingol.ensure_def defgen_class true
   121         ("generating class " ^ quote class) class'
   122     |> pair class'
   123   end
   124 and ensure_def_tyco thy algbr funcgr strct tyco trns =
   125   let
   126     fun defgen_datatype trns =
   127       case CodegenData.get_datatype thy tyco
   128        of SOME (vs, cos) =>
   129             trns
   130             |> fold_map (exprgen_tyvar_sort thy algbr funcgr strct) vs
   131             ||>> fold_map (fn (c, tys) =>
   132               fold_map (exprgen_type thy algbr funcgr strct) tys
   133               #-> (fn tys' =>
   134                 pair ((CodegenNames.const thy o CodegenConsts.norm_of_typ thy)
   135                   (c, tys ---> Type (tyco, map TFree vs)), tys'))) cos
   136             |-> (fn (vs, cos) => succeed (CodegenThingol.Datatype (vs, cos)))
   137         | NONE =>
   138             trns
   139             |> fail ("No such datatype: " ^ quote tyco)
   140     val tyco' = CodegenNames.tyco thy tyco;
   141     val strict = check_strict strct (CodegenSerializer.tyco_has_serialization thy) tyco';
   142   in
   143     trns
   144     |> tracing (fn _ => "generating type constructor " ^ quote tyco)
   145     |> CodegenThingol.ensure_def defgen_datatype strict
   146         ("generating type constructor " ^ quote tyco) tyco'
   147     |> pair tyco'
   148   end
   149 and exprgen_tyvar_sort thy (algbr as ((proj_sort, _), _)) funcgr strct (v, sort) trns =
   150   trns
   151   |> fold_map (ensure_def_class thy algbr funcgr strct) (proj_sort sort)
   152   |-> (fn sort => pair (unprefix "'" v, sort))
   153 and exprgen_type thy algbr funcgr strct (TVar _) trns =
   154       error "TVar encountered in typ during code generation"
   155   | exprgen_type thy algbr funcgr strct (TFree vs) trns =
   156       trns
   157       |> exprgen_tyvar_sort thy algbr funcgr strct vs
   158       |-> (fn (v, sort) => pair (ITyVar v))
   159   | exprgen_type thy algbr funcgr strct (Type ("fun", [t1, t2])) trns =
   160       trns
   161       |> exprgen_type thy algbr funcgr strct t1
   162       ||>> exprgen_type thy algbr funcgr strct t2
   163       |-> (fn (t1', t2') => pair (t1' `-> t2'))
   164   | exprgen_type thy algbr funcgr strct (Type (tyco, tys)) trns =
   165       case get_abstype thy (tyco, tys)
   166        of SOME ty =>
   167             trns
   168             |> exprgen_type thy algbr funcgr strct ty
   169         | NONE =>
   170             trns
   171             |> ensure_def_tyco thy algbr funcgr strct tyco
   172             ||>> fold_map (exprgen_type thy algbr funcgr strct) tys
   173             |-> (fn (tyco, tys) => pair (tyco `%% tys));
   174 
   175 exception CONSTRAIN of (string * typ) * typ;
   176 
   177 fun exprgen_typinst thy (algbr as ((proj_sort, algebra), consts)) funcgr strct (ty_ctxt, sort_decl) trns =
   178   let
   179     val pp = Sign.pp thy;
   180     datatype inst =
   181         Inst of (class * string) * inst list list
   182       | Contxt of (string * sort) * (class list * int);
   183     fun classrel (l as Contxt (v_sort, (classes, n)), _) class  =
   184           Contxt (v_sort, (class :: classes, n))
   185       | classrel (Inst ((_, tyco), lss), _) class =
   186           Inst ((class, tyco), lss);
   187     fun constructor tyco iss class =
   188       Inst ((class, tyco), (map o map) fst iss);
   189     fun variable (TFree (v, sort)) =
   190       let
   191         val sort' = proj_sort sort;
   192       in map_index (fn (n, class) => (Contxt ((v, sort'), ([], n)), class)) sort' end;
   193     val insts = Sorts.of_sort_derivation pp algebra
   194       {classrel = classrel, constructor = constructor, variable = variable}
   195       (ty_ctxt, proj_sort sort_decl);
   196     fun mk_dict (Inst (inst, instss)) trns =
   197           trns
   198           |> ensure_def_inst thy algbr funcgr strct inst
   199           ||>> (fold_map o fold_map) mk_dict instss
   200           |-> (fn (inst, instss) => pair (Instance (inst, instss)))
   201       | mk_dict (Contxt ((v, sort), (classes, k))) trns =
   202           trns
   203           |> fold_map (ensure_def_class thy algbr funcgr strct) classes
   204           |-> (fn classes => pair (Context (classes, (unprefix "'" v,
   205                 if length sort = 1 then ~1 else k))))
   206   in
   207     trns
   208     |> fold_map mk_dict insts
   209   end
   210 and exprgen_typinst_const thy (algbr as (_, consts)) funcgr strct (c, ty_ctxt) trns =
   211   let
   212     val c' = CodegenConsts.norm_of_typ thy (c, ty_ctxt)
   213     val idf = CodegenNames.const thy c';
   214     val ty_decl = Consts.declaration consts idf;
   215     val insts = (op ~~ o apsnd (map (snd o dest_TVar)) oo pairself)
   216       (curry (Consts.typargs consts) idf) (ty_ctxt, ty_decl);
   217     val _ = if exists not (map (Sign.of_sort thy) insts)
   218       then raise CONSTRAIN ((c, ty_decl), ty_ctxt) else ();
   219   in
   220     trns
   221     |> fold_map (exprgen_typinst thy algbr funcgr strct) insts
   222   end
   223 and ensure_def_inst thy (algbr as ((proj_sort, _), _)) funcgr strct (class, tyco) trns =
   224   let
   225     val (vs, classop_defs) = ((apsnd o map) Const o ClassPackage.the_inst_sign thy)
   226       (class, tyco);
   227     val classops = (map (CodegenConsts.norm_of_typ thy) o snd
   228       o ClassPackage.the_consts_sign thy) class;
   229     val arity_typ = Type (tyco, (map TFree vs));
   230     val superclasses = (proj_sort o Sign.super_classes thy) class
   231     fun gen_superarity superclass trns =
   232       trns
   233       |> ensure_def_class thy algbr funcgr strct superclass
   234       ||>> exprgen_typinst thy algbr funcgr strct (arity_typ, [superclass])
   235       |-> (fn (superclass, [Instance (inst, iss)]) => pair (superclass, (inst, iss)));
   236     fun gen_classop_def (classop, t) trns =
   237       trns
   238       |> ensure_def_const thy algbr funcgr strct classop
   239       ||>> exprgen_term thy algbr funcgr strct t;
   240     fun defgen_inst trns =
   241       trns
   242       |> ensure_def_class thy algbr funcgr strct class
   243       ||>> ensure_def_tyco thy algbr funcgr strct tyco
   244       ||>> fold_map (exprgen_tyvar_sort thy algbr funcgr strct) vs
   245       ||>> fold_map gen_superarity superclasses
   246       ||>> fold_map gen_classop_def (classops ~~ classop_defs)
   247       |-> (fn ((((class, tyco), arity), superarities), classops) =>
   248              succeed (CodegenThingol.Classinst ((class, (tyco, arity)), (superarities, classops))));
   249     val inst = CodegenNames.instance thy (class, tyco);
   250   in
   251     trns
   252     |> tracing (fn _ => "generating instance " ^ quote class ^ " / " ^ quote tyco)
   253     |> CodegenThingol.ensure_def defgen_inst true
   254          ("generating instance " ^ quote class ^ " / " ^ quote tyco) inst
   255     |> pair inst
   256   end
   257 and ensure_def_const thy (algbr as (_, consts)) funcgr strct (c, tys) trns =
   258   let
   259     val c' = CodegenNames.const thy (c, tys);
   260     fun defgen_datatypecons trns =
   261       trns
   262       |> ensure_def_tyco thy algbr funcgr strct
   263           ((the o CodegenData.get_datatype_of_constr thy) (c, tys))
   264       |-> (fn _ => succeed CodegenThingol.Bot);
   265     fun defgen_classop trns =
   266       trns
   267       |> ensure_def_class thy algbr funcgr strct ((the o AxClass.class_of_param thy) c)
   268       |-> (fn _ => succeed CodegenThingol.Bot);
   269     fun defgen_fun trns =
   270       case CodegenFuncgr.get_funcs funcgr
   271         (perhaps (Consttab.lookup ((snd o snd o CodegenPackageData.get) thy)) (c, tys))
   272        of eq_thms as eq_thm :: _ =>
   273             let
   274               val msg = cat_lines ("generating code for theorems " :: map string_of_thm eq_thms);
   275               val ty = (Logic.unvarifyT o CodegenData.typ_func thy) eq_thm;
   276               val vs = (map dest_TFree o Consts.typargs consts) (c', ty);
   277               val dest_eqthm =
   278                 apfst (snd o strip_comb) o Logic.dest_equals o Logic.unvarify o prop_of;
   279               fun exprgen_eq (args, rhs) trns =
   280                 trns
   281                 |> fold_map (exprgen_term thy algbr funcgr strct) args
   282                 ||>> exprgen_term thy algbr funcgr strct rhs;
   283             in
   284               trns
   285               |> CodegenThingol.message msg (fn trns => trns
   286               |> fold_map (exprgen_eq o dest_eqthm) eq_thms
   287               ||>> fold_map (exprgen_tyvar_sort thy algbr funcgr strct) vs
   288               ||>> exprgen_type thy algbr funcgr strct ty
   289               |-> (fn ((eqs, vs), ty) => succeed (CodegenThingol.Fun (eqs, (vs, ty)))))
   290             end
   291         | [] =>
   292               trns
   293               |> fail ("No defining equations found for "
   294                    ^ (quote o CodegenConsts.string_of_const thy) (c, tys));
   295     val defgen =
   296       if CodegenNames.has_nsp CodegenNames.nsp_fun c'
   297       then defgen_fun
   298       else if CodegenNames.has_nsp CodegenNames.nsp_classop c'
   299       then defgen_classop
   300       else if CodegenNames.has_nsp CodegenNames.nsp_dtco c'
   301       then defgen_datatypecons
   302       else error ("Illegal shallow name space for constant: " ^ quote c');
   303     val strict = check_strict strct (CodegenSerializer.const_has_serialization thy) c';
   304   in
   305     trns
   306     |> tracing (fn _ => "generating constant "
   307         ^ (quote o CodegenConsts.string_of_const thy) (c, tys))
   308     |> CodegenThingol.ensure_def defgen strict ("generating constant "
   309          ^ CodegenConsts.string_of_const thy (c, tys)) c'
   310     |> pair c'
   311   end
   312 and exprgen_term thy algbr funcgr strct (Const (c, ty)) trns =
   313       trns
   314       |> select_appgen thy algbr funcgr strct ((c, ty), [])
   315   | exprgen_term thy algbr funcgr strct (Var _) trns =
   316       error "Var encountered in term during code generation"
   317   | exprgen_term thy algbr funcgr strct (Free (v, ty)) trns =
   318       trns
   319       |> exprgen_type thy algbr funcgr strct ty
   320       |-> (fn _ => pair (IVar v))
   321   | exprgen_term thy algbr funcgr strct (Abs (raw_v, ty, raw_t)) trns =
   322       let
   323         val (v, t) = Syntax.variant_abs (CodegenNames.purify_var raw_v, ty, raw_t);
   324       in
   325         trns
   326         |> exprgen_type thy algbr funcgr strct ty
   327         ||>> exprgen_term thy algbr funcgr strct t
   328         |-> (fn (ty, t) => pair ((v, ty) `|-> t))
   329       end
   330   | exprgen_term thy algbr funcgr strct (t as _ $ _) trns =
   331       case strip_comb t
   332        of (Const (c, ty), ts) =>
   333             trns
   334             |> select_appgen thy algbr funcgr strct ((c, ty), ts)
   335             |-> (fn t => pair t)
   336         | (t', ts) =>
   337             trns
   338             |> exprgen_term thy algbr funcgr strct t'
   339             ||>> fold_map (exprgen_term thy algbr funcgr strct) ts
   340             |-> (fn (t, ts) => pair (t `$$ ts))
   341 and appgen_default thy algbr funcgr strct ((c, ty), ts) trns =
   342   trns
   343   |> ensure_def_const thy algbr funcgr strct (CodegenConsts.norm_of_typ thy (c, ty))
   344   ||>> exprgen_type thy algbr funcgr strct ty
   345   ||>> exprgen_typinst_const thy algbr funcgr strct (c, ty)
   346   ||>> fold_map (exprgen_term thy algbr funcgr strct) ts
   347   |-> (fn (((c, ty), iss), ts) =>
   348          pair (IConst (c, (iss, ty)) `$$ ts))
   349 and select_appgen thy algbr funcgr strct ((c, ty), ts) trns =
   350   case Symtab.lookup (fst (CodegenPackageData.get thy)) c
   351    of SOME (i, (appgen, _)) =>
   352         if length ts < i then
   353           let
   354             val tys = Library.take (i - length ts, ((fst o strip_type) ty));
   355             val vs = Name.names (Name.declare c Name.context) "a" tys;
   356           in
   357             trns
   358             |> fold_map (exprgen_type thy algbr funcgr strct) tys
   359             ||>> appgen thy algbr funcgr strct ((c, ty), ts @ map Free vs)
   360             |-> (fn (tys, t) => pair (map2 (fn (v, _) => pair v) vs tys `|--> t))
   361           end
   362         else if length ts > i then
   363           trns
   364           |> appgen thy algbr funcgr strct ((c, ty), Library.take (i, ts))
   365           ||>> fold_map (exprgen_term thy algbr funcgr strct) (Library.drop (i, ts))
   366           |-> (fn (t, ts) => pair (t `$$ ts))
   367         else
   368           trns
   369           |> appgen thy algbr funcgr strct ((c, ty), ts)
   370     | NONE =>
   371         trns
   372         |> appgen_default thy algbr funcgr strct ((c, ty), ts);
   373 
   374 
   375 (* entrance points into extraction kernel *)
   376 
   377 fun ensure_def_const' thy algbr funcgr strct c trns =
   378   ensure_def_const thy algbr funcgr strct c trns
   379   handle CONSTRAIN ((c, ty), ty_decl) => error (
   380     "Constant " ^ c ^ " with most general type\n"
   381     ^ Sign.string_of_typ thy ty
   382     ^ "\noccurs with type\n"
   383     ^ Sign.string_of_typ thy ty_decl);
   384 fun exprgen_term' thy algbr funcgr strct t trns =
   385   exprgen_term thy algbr funcgr strct t trns
   386   handle CONSTRAIN ((c, ty), ty_decl) => error ("In term " ^ (quote o Sign.string_of_term thy) t
   387     ^ ",\nconstant " ^ c ^ " with most general type\n"
   388     ^ Sign.string_of_typ thy ty
   389     ^ "\noccurs with type\n"
   390     ^ Sign.string_of_typ thy ty_decl);
   391 
   392 
   393 (* parametrized application generators, for instantiation in object logic *)
   394 (* (axiomatic extensions of extraction kernel *)
   395 
   396 fun appgen_numeral int_of_numeral thy algbr funcgr strct (app as (c, ts)) trns =
   397   case try (int_of_numeral thy) (list_comb (Const c, ts))
   398    of SOME i =>
   399         trns
   400         |> appgen_default thy algbr funcgr strct app
   401         |-> (fn t => pair (CodegenThingol.INum (i, t)))
   402     | NONE =>
   403         trns
   404         |> appgen_default thy algbr funcgr strct app;
   405 
   406 fun appgen_char char_to_index thy algbr funcgr strct (app as ((_, ty), _)) trns =
   407   case (char_to_index o list_comb o apfst Const) app
   408    of SOME i =>
   409         trns
   410         |> exprgen_type thy algbr funcgr strct ty
   411         ||>> appgen_default thy algbr funcgr strct app
   412         |-> (fn (_, t0) => pair (IChar (chr i, t0)))
   413     | NONE =>
   414         trns
   415         |> appgen_default thy algbr funcgr strct app;
   416 
   417 fun appgen_case dest_case_expr thy algbr funcgr strct (app as (c_ty, ts)) trns =
   418   let
   419     val SOME ([], ((st, sty), ds)) = dest_case_expr thy (list_comb (Const c_ty, ts));
   420     fun clausegen (dt, bt) trns =
   421       trns
   422       |> exprgen_term thy algbr funcgr strct dt
   423       ||>> exprgen_term thy algbr funcgr strct bt;
   424   in
   425     trns
   426     |> exprgen_term thy algbr funcgr strct st
   427     ||>> exprgen_type thy algbr funcgr strct sty
   428     ||>> fold_map clausegen ds
   429     ||>> appgen_default thy algbr funcgr strct app
   430     |-> (fn (((se, sty), ds), e0) => pair (ICase (((se, sty), ds), e0)))
   431   end;
   432 
   433 fun appgen_let thy algbr funcgr strct (app as (_, [st, ct])) trns =
   434   trns
   435   |> exprgen_term thy algbr funcgr strct ct
   436   ||>> exprgen_term thy algbr funcgr strct st
   437   ||>> appgen_default thy algbr funcgr strct app
   438   |-> (fn (((v, ty) `|-> be, se), e0) =>
   439             pair (ICase (((se, ty), case be
   440               of ICase (((IVar w, _), ds), _) => if v = w then ds else [(IVar v, be)]
   441                | _ => [(IVar v, be)]
   442             ), e0))
   443         | (_, e0) => pair e0);
   444 
   445 fun add_appconst (c, appgen) thy =
   446   let
   447     val i = (length o fst o strip_type o Sign.the_const_type thy) c;
   448     val _ = Code.change thy (K CodegenThingol.empty_code);
   449   in
   450     (CodegenPackageData.map o apfst)
   451       (Symtab.update (c, (i, (appgen, stamp ())))) thy
   452   end;
   453 
   454 
   455 
   456 (** abstype and constsubst interface **)
   457 
   458 fun gen_abstyp prep_const prep_typ (raw_abstyp, raw_substtyp) raw_absconsts thy =
   459   let
   460     val abstyp = Type.no_tvars (prep_typ thy raw_abstyp);
   461     val substtyp = Type.no_tvars (prep_typ thy raw_substtyp);
   462     val absconsts = (map o pairself) (prep_const thy) raw_absconsts;
   463     val Type (abstyco, tys) = abstyp handle BIND => error ("bad type: " ^ Sign.string_of_typ thy abstyp);
   464     val typarms = map (fst o dest_TFree) tys handle MATCH => error ("bad type: " ^ Sign.string_of_typ thy abstyp);
   465     fun mk_index v = 
   466       let
   467         val k = find_index (fn w => v = w) typarms;
   468       in if k = ~1
   469         then error ("free type variable: " ^ quote v)
   470         else TFree (string_of_int k, [])
   471       end;
   472     val typpat = map_atyps (fn TFree (v, _) => mk_index v) substtyp;
   473     fun apply_typpat (Type (tyco, tys)) =
   474           let
   475             val tys' = map apply_typpat tys;
   476           in if tyco = abstyco then
   477             (map_atyps (fn TFree (n, _) => nth tys' (the (Int.fromString n)))) typpat
   478           else
   479             Type (tyco, tys')
   480           end
   481       | apply_typpat ty = ty;
   482     val string_of_typ = setmp show_sorts true (Sign.string_of_typ thy);
   483     fun add_consts (c1, c2) =
   484       let
   485         val _ = if CodegenNames.has_nsp CodegenNames.nsp_fun (CodegenNames.const thy c2)
   486           then ()
   487           else error ("not a function: " ^ CodegenConsts.string_of_const thy c2);
   488         val funcgr = CodegenFuncgr.mk_funcgr thy [c1, c2] [];
   489         val ty_map = CodegenFuncgr.get_func_typs funcgr;
   490         val ty1 = (apply_typpat o the o AList.lookup CodegenConsts.eq_const ty_map) c1;
   491         val ty2 = (the o AList.lookup CodegenConsts.eq_const ty_map) c2;
   492         val _ = if Sign.typ_equiv thy (ty1, ty2) then () else
   493           error ("Incompatiable type signatures of " ^ CodegenConsts.string_of_const thy c1
   494             ^ " and " ^ CodegenConsts.string_of_const thy c2 ^ ":\n"
   495             ^ string_of_typ ty1 ^ "\n" ^ string_of_typ ty2);
   496       in Consttab.update (c1, c2) end;
   497     val _ = Code.change thy (K CodegenThingol.empty_code);
   498   in
   499     thy
   500     |> (CodegenPackageData.map o apsnd) (fn (abstypes, abscs) =>
   501           (abstypes
   502           |> Symtab.update (abstyco, typpat),
   503           abscs
   504           |> fold add_consts absconsts)
   505        )
   506   end;
   507 
   508 fun gen_constsubst prep_const raw_constsubsts thy =
   509   let
   510     val constsubsts = (map o pairself) (prep_const thy) raw_constsubsts;
   511     val string_of_typ = setmp show_sorts true (Sign.string_of_typ thy);
   512     fun add_consts (c1, c2) =
   513       let
   514         val _ = if CodegenNames.has_nsp CodegenNames.nsp_fun (CodegenNames.const thy c2)
   515           then ()
   516           else error ("not a function: " ^ CodegenConsts.string_of_const thy c2);
   517         val funcgr = CodegenFuncgr.mk_funcgr thy [c1, c2] [];
   518         val ty_map = CodegenFuncgr.get_func_typs funcgr;
   519         val ty1 = (the o AList.lookup CodegenConsts.eq_const ty_map) c1;
   520         val ty2 = (the o AList.lookup CodegenConsts.eq_const ty_map) c2;
   521         val _ = if Sign.typ_equiv thy (ty1, ty2) then () else
   522           error ("Incompatiable type signatures of " ^ CodegenConsts.string_of_const thy c1
   523             ^ " and " ^ CodegenConsts.string_of_const thy c2 ^ ":\n"
   524             ^ string_of_typ ty1 ^ "\n" ^ string_of_typ ty2);
   525       in Consttab.update (c1, c2) end;
   526     val _ = Code.change thy (K CodegenThingol.empty_code);
   527   in
   528     thy
   529     |> (CodegenPackageData.map o apsnd o apsnd) (fold add_consts constsubsts)
   530   end;
   531 
   532 val abstyp = gen_abstyp CodegenConsts.norm Sign.certify_typ;
   533 val abstyp_e = gen_abstyp CodegenConsts.read_const (fn thy => Sign.read_typ (thy, K NONE));
   534 
   535 val constsubst = gen_constsubst CodegenConsts.norm;
   536 val constsubst_e = gen_constsubst CodegenConsts.read_const;
   537 
   538 
   539 
   540 (** code generation interfaces **)
   541 
   542 fun generate thy (cs, rhss) targets init gen it =
   543   let
   544     val raw_funcgr = CodegenFuncgr.mk_funcgr thy cs rhss;
   545     val cs' = map_filter (Consttab.lookup ((snd o snd o CodegenPackageData.get) thy))
   546       (CodegenFuncgr.Constgraph.keys raw_funcgr);
   547     val funcgr = CodegenFuncgr.mk_funcgr thy cs' [];
   548     val qnaming = NameSpace.qualified_names NameSpace.default_naming;
   549     val algebr = ClassPackage.operational_algebra thy;
   550     val consttab = Consts.empty
   551       |> fold (fn (c, ty) => Consts.declare qnaming
   552            ((CodegenNames.const thy c, ty), true))
   553            (CodegenFuncgr.get_func_typs funcgr);
   554     val algbr = (algebr, consttab);
   555   in   
   556     Code.change_yield thy (CodegenThingol.start_transact init (gen thy algbr funcgr
   557         (true, targets) it))
   558     |> (fn (x, modl) => x)
   559   end;
   560 
   561 fun codegen_term thy t =
   562   let
   563     fun const_typ (c, ty) =
   564       let
   565         val const = CodegenConsts.norm_of_typ thy (c, ty);
   566         val funcgr = CodegenFuncgr.mk_funcgr thy [const] [];
   567       in case CodegenFuncgr.get_funcs funcgr const
   568        of (thm :: _) => CodegenData.typ_func thy thm
   569         | [] => Sign.the_const_type thy c
   570       end;
   571     val ct = Thm.cterm_of thy t;
   572     val (thm, ct') = CodegenData.preprocess_cterm thy
   573       (const_typ) ct;
   574     val t' = Thm.term_of ct';
   575     val cs_rhss = CodegenConsts.consts_of thy t';
   576   in
   577     (thm, generate thy cs_rhss (SOME []) NONE exprgen_term' t')
   578   end;
   579 
   580 fun const_of_idf thy =
   581   CodegenConsts.typ_of_inst thy o the o CodegenNames.const_rev thy;
   582 
   583 fun get_root_module thy =
   584   Code.get thy;
   585 
   586 fun eval_term thy (ref_spec, t) =
   587   let
   588     val _ = Term.fold_atyps (fn _ =>
   589       error ("Term" ^ Sign.string_of_term thy t ^ "is polymorhpic"))
   590       (Term.fastype_of t);
   591     val (_, t') = codegen_term thy t;
   592   in
   593     CodegenSerializer.eval_term thy (ref_spec, t') (Code.get thy)
   594   end;
   595 
   596 
   597 
   598 (** toplevel interface and setup **)
   599 
   600 local
   601 
   602 structure P = OuterParse
   603 and K = OuterKeyword
   604 
   605 fun code raw_cs seris thy =
   606   let
   607     val cs = map (CodegenConsts.read_const thy) raw_cs;
   608     val targets = case map fst seris
   609      of [] => NONE
   610       | xs => SOME xs;
   611     val seris' = map_filter (fn (target, args as _ :: _) =>
   612       SOME (CodegenSerializer.get_serializer thy (target, args)) | _ => NONE) seris;
   613     fun generate' thy = case cs
   614      of [] => []
   615       | _ =>
   616           generate thy (cs, []) targets NONE (fold_map oooo ensure_def_const') cs;
   617     fun serialize' [] code seri =
   618           seri NONE code 
   619       | serialize' cs code seri =
   620           seri (SOME cs) code;
   621     val cs = generate' thy;
   622     val code = Code.get thy;
   623   in
   624     (map (serialize' cs code) seris'; ())
   625   end;
   626 
   627 val (codeK, code_abstypeK, code_constsubstK) =
   628   ("code_gen", "code_abstype", "code_constsubst");
   629 
   630 in
   631 
   632 val codeP =
   633   OuterSyntax.improper_command codeK "generate and serialize executable code for constants" K.diag (
   634     Scan.repeat P.term
   635     -- Scan.repeat (P.$$$ "(" |--
   636         P.name -- P.arguments
   637         --| P.$$$ ")")
   638     >> (fn (raw_cs, seris) => Toplevel.keep (code raw_cs seris o Toplevel.theory_of))
   639   );
   640 
   641 val code_abstypeP =
   642   OuterSyntax.command code_abstypeK "axiomatic abstypes for code generation" K.thy_decl (
   643     (P.typ -- P.typ -- Scan.optional (P.$$$ "where" |-- Scan.repeat1
   644         (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term)) [])
   645     >> (Toplevel.theory o uncurry abstyp_e)
   646   );
   647 
   648 val code_constsubstP =
   649   OuterSyntax.command code_constsubstK "axiomatic constant substitutions for code generation" K.thy_decl (
   650     Scan.repeat1 (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term)
   651     >> (Toplevel.theory o constsubst_e)
   652   );
   653 
   654 val _ = OuterSyntax.add_parsers [codeP, code_abstypeP, code_constsubstP];
   655 
   656 end; (* local *)
   657 
   658 end; (* struct *)