src/Pure/Tools/codegen_package.ML
changeset 20931 19d9b78218fd
parent 20896 1484c7af6d68
child 20976 e324808e9f1f
equal deleted inserted replaced
20930:7ab9fa7d658f 20931:19d9b78218fd
    33 
    33 
    34 (** code extraction **)
    34 (** code extraction **)
    35 
    35 
    36 (* theory data *)
    36 (* theory data *)
    37 
    37 
    38 type appgen = theory -> ((sort -> sort) * Sorts.algebra) * Consts.T
       
    39   -> CodegenFuncgr.T
       
    40   -> bool * string list option
       
    41   -> (string * typ) * term list -> CodegenThingol.transact -> iterm * CodegenThingol.transact;
       
    42 
       
    43 type appgens = (int * (appgen * stamp)) Symtab.table;
       
    44 
       
    45 fun merge_appgens (x : appgens * appgens) =
       
    46   Symtab.merge (fn ((bounds1, (_, stamp1)), (bounds2, (_, stamp2))) =>
       
    47     bounds1 = bounds2 andalso stamp1 = stamp2) x;
       
    48 
       
    49 structure Code = CodeDataFun
    38 structure Code = CodeDataFun
    50 (struct
    39 (struct
    51   val name = "Pure/code";
    40   val name = "Pure/code";
    52   type T = CodegenThingol.code;
    41   type T = CodegenThingol.code;
    53   val empty = CodegenThingol.empty_code;
    42   val empty = CodegenThingol.empty_code;
    54   fun merge _ = CodegenThingol.merge_code;
    43   fun merge _ = CodegenThingol.merge_code;
    55   fun purge _ _ = CodegenThingol.empty_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;
    56 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));
    57 
    75 
    58 structure CodegenPackageData = TheoryDataFun
    76 structure CodegenPackageData = TheoryDataFun
    59 (struct
    77 (struct
    60   val name = "Pure/codegen_package";
    78   val name = "Pure/codegen_package";
    61   type T = appgens;
    79   type T = appgens * abstypes;
    62   val empty = Symtab.empty;
    80   val empty = (Symtab.empty, (Symtab.empty, Consttab.empty));
    63   val copy = I;
    81   val copy = I;
    64   val extend = I;
    82   val extend = I;
    65   fun merge _ = merge_appgens;
    83   fun merge _ ((appgens1, abstypes1), (appgens2, abstypes2)) =
       
    84     (merge_appgens (appgens1, appgens2), merge_abstypes (abstypes1, abstypes2));
    66   fun print _ _ = ();
    85   fun print _ _ = ();
    67 end);
    86 end);
    68 
    87 
    69 val _ = Context.add_setup (Code.init #> CodegenPackageData.init);
    88 val _ = Context.add_setup (Code.init #> CodegenPackageData.init);
    70 
    89 
    71 
    90 
    72 (* extraction kernel *)
    91 (* extraction kernel *)
    73 
    92 
    74 fun check_strict has_seri x (false, _) =
    93 fun check_strict (false, _) has_seri x =
    75       false
    94       false
    76   | check_strict has_seri x (_, SOME targets) =
    95   | check_strict (_, SOME targets) has_seri x =
    77       not (has_seri targets x)
    96       not (has_seri targets x)
    78   | check_strict has_seri x (true, _) =
    97   | check_strict (true, _) has_seri x =
    79       true;
    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;
    80 
   103 
    81 fun ensure_def_class thy (algbr as ((proj_sort, _), _)) funcgr strct class trns =
   104 fun ensure_def_class thy (algbr as ((proj_sort, _), _)) funcgr strct class trns =
    82   let
   105   let
    83     val (v, cs) = (ClassPackage.the_consts_sign thy) class;
   106     val (v, cs) = (ClassPackage.the_consts_sign thy) class;
    84     val superclasses = (proj_sort o Sign.super_classes thy) class;
   107     val superclasses = (proj_sort o Sign.super_classes thy) class;
   113             |-> (fn (vs, cos) => succeed (CodegenThingol.Datatype (vs, cos)))
   136             |-> (fn (vs, cos) => succeed (CodegenThingol.Datatype (vs, cos)))
   114         | NONE =>
   137         | NONE =>
   115             trns
   138             trns
   116             |> fail ("No such datatype: " ^ quote tyco)
   139             |> fail ("No such datatype: " ^ quote tyco)
   117     val tyco' = CodegenNames.tyco thy tyco;
   140     val tyco' = CodegenNames.tyco thy tyco;
   118     val strict = check_strict (CodegenSerializer.tyco_has_serialization thy) tyco' strct;
   141     val strict = check_strict strct (CodegenSerializer.tyco_has_serialization thy) tyco';
   119   in
   142   in
   120     trns
   143     trns
   121     |> tracing (fn _ => "generating type constructor " ^ quote tyco)
   144     |> tracing (fn _ => "generating type constructor " ^ quote tyco)
   122     |> CodegenThingol.ensure_def defgen_datatype strict
   145     |> CodegenThingol.ensure_def defgen_datatype strict
   123         ("generating type constructor " ^ quote tyco) tyco'
   146         ("generating type constructor " ^ quote tyco) tyco'
   137       trns
   160       trns
   138       |> exprgen_type thy algbr funcgr strct t1
   161       |> exprgen_type thy algbr funcgr strct t1
   139       ||>> exprgen_type thy algbr funcgr strct t2
   162       ||>> exprgen_type thy algbr funcgr strct t2
   140       |-> (fn (t1', t2') => pair (t1' `-> t2'))
   163       |-> (fn (t1', t2') => pair (t1' `-> t2'))
   141   | exprgen_type thy algbr funcgr strct (Type (tyco, tys)) trns =
   164   | exprgen_type thy algbr funcgr strct (Type (tyco, tys)) trns =
   142       trns
   165       case get_abstype thy (tyco, tys)
   143       |> ensure_def_tyco thy algbr funcgr strct tyco
   166        of SOME ty =>
   144       ||>> fold_map (exprgen_type thy algbr funcgr strct) tys
   167             trns
   145       |-> (fn (tyco, tys) => pair (tyco `%% tys));
   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));
   146 
   174 
   147 exception CONSTRAIN of (string * typ) * typ;
   175 exception CONSTRAIN of (string * typ) * typ;
   148 
   176 
   149 fun exprgen_typinst thy (algbr as ((proj_sort, algebra), consts)) funcgr strct (ty_ctxt, sort_decl) trns =
   177 fun exprgen_typinst thy (algbr as ((proj_sort, algebra), consts)) funcgr strct (ty_ctxt, sort_decl) trns =
   150   let
   178   let
   237     fun defgen_classop trns =
   265     fun defgen_classop trns =
   238       trns
   266       trns
   239       |> ensure_def_class thy algbr funcgr strct ((the o AxClass.class_of_param thy) c)
   267       |> ensure_def_class thy algbr funcgr strct ((the o AxClass.class_of_param thy) c)
   240       |-> (fn _ => succeed CodegenThingol.Bot);
   268       |-> (fn _ => succeed CodegenThingol.Bot);
   241     fun defgen_fun trns =
   269     fun defgen_fun trns =
   242       case CodegenFuncgr.get_funcs funcgr (c, tys)
   270       case CodegenFuncgr.get_funcs funcgr
       
   271         (perhaps (Consttab.lookup ((snd o snd o CodegenPackageData.get) thy)) (c, tys))
   243        of eq_thms as eq_thm :: _ =>
   272        of eq_thms as eq_thm :: _ =>
   244             let
   273             let
   245               val msg = cat_lines ("generating code for theorems " :: map string_of_thm eq_thms);
   274               val msg = cat_lines ("generating code for theorems " :: map string_of_thm eq_thms);
   246               val ty = (Logic.unvarifyT o CodegenData.typ_func thy) eq_thm;
   275               val ty = (Logic.unvarifyT o CodegenData.typ_func thy) eq_thm;
   247               val vs = (map dest_TFree o Consts.typargs consts) (c', ty);
   276               val vs = (map dest_TFree o Consts.typargs consts) (c', ty);
   269       else if CodegenNames.has_nsp CodegenNames.nsp_classop c'
   298       else if CodegenNames.has_nsp CodegenNames.nsp_classop c'
   270       then defgen_classop
   299       then defgen_classop
   271       else if CodegenNames.has_nsp CodegenNames.nsp_dtco c'
   300       else if CodegenNames.has_nsp CodegenNames.nsp_dtco c'
   272       then defgen_datatypecons
   301       then defgen_datatypecons
   273       else error ("Illegal shallow name space for constant: " ^ quote c');
   302       else error ("Illegal shallow name space for constant: " ^ quote c');
   274     val strict = check_strict (CodegenSerializer.const_has_serialization thy) c' strct;
   303     val strict = check_strict strct (CodegenSerializer.const_has_serialization thy) c';
   275   in
   304   in
   276     trns
   305     trns
   277     |> tracing (fn _ => "generating constant "
   306     |> tracing (fn _ => "generating constant "
   278         ^ (quote o CodegenConsts.string_of_const thy) (c, tys))
   307         ^ (quote o CodegenConsts.string_of_const thy) (c, tys))
   279     |> CodegenThingol.ensure_def defgen strict ("generating constant "
   308     |> CodegenThingol.ensure_def defgen strict ("generating constant "
   316   ||>> exprgen_typinst_const thy algbr funcgr strct (c, ty)
   345   ||>> exprgen_typinst_const thy algbr funcgr strct (c, ty)
   317   ||>> fold_map (exprgen_term thy algbr funcgr strct) ts
   346   ||>> fold_map (exprgen_term thy algbr funcgr strct) ts
   318   |-> (fn (((c, ty), iss), ts) =>
   347   |-> (fn (((c, ty), iss), ts) =>
   319          pair (IConst (c, (iss, ty)) `$$ ts))
   348          pair (IConst (c, (iss, ty)) `$$ ts))
   320 and select_appgen thy algbr funcgr strct ((c, ty), ts) trns =
   349 and select_appgen thy algbr funcgr strct ((c, ty), ts) trns =
   321   case Symtab.lookup (CodegenPackageData.get thy) c
   350   case Symtab.lookup (fst (CodegenPackageData.get thy)) c
   322    of SOME (i, (appgen, _)) =>
   351    of SOME (i, (appgen, _)) =>
   323         if length ts < i then
   352         if length ts < i then
   324           let
   353           let
   325             val tys = Library.take (i - length ts, ((fst o strip_type) ty));
   354             val tys = Library.take (i - length ts, ((fst o strip_type) ty));
   326             val vs = Name.names (Name.declare c Name.context) "a" tys;
   355             val vs = Name.names (Name.declare c Name.context) "a" tys;
   413             ), e0))
   442             ), e0))
   414         | (_, e0) => pair e0);
   443         | (_, e0) => pair e0);
   415 
   444 
   416 fun add_appconst (c, appgen) thy =
   445 fun add_appconst (c, appgen) thy =
   417   let
   446   let
   418     val i = (length o fst o strip_type o Sign.the_const_type thy) c
   447     val i = (length o fst o strip_type o Sign.the_const_type thy) c;
   419   in CodegenPackageData.map (Symtab.update (c, (i, (appgen, stamp ())))) thy end;
   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;
   420 
   537 
   421 
   538 
   422 
   539 
   423 (** code generation interfaces **)
   540 (** code generation interfaces **)
   424 
   541 
   425 fun generate thy (cs, rhss) targets init gen it =
   542 fun generate thy (cs, rhss) targets init gen it =
   426   let
   543   let
   427     val funcgr = CodegenFuncgr.mk_funcgr thy cs rhss;
   544     val raw_funcgr = CodegenFuncgr.mk_funcgr thy cs rhss;
   428     val qnaming = NameSpace.qualified_names NameSpace.default_naming
   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;
   429     val algebr = ClassPackage.operational_algebra thy;
   549     val algebr = ClassPackage.operational_algebra thy;
   430     val consttab = Consts.empty
   550     val consttab = Consts.empty
   431       |> fold (fn (c, ty) => Consts.declare qnaming
   551       |> fold (fn (c, ty) => Consts.declare qnaming
   432            ((CodegenNames.const thy c, ty), true))
   552            ((CodegenNames.const thy c, ty), true))
   433            (CodegenFuncgr.get_func_typs funcgr)
   553            (CodegenFuncgr.get_func_typs funcgr);
   434     val algbr = (algebr, consttab);
   554     val algbr = (algebr, consttab);
   435   in   
   555   in   
   436     Code.change_yield thy (CodegenThingol.start_transact init (gen thy algbr funcgr
   556     Code.change_yield thy (CodegenThingol.start_transact init (gen thy algbr funcgr
   437         (true, targets) it))
   557         (true, targets) it))
   438     |> (fn (x, modl) => x)
   558     |> (fn (x, modl) => x)
   502     val code = Code.get thy;
   622     val code = Code.get thy;
   503   in
   623   in
   504     (map (serialize' cs code) seris'; ())
   624     (map (serialize' cs code) seris'; ())
   505   end;
   625   end;
   506 
   626 
   507 fun reader_tyco thy rhss target dep =
   627 val (codeK, code_abstypeK, code_constsubstK) =
   508   generate thy rhss (SOME [target]) (SOME dep) (fold_map oooo exprgen_type);
   628   ("code_gen", "code_abstype", "code_constsubst");
   509 
       
   510 fun reader_const thy rhss target dep =
       
   511   generate thy rhss (SOME [target]) (SOME dep) (fold_map oooo exprgen_term');
       
   512 
       
   513 fun zip_list (x::xs) f g =
       
   514   f x #-> (fn y => fold_map (fn x => g |-- f x >> pair x) xs
       
   515     #-> (fn xys => pair ((x, y) :: xys)));
       
   516 
       
   517 fun parse_multi_syntax parse_thing parse_syntax =
       
   518   P.and_list1 parse_thing
       
   519   #-> (fn things => Scan.repeat1 (P.$$$ "(" |-- P.name :--
       
   520       (fn target => zip_list things (parse_syntax target)
       
   521         (P.$$$ "and")) --| P.$$$ ")"))
       
   522 
       
   523 
   629 
   524 in
   630 in
   525 
       
   526 val (codeK,
       
   527      syntax_classK, syntax_instK, syntax_tycoK, syntax_constK) =
       
   528   ("code_gen",
       
   529    "code_class", "code_instance", "code_type", "code_const");
       
   530 
   631 
   531 val codeP =
   632 val codeP =
   532   OuterSyntax.improper_command codeK "generate and serialize executable code for constants" K.diag (
   633   OuterSyntax.improper_command codeK "generate and serialize executable code for constants" K.diag (
   533     Scan.repeat P.term
   634     Scan.repeat P.term
   534     -- Scan.repeat (P.$$$ "(" |--
   635     -- Scan.repeat (P.$$$ "(" |--
   535         P.name -- P.arguments
   636         P.name -- P.arguments
   536         --| P.$$$ ")")
   637         --| P.$$$ ")")
   537     >> (fn (raw_cs, seris) => Toplevel.keep (code raw_cs seris o Toplevel.theory_of))
   638     >> (fn (raw_cs, seris) => Toplevel.keep (code raw_cs seris o Toplevel.theory_of))
   538   );
   639   );
   539 
   640 
   540 val syntax_classP =
   641 val code_abstypeP =
   541   OuterSyntax.command syntax_classK "define code syntax for class" K.thy_decl (
   642   OuterSyntax.command code_abstypeK "axiomatic abstypes for code generation" K.thy_decl (
   542     parse_multi_syntax P.xname
   643     (P.typ -- P.typ -- Scan.optional (P.$$$ "where" |-- Scan.repeat1
   543       (fn _ => fn _ => P.string -- Scan.optional (P.$$$ "where" |-- Scan.repeat1
   644         (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term)) [])
   544         (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.string)) [])
   645     >> (Toplevel.theory o uncurry abstyp_e)
   545     >> (Toplevel.theory oo fold) (fn (target, syns) =>
       
   546           fold (fn (raw_class, syn) => CodegenSerializer.add_syntax_class target raw_class syn) syns)
       
   547   );
   646   );
   548 
   647 
   549 val syntax_instP =
   648 val code_constsubstP =
   550   OuterSyntax.command syntax_instK "define code syntax for instance" K.thy_decl (
   649   OuterSyntax.command code_constsubstK "axiomatic constant substitutions for code generation" K.thy_decl (
   551     parse_multi_syntax (P.xname --| P.$$$ "::" -- P.xname)
   650     Scan.repeat1 (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term)
   552       (fn _ => fn _ => P.name #->
   651     >> (Toplevel.theory o constsubst_e)
   553         (fn "-" => Scan.succeed () | _ => Scan.fail_with (fn _ => "\"-\" expected") ()))
       
   554     >> (Toplevel.theory oo fold) (fn (target, syns) =>
       
   555           fold (fn (raw_inst, ()) => CodegenSerializer.add_syntax_inst target raw_inst) syns)
       
   556   );
   652   );
   557 
   653 
   558 val syntax_tycoP =
   654 val _ = OuterSyntax.add_parsers [codeP, code_abstypeP, code_constsubstP];
   559   OuterSyntax.command syntax_tycoK "define code syntax for type constructor" K.thy_decl (
       
   560     Scan.repeat1 (
       
   561       parse_multi_syntax P.xname (CodegenSerializer.parse_syntax_tyco reader_tyco)
       
   562     )
       
   563     >> (Toplevel.theory o (fold o fold) (fold snd o snd))
       
   564   );
       
   565 
       
   566 val syntax_constP =
       
   567   OuterSyntax.command syntax_constK "define code syntax for constant" K.thy_decl (
       
   568     Scan.repeat1 (
       
   569       parse_multi_syntax P.term (CodegenSerializer.parse_syntax_const reader_const)
       
   570     )
       
   571     >> (Toplevel.theory o (fold o fold) (fold snd o snd))
       
   572   );
       
   573 
       
   574 val _ = OuterSyntax.add_parsers [codeP,
       
   575   syntax_classP, syntax_instP, syntax_tycoP, syntax_constP];
       
   576 
   655 
   577 end; (* local *)
   656 end; (* local *)
   578 
   657 
   579 end; (* struct *)
   658 end; (* struct *)