src/Tools/Code/code_target.ML
changeset 55757 9fc71814b8c1
parent 55684 ee49b4f7edc8
child 55776 7dd1971b39c1
equal deleted inserted replaced
55756:565a20b22f09 55757:9fc71814b8c1
     4 Generic infrastructure for target language data.
     4 Generic infrastructure for target language data.
     5 *)
     5 *)
     6 
     6 
     7 signature CODE_TARGET =
     7 signature CODE_TARGET =
     8 sig
     8 sig
     9   val cert_tyco: theory -> string -> string
     9   val cert_tyco: Proof.context -> string -> string
    10   val read_tyco: theory -> string -> string
    10   val read_tyco: Proof.context -> string -> string
    11 
    11 
    12   val export_code_for: theory -> Path.T option -> string -> int option -> string -> Token.T list
    12   val export_code_for: Proof.context -> Path.T option -> string -> int option -> string -> Token.T list
    13     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> unit
    13     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> unit
    14   val produce_code_for: theory -> string -> int option -> string -> Token.T list
    14   val produce_code_for: Proof.context -> string -> int option -> string -> Token.T list
    15     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> (string * string) list * string option list
    15     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> (string * string) list * string option list
    16   val present_code_for: theory -> string -> int option -> string -> Token.T list
    16   val present_code_for: Proof.context -> string -> int option -> string -> Token.T list
    17     -> Code_Thingol.program -> Code_Symbol.T list * Code_Symbol.T list -> string
    17     -> Code_Thingol.program -> Code_Symbol.T list * Code_Symbol.T list -> string
    18   val check_code_for: theory -> string -> bool -> Token.T list
    18   val check_code_for: Proof.context -> string -> bool -> Token.T list
    19     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> unit
    19     -> Code_Thingol.program -> bool -> Code_Symbol.T list -> unit
    20 
    20 
    21   val export_code: theory -> bool -> string list
    21   val export_code: Proof.context -> bool -> string list
    22     -> (((string * string) * Path.T option) * Token.T list) list -> unit
    22     -> (((string * string) * Path.T option) * Token.T list) list -> unit
    23   val produce_code: theory -> bool -> string list
    23   val produce_code: Proof.context -> bool -> string list
    24     -> string -> int option -> string -> Token.T list -> (string * string) list * string option list
    24     -> string -> int option -> string -> Token.T list -> (string * string) list * string option list
    25   val present_code: theory -> string list -> Code_Symbol.T list
    25   val present_code: Proof.context -> string list -> Code_Symbol.T list
    26     -> string -> int option -> string -> Token.T list -> string
    26     -> string -> int option -> string -> Token.T list -> string
    27   val check_code: theory -> bool -> string list
    27   val check_code: Proof.context -> bool -> string list
    28     -> ((string * bool) * Token.T list) list -> unit
    28     -> ((string * bool) * Token.T list) list -> unit
    29 
    29 
    30   val generatedN: string
    30   val generatedN: string
    31   val evaluator: theory -> string -> Code_Thingol.program
    31   val evaluator: Proof.context -> string -> Code_Thingol.program
    32     -> Code_Symbol.T list -> bool -> ((string * class list) list * Code_Thingol.itype) * Code_Thingol.iterm
    32     -> Code_Symbol.T list -> bool -> ((string * class list) list * Code_Thingol.itype) * Code_Thingol.iterm
    33     -> (string * string) list * string
    33     -> (string * string) list * string
    34 
    34 
    35   type serializer
    35   type serializer
    36   type literals = Code_Printer.literals
    36   type literals = Code_Printer.literals
    38     check: { env_var: string, make_destination: Path.T -> Path.T, make_command: string -> string } }
    38     check: { env_var: string, make_destination: Path.T -> Path.T, make_command: string -> string } }
    39     -> theory -> theory
    39     -> theory -> theory
    40   val extend_target: string *
    40   val extend_target: string *
    41       (string * (Code_Thingol.program -> Code_Thingol.program))
    41       (string * (Code_Thingol.program -> Code_Thingol.program))
    42     -> theory -> theory
    42     -> theory -> theory
    43   val assert_target: theory -> string -> string
    43   val assert_target: Proof.context -> string -> string
    44   val the_literals: theory -> string -> literals
    44   val the_literals: Proof.context -> string -> literals
    45   type serialization
    45   type serialization
    46   val parse_args: 'a parser -> Token.T list -> 'a
    46   val parse_args: 'a parser -> Token.T list -> 'a
    47   val serialization: (int -> Path.T option -> 'a -> unit)
    47   val serialization: (int -> Path.T option -> 'a -> unit)
    48     -> (Code_Symbol.T list -> int -> 'a -> (string * string) list * (Code_Symbol.T -> string option))
    48     -> (Code_Symbol.T list -> int -> 'a -> (string * string) list * (Code_Symbol.T -> string option))
    49     -> 'a -> serialization
    49     -> 'a -> serialization
    81 type raw_const_syntax = Code_Printer.raw_const_syntax;
    81 type raw_const_syntax = Code_Printer.raw_const_syntax;
    82 
    82 
    83 
    83 
    84 (** checking and parsing of symbols **)
    84 (** checking and parsing of symbols **)
    85 
    85 
    86 fun cert_const thy const =
    86 fun cert_const ctxt const =
    87   let
    87   let
    88     val _ = if Sign.declared_const thy const then ()
    88     val _ = if Sign.declared_const (Proof_Context.theory_of ctxt) const then ()
    89       else error ("No such constant: " ^ quote const);
    89       else error ("No such constant: " ^ quote const);
    90   in const end;
    90   in const end;
    91 
    91 
    92 fun cert_tyco thy tyco =
    92 fun read_const ctxt = Code.read_const (Proof_Context.theory_of ctxt);
    93   let
    93 
    94     val _ = if Sign.declared_tyname thy tyco then ()
    94 fun cert_tyco ctxt tyco =
       
    95   let
       
    96     val _ = if Sign.declared_tyname (Proof_Context.theory_of ctxt) tyco then ()
    95       else error ("No such type constructor: " ^ quote tyco);
    97       else error ("No such type constructor: " ^ quote tyco);
    96   in tyco end;
    98   in tyco end;
    97 
    99 
    98 fun read_tyco thy = #1 o dest_Type
   100 fun read_tyco ctxt = #1 o dest_Type
    99   o Proof_Context.read_type_name_proper (Proof_Context.init_global thy) true;
   101   o Proof_Context.read_type_name_proper ctxt true;
   100 
   102 
   101 fun cert_class thy class =
   103 fun cert_class ctxt class =
   102   let
   104   let
   103     val _ = Axclass.get_info thy class;
   105     val _ = Axclass.get_info (Proof_Context.theory_of ctxt) class;
   104   in class end;
   106   in class end;
   105 
   107 
   106 fun read_class thy = Proof_Context.read_class (Proof_Context.init_global thy);
       
   107 
       
   108 val parse_classrel_ident = Parse.class --| @{keyword "<"} -- Parse.class;
   108 val parse_classrel_ident = Parse.class --| @{keyword "<"} -- Parse.class;
   109 
   109 
   110 fun cert_inst thy (class, tyco) =
   110 fun cert_inst ctxt (class, tyco) =
   111   (cert_class thy class, cert_tyco thy tyco);
   111   (cert_class ctxt class, cert_tyco ctxt tyco);
   112 
   112 
   113 fun read_inst thy (raw_tyco, raw_class) =
   113 fun read_inst ctxt (raw_tyco, raw_class) =
   114   (read_tyco thy raw_tyco, read_class thy raw_class);
   114   (read_tyco ctxt raw_tyco, Proof_Context.read_class ctxt raw_class);
   115 
   115 
   116 val parse_inst_ident = Parse.xname --| @{keyword "::"} -- Parse.class;
   116 val parse_inst_ident = Parse.xname --| @{keyword "::"} -- Parse.class;
   117 
   117 
   118 fun cert_syms thy =
   118 fun cert_syms ctxt =
   119   Code_Symbol.map_attr (apfst (cert_const thy)) (apfst (cert_tyco thy))
   119   Code_Symbol.map_attr (apfst (cert_const ctxt)) (apfst (cert_tyco ctxt))
   120     (apfst (cert_class thy)) ((apfst o pairself) (cert_class thy)) (apfst (cert_inst thy)) I;
   120     (apfst (cert_class ctxt)) ((apfst o pairself) (cert_class ctxt)) (apfst (cert_inst ctxt)) I;
   121 
   121 
   122 fun read_syms thy =
   122 fun read_syms ctxt =
   123   Code_Symbol.map_attr (apfst (Code.read_const thy)) (apfst (read_tyco thy))
   123   Code_Symbol.map_attr (apfst (read_const ctxt)) (apfst (read_tyco ctxt))
   124     (apfst (read_class thy)) ((apfst o pairself) (read_class thy)) (apfst (read_inst thy)) I;
   124     (apfst (Proof_Context.read_class ctxt)) ((apfst o pairself) (Proof_Context.read_class ctxt)) (apfst (read_inst ctxt)) I;
   125 
   125 
   126 fun check_name is_module s =
   126 fun check_name is_module s =
   127   let
   127   let
   128     val _ = if s = "" then error "Bad empty code name" else ();
   128     val _ = if s = "" then error "Bad empty code name" else ();
   129     val xs = Long_Name.explode s;
   129     val xs = Long_Name.explode s;
   229   val extend = I;
   229   val extend = I;
   230   fun merge ((target1, width1), (target2, width2)) : T =
   230   fun merge ((target1, width1), (target2, width2)) : T =
   231     (Symtab.join (merge_target true) (target1, target2), Int.max (width1, width2));
   231     (Symtab.join (merge_target true) (target1, target2), Int.max (width1, width2));
   232 );
   232 );
   233 
   233 
   234 fun assert_target thy target = if Symtab.defined (fst (Targets.get thy)) target
   234 fun assert_target ctxt target =
       
   235   if Symtab.defined (fst (Targets.get (Proof_Context.theory_of ctxt))) target
   235   then target
   236   then target
   236   else error ("Unknown code target language: " ^ quote target);
   237   else error ("Unknown code target language: " ^ quote target);
   237 
   238 
   238 fun put_target (target, seri) thy =
   239 fun put_target (target, seri) thy =
   239   let
   240   let
   262 fun extend_target (target, (super, modify)) =
   263 fun extend_target (target, (super, modify)) =
   263   put_target (target, Extension (super, modify));
   264   put_target (target, Extension (super, modify));
   264 
   265 
   265 fun map_target_data target f thy =
   266 fun map_target_data target f thy =
   266   let
   267   let
   267     val _ = assert_target thy target;
   268     val _ = assert_target (Proof_Context.init_global thy) target;
   268   in
   269   in
   269     thy
   270     thy
   270     |> (Targets.map o apfst o Symtab.map_entry target o map_target o apsnd) f
   271     |> (Targets.map o apfst o Symtab.map_entry target o map_target o apsnd) f
   271   end;
   272   end;
   272 
   273 
   282 
   283 
   283 (** serializer usage **)
   284 (** serializer usage **)
   284 
   285 
   285 (* montage *)
   286 (* montage *)
   286 
   287 
   287 fun the_fundamental thy =
   288 fun the_fundamental ctxt =
   288   let
   289   let
   289     val (targets, _) = Targets.get thy;
   290     val (targets, _) = Targets.get (Proof_Context.theory_of ctxt);
   290     fun fundamental target = case Symtab.lookup targets target
   291     fun fundamental target = case Symtab.lookup targets target
   291      of SOME data => (case the_description data
   292      of SOME data => (case the_description data
   292          of Fundamental data => data
   293          of Fundamental data => data
   293           | Extension (super, _) => fundamental super)
   294           | Extension (super, _) => fundamental super)
   294       | NONE => error ("Unknown code target language: " ^ quote target);
   295       | NONE => error ("Unknown code target language: " ^ quote target);
   295   in fundamental end;
   296   in fundamental end;
   296 
   297 
   297 fun the_literals thy = #literals o the_fundamental thy;
   298 fun the_literals ctxt = #literals o the_fundamental ctxt;
   298 
   299 
   299 fun collapse_hierarchy thy =
   300 fun collapse_hierarchy ctxt =
   300   let
   301   let
   301     val (targets, _) = Targets.get thy;
   302     val (targets, _) = Targets.get (Proof_Context.theory_of ctxt);
   302     fun collapse target =
   303     fun collapse target =
   303       let
   304       let
   304         val data = case Symtab.lookup targets target
   305         val data = case Symtab.lookup targets target
   305          of SOME data => data
   306          of SOME data => data
   306           | NONE => error ("Unknown code target language: " ^ quote target);
   307           | NONE => error ("Unknown code target language: " ^ quote target);
   312       end;
   313       end;
   313   in collapse end;
   314   in collapse end;
   314 
   315 
   315 local
   316 local
   316 
   317 
   317 fun activate_target thy target =
   318 fun activate_target ctxt target =
   318   let
   319   let
       
   320     val thy = Proof_Context.theory_of ctxt;
   319     val (_, default_width) = Targets.get thy;
   321     val (_, default_width) = Targets.get thy;
   320     val (modify, data) = collapse_hierarchy thy target;
   322     val (modify, data) = collapse_hierarchy ctxt target;
   321   in (default_width, data, modify) end;
   323   in (default_width, data, modify) end;
   322 
   324 
   323 fun project_program thy syms_hidden syms1 program2 =
   325 fun project_program ctxt syms_hidden syms1 program2 =
   324   let
   326   let
   325     val ctxt = Proof_Context.init_global thy;
       
   326     val syms2 = subtract (op =) syms_hidden syms1;
   327     val syms2 = subtract (op =) syms_hidden syms1;
   327     val program3 = Code_Symbol.Graph.restrict (not o member (op =) syms_hidden) program2;
   328     val program3 = Code_Symbol.Graph.restrict (not o member (op =) syms_hidden) program2;
   328     val syms4 = Code_Symbol.Graph.all_succs program3 syms2;
   329     val syms4 = Code_Symbol.Graph.all_succs program3 syms2;
   329     val unimplemented = Code_Thingol.unimplemented program3;
   330     val unimplemented = Code_Thingol.unimplemented program3;
   330     val _ =
   331     val _ =
   332       else error ("No code equations for " ^
   333       else error ("No code equations for " ^
   333         commas (map (Proof_Context.markup_const ctxt) unimplemented));
   334         commas (map (Proof_Context.markup_const ctxt) unimplemented));
   334     val program4 = Code_Symbol.Graph.restrict (member (op =) syms4) program3;
   335     val program4 = Code_Symbol.Graph.restrict (member (op =) syms4) program3;
   335   in (syms4, program4) end;
   336   in (syms4, program4) end;
   336 
   337 
   337 fun prepare_serializer thy (serializer : serializer) reserved identifiers
   338 fun prepare_serializer ctxt (serializer : serializer) reserved identifiers
   338     printings module_name args proto_program syms =
   339     printings module_name args proto_program syms =
   339   let
   340   let
   340     val syms_hidden = Code_Symbol.symbols_of printings;
   341     val syms_hidden = Code_Symbol.symbols_of printings;
   341     val (syms_all, program) = project_program thy syms_hidden syms proto_program;
   342     val (syms_all, program) = project_program ctxt syms_hidden syms proto_program;
   342     fun select_include (name, (content, cs)) =
   343     fun select_include (name, (content, cs)) =
   343       if null cs orelse exists (fn c => member (op =) syms_all (Constant c)) cs
   344       if null cs orelse exists (fn c => member (op =) syms_all (Constant c)) cs
   344       then SOME (name, content) else NONE;
   345       then SOME (name, content) else NONE;
   345     val includes = map_filter select_include (Code_Symbol.dest_module_data printings);
   346     val includes = map_filter select_include (Code_Symbol.dest_module_data printings);
   346   in
   347   in
   347     (serializer args (Proof_Context.init_global thy) {
   348     (serializer args ctxt {
   348       module_name = module_name,
   349       module_name = module_name,
   349       reserved_syms = reserved,
   350       reserved_syms = reserved,
   350       identifiers = identifiers,
   351       identifiers = identifiers,
   351       includes = includes,
   352       includes = includes,
   352       const_syntax = Code_Symbol.lookup_constant_data printings,
   353       const_syntax = Code_Symbol.lookup_constant_data printings,
   353       tyco_syntax = Code_Symbol.lookup_type_constructor_data printings,
   354       tyco_syntax = Code_Symbol.lookup_type_constructor_data printings,
   354       class_syntax = Code_Symbol.lookup_type_class_data printings },
   355       class_syntax = Code_Symbol.lookup_type_class_data printings },
   355       (syms_all, program))
   356       (syms_all, program))
   356   end;
   357   end;
   357 
   358 
   358 fun mount_serializer thy target some_width module_name args program syms =
   359 fun mount_serializer ctxt target some_width module_name args program syms =
   359   let
   360   let
   360     val (default_width, data, modify) = activate_target thy target;
   361     val (default_width, data, modify) = activate_target ctxt target;
   361     val serializer = case the_description data
   362     val serializer = case the_description data
   362      of Fundamental seri => #serializer seri;
   363      of Fundamental seri => #serializer seri;
   363     val (prepared_serializer, (prepared_syms, prepared_program)) =
   364     val (prepared_serializer, (prepared_syms, prepared_program)) =
   364       prepare_serializer thy serializer
   365       prepare_serializer ctxt serializer
   365         (the_reserved data) (the_identifiers data) (the_printings data)
   366         (the_reserved data) (the_identifiers data) (the_printings data)
   366         module_name args (modify program) syms
   367         module_name args (modify program) syms
   367     val width = the_default default_width some_width;
   368     val width = the_default default_width some_width;
   368   in (fn program => fn syms => prepared_serializer syms program width, (prepared_syms, prepared_program)) end;
   369   in (fn program => fn syms => prepared_serializer syms program width, (prepared_syms, prepared_program)) end;
   369 
   370 
   370 fun invoke_serializer thy target some_width raw_module_name args program all_public syms =
   371 fun invoke_serializer ctxt target some_width raw_module_name args program all_public syms =
   371   let
   372   let
   372     val module_name = if raw_module_name = "" then ""
   373     val module_name = if raw_module_name = "" then ""
   373       else (check_name true raw_module_name; raw_module_name)
   374       else (check_name true raw_module_name; raw_module_name)
   374     val (mounted_serializer, (prepared_syms, prepared_program)) = mount_serializer thy
   375     val (mounted_serializer, (prepared_syms, prepared_program)) =
   375       target some_width module_name args program syms;
   376       mount_serializer ctxt target some_width module_name args program syms;
   376   in mounted_serializer prepared_program (if all_public then prepared_syms else []) end;
   377   in mounted_serializer prepared_program (if all_public then prepared_syms else []) end;
   377 
   378 
   378 fun assert_module_name "" = error "Empty module name not allowed here"
   379 fun assert_module_name "" = error "Empty module name not allowed here"
   379   | assert_module_name module_name = module_name;
   380   | assert_module_name module_name = module_name;
   380 
   381 
   381 fun using_master_directory thy =
   382 fun using_master_directory ctxt =
   382   Option.map (Path.append (File.pwd ()) o Path.append (Thy_Load.master_directory thy));
   383   Option.map (Path.append (File.pwd ()) o Path.append (Thy_Load.master_directory (Proof_Context.theory_of ctxt)));
   383 
   384 
   384 in
   385 in
   385 
   386 
   386 val generatedN = "Generated_Code";
   387 val generatedN = "Generated_Code";
   387 
   388 
   388 fun export_code_for thy some_path target some_width module_name args =
   389 fun export_code_for ctxt some_path target some_width module_name args =
   389   export (using_master_directory thy some_path)
   390   export (using_master_directory ctxt some_path)
   390   ooo invoke_serializer thy target some_width module_name args;
   391   ooo invoke_serializer ctxt target some_width module_name args;
   391 
   392 
   392 fun produce_code_for thy target some_width module_name args =
   393 fun produce_code_for ctxt target some_width module_name args =
   393   let
   394   let
   394     val serializer = invoke_serializer thy target some_width (assert_module_name module_name) args;
   395     val serializer = invoke_serializer ctxt target some_width (assert_module_name module_name) args;
   395   in fn program => fn all_public => fn syms =>
   396   in fn program => fn all_public => fn syms =>
   396     produce (serializer program all_public syms) |> apsnd (fn deresolve => map deresolve syms)
   397     produce (serializer program all_public syms) |> apsnd (fn deresolve => map deresolve syms)
   397   end;
   398   end;
   398 
   399 
   399 fun present_code_for thy target some_width module_name args =
   400 fun present_code_for ctxt target some_width module_name args =
   400   let
   401   let
   401     val serializer = invoke_serializer thy target some_width (assert_module_name module_name) args;
   402     val serializer = invoke_serializer ctxt target some_width (assert_module_name module_name) args;
   402   in fn program => fn (syms, selects) =>
   403   in fn program => fn (syms, selects) =>
   403     present selects (serializer program false syms)
   404     present selects (serializer program false syms)
   404   end;
   405   end;
   405 
   406 
   406 fun check_code_for thy target strict args program all_public syms =
   407 fun check_code_for ctxt target strict args program all_public syms =
   407   let
   408   let
   408     val { env_var, make_destination, make_command } =
   409     val { env_var, make_destination, make_command } =
   409       (#check o the_fundamental thy) target;
   410       (#check o the_fundamental ctxt) target;
   410     fun ext_check p =
   411     fun ext_check p =
   411       let
   412       let
   412         val destination = make_destination p;
   413         val destination = make_destination p;
   413         val _ = export (SOME destination) (invoke_serializer thy target (SOME 80)
   414         val _ = export (SOME destination) (invoke_serializer ctxt target (SOME 80)
   414           generatedN args program all_public syms);
   415           generatedN args program all_public syms);
   415         val cmd = make_command generatedN;
   416         val cmd = make_command generatedN;
   416       in
   417       in
   417         if Isabelle_System.bash ("cd " ^ File.shell_path p ^ " && " ^ cmd ^ " 2>&1") <> 0
   418         if Isabelle_System.bash ("cd " ^ File.shell_path p ^ " && " ^ cmd ^ " 2>&1") <> 0
   418         then error ("Code check failed for " ^ target ^ ": " ^ cmd)
   419         then error ("Code check failed for " ^ target ^ ": " ^ cmd)
   441     val (program_code, deresolve) =
   442     val (program_code, deresolve) =
   442       produce (mounted_serializer program (if all_public then [] else [Code_Symbol.value]));
   443       produce (mounted_serializer program (if all_public then [] else [Code_Symbol.value]));
   443     val value_name = the (deresolve Code_Symbol.value);
   444     val value_name = the (deresolve Code_Symbol.value);
   444   in (program_code, value_name) end;
   445   in (program_code, value_name) end;
   445 
   446 
   446 fun evaluator thy target program syms =
   447 fun evaluator ctxt target program syms =
   447   let
   448   let
   448     val (mounted_serializer, (_, prepared_program)) =
   449     val (mounted_serializer, (_, prepared_program)) =
   449       mount_serializer thy target NONE generatedN [] program syms;
   450       mount_serializer ctxt target NONE generatedN [] program syms;
   450   in evaluation mounted_serializer prepared_program syms end;
   451   in evaluation mounted_serializer prepared_program syms end;
   451 
   452 
   452 end; (* local *)
   453 end; (* local *)
   453 
   454 
   454 
   455 
   455 (* code generation *)
   456 (* code generation *)
   456 
   457 
   457 fun prep_destination "" = NONE
   458 fun prep_destination "" = NONE
   458   | prep_destination s = SOME (Path.explode s);
   459   | prep_destination s = SOME (Path.explode s);
   459 
   460 
   460 fun export_code thy all_public cs seris =
   461 fun export_code ctxt all_public cs seris =
   461   let
   462   let
       
   463     val thy = Proof_Context.theory_of ctxt;
   462     val program = Code_Thingol.consts_program thy cs;
   464     val program = Code_Thingol.consts_program thy cs;
   463     val _ = map (fn (((target, module_name), some_path), args) =>
   465     val _ = map (fn (((target, module_name), some_path), args) =>
   464       export_code_for thy some_path target NONE module_name args program all_public (map Constant cs)) seris;
   466       export_code_for ctxt some_path target NONE module_name args program all_public (map Constant cs)) seris;
   465   in () end;
   467   in () end;
   466 
   468 
   467 fun export_code_cmd all_public raw_cs seris thy =
   469 fun export_code_cmd all_public raw_cs seris ctxt =
   468   export_code thy all_public
   470   export_code ctxt all_public
   469     (Code_Thingol.read_const_exprs thy raw_cs)
   471     (Code_Thingol.read_const_exprs ctxt raw_cs)
   470     ((map o apfst o apsnd) prep_destination seris);
   472     ((map o apfst o apsnd) prep_destination seris);
   471 
   473 
   472 fun produce_code thy all_public cs target some_width some_module_name args =
   474 fun produce_code ctxt all_public cs target some_width some_module_name args =
   473   let
   475   let
       
   476     val thy = Proof_Context.theory_of ctxt;
   474     val program = Code_Thingol.consts_program thy cs;
   477     val program = Code_Thingol.consts_program thy cs;
   475   in produce_code_for thy target some_width some_module_name args program all_public (map Constant cs) end;
   478   in produce_code_for ctxt target some_width some_module_name args program all_public (map Constant cs) end;
   476 
   479 
   477 fun present_code thy cs syms target some_width some_module_name args =
   480 fun present_code ctxt cs syms target some_width some_module_name args =
   478   let
   481   let
       
   482     val thy = Proof_Context.theory_of ctxt;
   479     val program = Code_Thingol.consts_program thy cs;
   483     val program = Code_Thingol.consts_program thy cs;
   480   in present_code_for thy target some_width some_module_name args program (map Constant cs, syms) end;
   484   in present_code_for ctxt target some_width some_module_name args program (map Constant cs, syms) end;
   481 
   485 
   482 fun check_code thy all_public cs seris =
   486 fun check_code ctxt all_public cs seris =
   483   let
   487   let
       
   488     val thy = Proof_Context.theory_of ctxt;
   484     val program = Code_Thingol.consts_program thy cs;
   489     val program = Code_Thingol.consts_program thy cs;
   485     val _ = map (fn ((target, strict), args) =>
   490     val _ = map (fn ((target, strict), args) =>
   486       check_code_for thy target strict args program all_public (map Constant cs)) seris;
   491       check_code_for ctxt target strict args program all_public (map Constant cs)) seris;
   487   in () end;
   492   in () end;
   488 
   493 
   489 fun check_code_cmd all_public raw_cs seris thy =
   494 fun check_code_cmd all_public raw_cs seris ctxt =
   490   check_code thy all_public
   495   check_code ctxt all_public
   491     (Code_Thingol.read_const_exprs thy raw_cs) seris;
   496     (Code_Thingol.read_const_exprs ctxt raw_cs) seris;
   492 
   497 
   493 local
   498 local
   494 
   499 
   495 val parse_const_terms = Scan.repeat1 Args.term
   500 val parse_const_terms = Scan.repeat1 Args.term
   496   >> (fn ts => fn thy => map (Code.check_const thy) ts);
   501   >> (fn ts => fn ctxt => map (Code.check_const (Proof_Context.theory_of ctxt)) ts);
   497 
   502 
   498 fun parse_names category parse internalize mark_symbol =
   503 fun parse_names category parse internalize mark_symbol =
   499   Scan.lift (Args.parens (Args.$$$ category)) |-- Scan.repeat1 parse
   504   Scan.lift (Args.parens (Args.$$$ category)) |-- Scan.repeat1 parse
   500   >> (fn xs => fn thy => map (mark_symbol o internalize thy) xs);
   505   >> (fn xs => fn ctxt => map (mark_symbol o internalize ctxt) xs);
   501 
   506 
   502 val parse_consts = parse_names "consts" Args.term
   507 val parse_consts = parse_names "consts" Args.term
   503   Code.check_const Constant;
   508   (Code.check_const o Proof_Context.theory_of) Constant;
   504 
   509 
   505 val parse_types = parse_names "types" (Scan.lift Args.name)
   510 val parse_types = parse_names "types" (Scan.lift Args.name)
   506   Sign.intern_type Type_Constructor;
   511   (Sign.intern_type o Proof_Context.theory_of) Type_Constructor;
   507 
   512 
   508 val parse_classes = parse_names "classes" (Scan.lift Args.name)
   513 val parse_classes = parse_names "classes" (Scan.lift Args.name)
   509   Sign.intern_class Type_Class;
   514   (Sign.intern_class o Proof_Context.theory_of) Type_Class;
   510 
   515 
   511 val parse_instances = parse_names "instances" (Scan.lift (Args.name --| Args.$$$ "::" -- Args.name))
   516 val parse_instances = parse_names "instances" (Scan.lift (Args.name --| Args.$$$ "::" -- Args.name))
   512   (fn thy => fn (raw_tyco, raw_class) => (Sign.intern_class thy raw_tyco, Sign.intern_type thy raw_class))
   517   (fn ctxt => fn (raw_tyco, raw_class) =>
   513     Class_Instance;
   518     let
       
   519       val thy = Proof_Context.theory_of ctxt;
       
   520     in (Sign.intern_class thy raw_tyco, Sign.intern_type thy raw_class) end) Class_Instance;
   514 
   521 
   515 in
   522 in
   516 
   523 
   517 val antiq_setup =
   524 val antiq_setup =
   518   Thy_Output.antiquotation @{binding code_stmts}
   525   Thy_Output.antiquotation @{binding code_stmts}
   519     (parse_const_terms --
   526     (parse_const_terms --
   520       Scan.repeat (parse_consts || parse_types || parse_classes || parse_instances)
   527       Scan.repeat (parse_consts || parse_types || parse_classes || parse_instances)
   521       -- Scan.lift (Args.parens (Args.name -- Scan.option Parse.int)))
   528       -- Scan.lift (Args.parens (Args.name -- Scan.option Parse.int)))
   522     (fn {context = ctxt, ...} => fn ((mk_cs, mk_stmtss), (target, some_width)) =>
   529     (fn {context = ctxt, ...} => fn ((mk_cs, mk_stmtss), (target, some_width)) =>
   523       let val thy = Proof_Context.theory_of ctxt in
   530         present_code ctxt (mk_cs ctxt)
   524         present_code thy (mk_cs thy)
   531           (maps (fn f => f ctxt) mk_stmtss)
   525           (maps (fn f => f thy) mk_stmtss)
   532           target some_width "Example" []);
   526           target some_width "Example" []
       
   527       end);
       
   528 
   533 
   529 end;
   534 end;
   530 
   535 
   531 
   536 
   532 (** serializer configuration **)
   537 (** serializer configuration **)
   533 
   538 
   534 (* reserved symbol names *)
   539 (* reserved symbol names *)
   535 
   540 
   536 fun add_reserved target sym thy =
   541 fun add_reserved target sym thy =
   537   let
   542   let
   538     val (_, data) = collapse_hierarchy thy target;
   543     val (_, data) = collapse_hierarchy (Proof_Context.init_global thy) target;
   539     val _ = if member (op =) (the_reserved data) sym
   544     val _ = if member (op =) (the_reserved data) sym
   540       then error ("Reserved symbol " ^ quote sym ^ " already declared")
   545       then error ("Reserved symbol " ^ quote sym ^ " already declared")
   541       else ();
   546       else ();
   542   in
   547   in
   543     thy
   548     thy
   545   end;
   550   end;
   546 
   551 
   547 
   552 
   548 (* checking of syntax *)
   553 (* checking of syntax *)
   549 
   554 
   550 fun check_const_syntax thy target c syn =
   555 fun check_const_syntax ctxt target c syn =
   551   if Code_Printer.requires_args syn > Code.args_number thy c
   556   if Code_Printer.requires_args syn > Code.args_number (Proof_Context.theory_of ctxt) c
   552   then error ("Too many arguments in syntax for constant " ^ quote c)
   557   then error ("Too many arguments in syntax for constant " ^ quote c)
   553   else Code_Printer.prep_const_syntax thy (the_literals thy target) c syn;
   558   else Code_Printer.prep_const_syntax (Proof_Context.theory_of ctxt) (the_literals ctxt target) c syn;
   554 
   559 
   555 fun check_tyco_syntax thy target tyco syn =
   560 fun check_tyco_syntax ctxt target tyco syn =
   556   if fst syn <> Sign.arity_number thy tyco
   561   if fst syn <> Sign.arity_number (Proof_Context.theory_of ctxt) tyco
   557   then error ("Number of arguments mismatch in syntax for type constructor " ^ quote tyco)
   562   then error ("Number of arguments mismatch in syntax for type constructor " ^ quote tyco)
   558   else syn;
   563   else syn;
   559 
   564 
   560 
   565 
   561 (* custom symbol names *)
   566 (* custom symbol names *)
   567   in
   572   in
   568     Code_Symbol.maps_attr' (arrange false) (arrange false) (arrange false)
   573     Code_Symbol.maps_attr' (arrange false) (arrange false) (arrange false)
   569       (arrange false) (arrange false) (arrange true) x
   574       (arrange false) (arrange false) (arrange true) x
   570   end;
   575   end;
   571 
   576 
   572 fun cert_name_decls thy = cert_syms thy #> arrange_name_decls;
   577 fun cert_name_decls ctxt = cert_syms ctxt #> arrange_name_decls;
   573 
   578 
   574 fun read_name_decls thy = read_syms thy #> arrange_name_decls;
   579 fun read_name_decls ctxt = read_syms ctxt #> arrange_name_decls;
   575 
   580 
   576 fun set_identifier (target, sym_name) = map_identifiers target (Code_Symbol.set_data sym_name);
   581 fun set_identifier (target, sym_name) = map_identifiers target (Code_Symbol.set_data sym_name);
   577 
   582 
   578 fun gen_set_identifiers prep_name_decl raw_name_decls thy =
   583 fun gen_set_identifiers prep_name_decl raw_name_decls thy =
   579   fold set_identifier (prep_name_decl thy raw_name_decls) thy;
   584   fold set_identifier (prep_name_decl (Proof_Context.init_global thy) raw_name_decls) thy;
   580 
   585 
   581 val set_identifiers = gen_set_identifiers cert_name_decls;
   586 val set_identifiers = gen_set_identifiers cert_name_decls;
   582 val set_identifiers_cmd = gen_set_identifiers read_name_decls;
   587 val set_identifiers_cmd = gen_set_identifiers read_name_decls;
   583 
   588 
   584 
   589 
   585 (* custom printings *)
   590 (* custom printings *)
   586 
   591 
   587 fun arrange_printings prep_const thy =
   592 fun arrange_printings prep_const ctxt =
   588   let
   593   let
   589     fun arrange check (sym, target_syns) =
   594     fun arrange check (sym, target_syns) =
   590       map (fn (target, some_syn) => (target, (sym, Option.map (check thy target sym) some_syn))) target_syns;
   595       map (fn (target, some_syn) => (target, (sym, Option.map (check ctxt target sym) some_syn))) target_syns;
   591   in
   596   in
   592     Code_Symbol.maps_attr'
   597     Code_Symbol.maps_attr'
   593       (arrange check_const_syntax) (arrange check_tyco_syntax)
   598       (arrange check_const_syntax) (arrange check_tyco_syntax)
   594         (arrange ((K o K o K) I)) (arrange ((K o K o K) I)) (arrange ((K o K o K) I))
   599         (arrange ((K o K o K) I)) (arrange ((K o K o K) I)) (arrange ((K o K o K) I))
   595         (arrange (fn thy => fn _ => fn _ => fn (raw_content, raw_cs) =>
   600         (arrange (fn ctxt => fn _ => fn _ => fn (raw_content, raw_cs) =>
   596           (Code_Printer.str raw_content, map (prep_const thy) raw_cs)))
   601           (Code_Printer.str raw_content, map (prep_const ctxt) raw_cs)))
   597   end;
   602   end;
   598 
   603 
   599 fun cert_printings thy = cert_syms thy #> arrange_printings cert_const thy;
   604 fun cert_printings ctxt = cert_syms ctxt #> arrange_printings cert_const ctxt;
   600 
   605 
   601 fun read_printings thy = read_syms thy #> arrange_printings Code.read_const thy;
   606 fun read_printings ctxt = read_syms ctxt #> arrange_printings read_const ctxt;
   602 
   607 
   603 fun set_printing (target, sym_syn) = map_printings target (Code_Symbol.set_data sym_syn);
   608 fun set_printing (target, sym_syn) = map_printings target (Code_Symbol.set_data sym_syn);
   604 
   609 
   605 fun gen_set_printings prep_print_decl raw_print_decls thy =
   610 fun gen_set_printings prep_print_decl raw_print_decls thy =
   606   fold set_printing (prep_print_decl thy raw_print_decls) thy;
   611   fold set_printing (prep_print_decl (Proof_Context.init_global thy) raw_print_decls) thy;
   607 
   612 
   608 val set_printings = gen_set_printings cert_printings;
   613 val set_printings = gen_set_printings cert_printings;
   609 val set_printings_cmd = gen_set_printings read_printings;
   614 val set_printings_cmd = gen_set_printings read_printings;
   610 
   615 
   611 
   616 
   678       (Parse.text -- Scan.optional (@{keyword "attach"} |-- Scan.repeat1 Parse.term) [])
   683       (Parse.text -- Scan.optional (@{keyword "attach"} |-- Scan.repeat1 Parse.term) [])
   679       >> (Toplevel.theory o fold set_printings_cmd));
   684       >> (Toplevel.theory o fold set_printings_cmd));
   680 
   685 
   681 val _ =
   686 val _ =
   682   Outer_Syntax.command @{command_spec "export_code"} "generate executable code for constants"
   687   Outer_Syntax.command @{command_spec "export_code"} "generate executable code for constants"
   683     (Parse.!!! code_exprP >> (fn f => Toplevel.keep (f o Toplevel.theory_of)));
   688     (Parse.!!! code_exprP >> (fn f => Toplevel.keep (f o Toplevel.context_of)));
   684 
   689 
   685 
   690 
   686 (** external entrance point -- for codegen tool **)
   691 (** external entrance point -- for codegen tool **)
   687 
   692 
   688 fun codegen_tool thyname cmd_expr =
   693 fun codegen_tool thyname cmd_expr =
   689   let
   694   let
   690     val thy = Thy_Info.get_theory thyname;
   695     val ctxt = Proof_Context.init_global (Thy_Info.get_theory thyname);
   691     val parse = Scan.read Token.stopper (Parse.!!! code_exprP) o
   696     val parse = Scan.read Token.stopper (Parse.!!! code_exprP) o
   692       (filter Token.is_proper o Outer_Syntax.scan Position.none);
   697       (filter Token.is_proper o Outer_Syntax.scan Position.none);
   693   in case parse cmd_expr
   698   in case parse cmd_expr
   694    of SOME f => (writeln "Now generating code..."; f thy)
   699    of SOME f => (writeln "Now generating code..."; f ctxt)
   695     | NONE => error ("Bad directive " ^ quote cmd_expr)
   700     | NONE => error ("Bad directive " ^ quote cmd_expr)
   696   end;
   701   end;
   697 
   702 
   698 
   703 
   699 (** theory setup **)
   704 (** theory setup **)