1 (* Title: Tools/Code/code_target.ML
2 Author: Florian Haftmann, TU Muenchen
4 Generic infrastructure for target language data.
7 signature CODE_TARGET =
9 val cert_tyco: Proof.context -> string -> string
10 val read_tyco: Proof.context -> string -> string
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
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
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
18 val check_code_for: Proof.context -> string -> bool -> Token.T list
19 -> Code_Thingol.program -> bool -> Code_Symbol.T list -> unit
21 val export_code: Proof.context -> bool -> string list
22 -> (((string * string) * Path.T option) * Token.T list) list -> unit
23 val produce_code: Proof.context -> bool -> string list
24 -> string -> int option -> string -> Token.T list -> (string * string) list * string option list
25 val present_code: Proof.context -> string list -> Code_Symbol.T list
26 -> string -> int option -> string -> Token.T list -> string
27 val check_code: Proof.context -> bool -> string list
28 -> ((string * bool) * Token.T list) list -> unit
30 val generatedN: string
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
33 -> (string * string) list * string
36 type literals = Code_Printer.literals
37 val add_target: string * { serializer: serializer, literals: literals,
38 check: { env_var: string, make_destination: Path.T -> Path.T, make_command: string -> string } }
40 val extend_target: string *
41 (string * (Code_Thingol.program -> Code_Thingol.program))
43 val assert_target: Proof.context -> string -> string
44 val the_literals: Proof.context -> string -> literals
46 val parse_args: 'a parser -> Token.T list -> 'a
47 val serialization: (int -> Path.T option -> 'a -> unit)
48 -> (Code_Symbol.T list -> int -> 'a -> (string * string) list * (Code_Symbol.T -> string option))
49 -> 'a -> serialization
50 val set_default_code_width: int -> theory -> theory
52 type ('a, 'b, 'c, 'd, 'e, 'f) symbol_attr_decl
54 val set_identifiers: (string, string, string, string, string, string) symbol_attr_decl
56 val set_printings: (Code_Printer.raw_const_syntax, Code_Printer.tyco_syntax, string, unit, unit, (string * string list)) symbol_attr_decl
58 val add_reserved: string -> string -> theory -> theory
60 val codegen_tool: string (*theory name*) -> string (*export_code expr*) -> unit
62 val setup: theory -> theory
65 structure Code_Target : CODE_TARGET =
68 open Basic_Code_Symbol;
69 open Basic_Code_Thingol;
71 type literals = Code_Printer.literals;
72 type ('a, 'b, 'c, 'd, 'e, 'f) symbol_attr_decl =
73 (string * (string * 'a option) list, string * (string * 'b option) list,
74 class * (string * 'c option) list, (class * class) * (string * 'd option) list,
75 (class * string) * (string * 'e option) list,
76 string * (string * 'f option) list) Code_Symbol.attr;
77 type identifier_data = (string list * string, string list * string, string list * string, string list * string,
78 string list * string, string list * string) Code_Symbol.data;
80 type tyco_syntax = Code_Printer.tyco_syntax;
81 type raw_const_syntax = Code_Printer.raw_const_syntax;
84 (** checking and parsing of symbols **)
86 fun cert_const ctxt const =
88 val _ = if Sign.declared_const (Proof_Context.theory_of ctxt) const then ()
89 else error ("No such constant: " ^ quote const);
92 fun read_const ctxt = Code.read_const (Proof_Context.theory_of ctxt);
94 fun cert_tyco ctxt tyco =
96 val _ = if Sign.declared_tyname (Proof_Context.theory_of ctxt) tyco then ()
97 else error ("No such type constructor: " ^ quote tyco);
101 #1 o dest_Type o Proof_Context.read_type_name ctxt {proper = true, strict = true};
103 fun cert_class ctxt class =
105 val _ = Axclass.get_info (Proof_Context.theory_of ctxt) class;
108 val parse_classrel_ident = Parse.class --| @{keyword "<"} -- Parse.class;
110 fun cert_inst ctxt (class, tyco) =
111 (cert_class ctxt class, cert_tyco ctxt tyco);
113 fun read_inst ctxt (raw_tyco, raw_class) =
114 (read_tyco ctxt raw_tyco, Proof_Context.read_class ctxt raw_class);
116 val parse_inst_ident = Parse.xname --| @{keyword "::"} -- Parse.class;
119 Code_Symbol.map_attr (apfst (cert_const ctxt)) (apfst (cert_tyco ctxt))
120 (apfst (cert_class ctxt)) ((apfst o pairself) (cert_class ctxt)) (apfst (cert_inst ctxt)) I;
123 Code_Symbol.map_attr (apfst (read_const ctxt)) (apfst (read_tyco ctxt))
124 (apfst (Proof_Context.read_class ctxt)) ((apfst o pairself) (Proof_Context.read_class ctxt)) (apfst (read_inst ctxt)) I;
126 fun check_name is_module s =
128 val _ = if s = "" then error "Bad empty code name" else ();
129 val xs = Long_Name.explode s;
130 val xs' = if is_module
131 then map (Name.desymbolize true) xs
132 else if length xs < 2
133 then error ("Bad code name without module component: " ^ quote s)
136 val (ys, y) = split_last xs;
137 val ys' = map (Name.desymbolize true) ys;
138 val y' = Name.desymbolize false y;
141 then if is_module then (xs, "") else split_last xs
142 else error ("Invalid code name: " ^ quote s ^ "\n"
143 ^ "better try " ^ quote (Long_Name.implode xs'))
147 (** serializations and serializer **)
149 (* serialization: abstract nonsense to cover different destinies for generated code *)
151 datatype destination = Export of Path.T option | Produce | Present of Code_Symbol.T list;
152 type serialization = int -> destination -> ((string * string) list * (Code_Symbol.T -> string option)) option;
154 fun serialization output _ content width (Export some_path) =
155 (output width some_path content; NONE)
156 | serialization _ string content width Produce =
157 string [] width content |> SOME
158 | serialization _ string content width (Present syms) =
159 string syms width content
160 |> (apfst o map o apsnd) (Pretty.output (SOME width) o Pretty.str)
163 fun export some_path f = (f (Export some_path); ());
164 fun produce f = the (f Produce);
165 fun present syms f = space_implode "\n\n" (map snd (fst (the (f (Present syms)))));
168 (* serializers: functions producing serializations *)
170 type serializer = Token.T list
174 reserved_syms: string list,
175 identifiers: identifier_data,
176 includes: (string * Pretty.T) list,
177 class_syntax: string -> string option,
178 tyco_syntax: string -> Code_Printer.tyco_syntax option,
179 const_syntax: string -> Code_Printer.const_syntax option }
180 -> Code_Symbol.T list
181 -> Code_Thingol.program
184 datatype description =
185 Fundamental of { serializer: serializer,
187 check: { env_var: string, make_destination: Path.T -> Path.T,
188 make_command: string -> string } }
189 | Extension of string *
190 (Code_Thingol.program -> Code_Thingol.program);
195 datatype target = Target of {
197 description: description,
198 reserved: string list,
199 identifiers: identifier_data,
200 printings: (Code_Printer.const_syntax, Code_Printer.tyco_syntax, string, unit, unit,
201 (Pretty.T * string list)) Code_Symbol.data
204 fun make_target ((serial, description), (reserved, (identifiers, printings))) =
205 Target { serial = serial, description = description, reserved = reserved,
206 identifiers = identifiers, printings = printings };
207 fun map_target f (Target { serial, description, reserved, identifiers, printings }) =
208 make_target (f ((serial, description), (reserved, (identifiers, printings))));
209 fun merge_target strict target (Target { serial = serial1, description = description,
210 reserved = reserved1, identifiers = identifiers1, printings = printings1 },
211 Target { serial = serial2, description = _,
212 reserved = reserved2, identifiers = identifiers2, printings = printings2 }) =
213 if serial1 = serial2 orelse not strict then
214 make_target ((serial1, description), (merge (op =) (reserved1, reserved2),
215 (Code_Symbol.merge_data (identifiers1, identifiers2),
216 Code_Symbol.merge_data (printings1, printings2))))
218 error ("Incompatible targets: " ^ quote target);
220 fun the_description (Target { description, ... }) = description;
221 fun the_reserved (Target { reserved, ... }) = reserved;
222 fun the_identifiers (Target { identifiers , ... }) = identifiers;
223 fun the_printings (Target { printings, ... }) = printings;
225 structure Targets = Theory_Data
227 type T = target Symtab.table * int;
228 val empty = (Symtab.empty, 80);
230 fun merge ((target1, width1), (target2, width2)) : T =
231 (Symtab.join (merge_target true) (target1, target2), Int.max (width1, width2));
234 fun assert_target ctxt target =
235 if Symtab.defined (fst (Targets.get (Proof_Context.theory_of ctxt))) target
237 else error ("Unknown code target language: " ^ quote target);
239 fun put_target (target, seri) thy =
241 val lookup_target = Symtab.lookup (fst (Targets.get thy));
243 of Extension (super, _) => if is_some (lookup_target super) then ()
244 else error ("Unknown code target language: " ^ quote super)
246 val overwriting = case (Option.map the_description o lookup_target) target
248 | SOME (Extension _) => true
249 | SOME (Fundamental _) => (case seri
250 of Extension _ => error ("Will not overwrite existing target " ^ quote target)
252 val _ = if overwriting
253 then warning ("Overwriting existing target " ^ quote target)
257 |> (Targets.map o apfst o Symtab.update)
258 (target, make_target ((serial (), seri),
259 ([], (Code_Symbol.empty_data, Code_Symbol.empty_data))))
262 fun add_target (target, seri) = put_target (target, Fundamental seri);
263 fun extend_target (target, (super, modify)) =
264 put_target (target, Extension (super, modify));
266 fun map_target_data target f thy =
268 val _ = assert_target (Proof_Context.init_global thy) target;
271 |> (Targets.map o apfst o Symtab.map_entry target o map_target o apsnd) f
274 fun map_reserved target =
275 map_target_data target o apfst;
276 fun map_identifiers target =
277 map_target_data target o apsnd o apfst;
278 fun map_printings target =
279 map_target_data target o apsnd o apsnd;
281 fun set_default_code_width k = (Targets.map o apsnd) (K k);
284 (** serializer usage **)
288 fun the_fundamental ctxt =
290 val (targets, _) = Targets.get (Proof_Context.theory_of ctxt);
291 fun fundamental target = case Symtab.lookup targets target
292 of SOME data => (case the_description data
293 of Fundamental data => data
294 | Extension (super, _) => fundamental super)
295 | NONE => error ("Unknown code target language: " ^ quote target);
298 fun the_literals ctxt = #literals o the_fundamental ctxt;
300 fun collapse_hierarchy ctxt =
302 val (targets, _) = Targets.get (Proof_Context.theory_of ctxt);
303 fun collapse target =
305 val data = case Symtab.lookup targets target
307 | NONE => error ("Unknown code target language: " ^ quote target);
308 in case the_description data
309 of Fundamental _ => (I, data)
310 | Extension (super, modify) => let
311 val (modify', data') = collapse super
312 in (modify' #> modify, merge_target false target (data', data)) end
318 fun activate_target ctxt target =
320 val thy = Proof_Context.theory_of ctxt;
321 val (_, default_width) = Targets.get thy;
322 val (modify, data) = collapse_hierarchy ctxt target;
323 in (default_width, data, modify) end;
325 fun project_program ctxt syms_hidden syms1 program2 =
327 val syms2 = subtract (op =) syms_hidden syms1;
328 val program3 = Code_Symbol.Graph.restrict (not o member (op =) syms_hidden) program2;
329 val syms4 = Code_Symbol.Graph.all_succs program3 syms2;
330 val unimplemented = Code_Thingol.unimplemented program3;
332 if null unimplemented then ()
333 else error ("No code equations for " ^
334 commas (map (Proof_Context.markup_const ctxt) unimplemented));
335 val program4 = Code_Symbol.Graph.restrict (member (op =) syms4) program3;
336 in (syms4, program4) end;
338 fun prepare_serializer ctxt (serializer : serializer) reserved identifiers
339 printings module_name args proto_program syms =
341 val syms_hidden = Code_Symbol.symbols_of printings;
342 val (syms_all, program) = project_program ctxt syms_hidden syms proto_program;
343 fun select_include (name, (content, cs)) =
344 if null cs orelse exists (fn c => member (op =) syms_all (Constant c)) cs
345 then SOME (name, content) else NONE;
346 val includes = map_filter select_include (Code_Symbol.dest_module_data printings);
348 (serializer args ctxt {
349 module_name = module_name,
350 reserved_syms = reserved,
351 identifiers = identifiers,
353 const_syntax = Code_Symbol.lookup_constant_data printings,
354 tyco_syntax = Code_Symbol.lookup_type_constructor_data printings,
355 class_syntax = Code_Symbol.lookup_type_class_data printings },
356 (subtract (op =) syms_hidden syms, program))
359 fun mount_serializer ctxt target some_width module_name args program syms =
361 val (default_width, data, modify) = activate_target ctxt target;
362 val serializer = case the_description data
363 of Fundamental seri => #serializer seri;
364 val (prepared_serializer, (prepared_syms, prepared_program)) =
365 prepare_serializer ctxt serializer
366 (the_reserved data) (the_identifiers data) (the_printings data)
367 module_name args (modify program) syms
368 val width = the_default default_width some_width;
369 in (fn program => fn syms => prepared_serializer syms program width, (prepared_syms, prepared_program)) end;
371 fun invoke_serializer ctxt target some_width raw_module_name args program all_public syms =
373 val module_name = if raw_module_name = "" then ""
374 else (check_name true raw_module_name; raw_module_name)
375 val (mounted_serializer, (prepared_syms, prepared_program)) =
376 mount_serializer ctxt target some_width module_name args program syms;
377 in mounted_serializer prepared_program (if all_public then [] else prepared_syms) end;
379 fun assert_module_name "" = error "Empty module name not allowed here"
380 | assert_module_name module_name = module_name;
382 fun using_master_directory ctxt =
383 Option.map (Path.append (File.pwd ()) o Path.append (Thy_Load.master_directory (Proof_Context.theory_of ctxt)));
387 val generatedN = "Generated_Code";
389 fun export_code_for ctxt some_path target some_width module_name args =
390 export (using_master_directory ctxt some_path)
391 ooo invoke_serializer ctxt target some_width module_name args;
393 fun produce_code_for ctxt target some_width module_name args =
395 val serializer = invoke_serializer ctxt target some_width (assert_module_name module_name) args;
396 in fn program => fn all_public => fn syms =>
397 produce (serializer program all_public syms) |> apsnd (fn deresolve => map deresolve syms)
400 fun present_code_for ctxt target some_width module_name args =
402 val serializer = invoke_serializer ctxt target some_width (assert_module_name module_name) args;
403 in fn program => fn (syms, selects) =>
404 present selects (serializer program false syms)
407 fun check_code_for ctxt target strict args program all_public syms =
409 val { env_var, make_destination, make_command } =
410 (#check o the_fundamental ctxt) target;
413 val destination = make_destination p;
414 val _ = export (SOME destination) (invoke_serializer ctxt target (SOME 80)
415 generatedN args program all_public syms);
416 val cmd = make_command generatedN;
418 if Isabelle_System.bash ("cd " ^ File.shell_path p ^ " && " ^ cmd ^ " 2>&1") <> 0
419 then error ("Code check failed for " ^ target ^ ": " ^ cmd)
423 if getenv env_var = ""
425 then error (env_var ^ " not set; cannot check code for " ^ target)
426 else warning (env_var ^ " not set; skipped checking code for " ^ target)
427 else Isabelle_System.with_tmp_dir "Code_Test" ext_check
430 fun evaluation mounted_serializer prepared_program syms all_public ((vs, ty), t) =
432 val _ = if Code_Thingol.contains_dict_var t then
433 error "Term to be evaluated contains free dictionaries" else ();
434 val v' = singleton (Name.variant_list (map fst vs)) "a";
435 val vs' = (v', []) :: vs;
436 val ty' = ITyVar v' `-> ty;
437 val program = prepared_program
438 |> Code_Symbol.Graph.new_node (Code_Symbol.value,
439 Code_Thingol.Fun (((vs', ty'), [(([IVar NONE], t), (NONE, true))]), NONE))
440 |> fold (curry (perhaps o try o
441 Code_Symbol.Graph.add_edge) Code_Symbol.value) syms;
442 val (program_code, deresolve) =
443 produce (mounted_serializer program (if all_public then [] else [Code_Symbol.value]));
444 val value_name = the (deresolve Code_Symbol.value);
445 in (program_code, value_name) end;
447 fun evaluator ctxt target program syms =
449 val (mounted_serializer, (_, prepared_program)) =
450 mount_serializer ctxt target NONE generatedN [] program syms;
451 in evaluation mounted_serializer prepared_program syms end;
456 (* code generation *)
458 fun prep_destination "" = NONE
459 | prep_destination s = SOME (Path.explode s);
461 fun export_code ctxt all_public cs seris =
463 val thy = Proof_Context.theory_of ctxt;
464 val program = Code_Thingol.consts_program thy cs;
465 val _ = map (fn (((target, module_name), some_path), args) =>
466 export_code_for ctxt some_path target NONE module_name args program all_public (map Constant cs)) seris;
469 fun export_code_cmd all_public raw_cs seris ctxt =
470 export_code ctxt all_public
471 (Code_Thingol.read_const_exprs ctxt raw_cs)
472 ((map o apfst o apsnd) prep_destination seris);
474 fun produce_code ctxt all_public cs target some_width some_module_name args =
476 val thy = Proof_Context.theory_of ctxt;
477 val program = Code_Thingol.consts_program thy cs;
478 in produce_code_for ctxt target some_width some_module_name args program all_public (map Constant cs) end;
480 fun present_code ctxt cs syms target some_width some_module_name args =
482 val thy = Proof_Context.theory_of ctxt;
483 val program = Code_Thingol.consts_program thy cs;
484 in present_code_for ctxt target some_width some_module_name args program (map Constant cs, syms) end;
486 fun check_code ctxt all_public cs seris =
488 val thy = Proof_Context.theory_of ctxt;
489 val program = Code_Thingol.consts_program thy cs;
490 val _ = map (fn ((target, strict), args) =>
491 check_code_for ctxt target strict args program all_public (map Constant cs)) seris;
494 fun check_code_cmd all_public raw_cs seris ctxt =
495 check_code ctxt all_public
496 (Code_Thingol.read_const_exprs ctxt raw_cs) seris;
500 val parse_const_terms = Scan.repeat1 Args.term
501 >> (fn ts => fn ctxt => map (Code.check_const (Proof_Context.theory_of ctxt)) ts);
503 fun parse_names category parse internalize mark_symbol =
504 Scan.lift (Args.parens (Args.$$$ category)) |-- Scan.repeat1 parse
505 >> (fn xs => fn ctxt => map (mark_symbol o internalize ctxt) xs);
507 val parse_consts = parse_names "consts" Args.term
508 (Code.check_const o Proof_Context.theory_of) Constant;
510 val parse_types = parse_names "types" (Scan.lift Args.name)
511 (Sign.intern_type o Proof_Context.theory_of) Type_Constructor;
513 val parse_classes = parse_names "classes" (Scan.lift Args.name)
514 (Sign.intern_class o Proof_Context.theory_of) Type_Class;
516 val parse_instances = parse_names "instances" (Scan.lift (Args.name --| Args.$$$ "::" -- Args.name))
517 (fn ctxt => fn (raw_tyco, raw_class) =>
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;
525 Thy_Output.antiquotation @{binding code_stmts}
526 (parse_const_terms --
527 Scan.repeat (parse_consts || parse_types || parse_classes || parse_instances)
528 -- Scan.lift (Args.parens (Args.name -- Scan.option Parse.int)))
529 (fn {context = ctxt, ...} => fn ((mk_cs, mk_stmtss), (target, some_width)) =>
530 present_code ctxt (mk_cs ctxt)
531 (maps (fn f => f ctxt) mk_stmtss)
532 target some_width "Example" []);
537 (** serializer configuration **)
539 (* reserved symbol names *)
541 fun add_reserved target sym thy =
543 val (_, data) = collapse_hierarchy (Proof_Context.init_global thy) target;
544 val _ = if member (op =) (the_reserved data) sym
545 then error ("Reserved symbol " ^ quote sym ^ " already declared")
549 |> map_reserved target (insert (op =) sym)
553 (* checking of syntax *)
555 fun check_const_syntax ctxt target c syn =
556 if Code_Printer.requires_args syn > Code.args_number (Proof_Context.theory_of ctxt) c
557 then error ("Too many arguments in syntax for constant " ^ quote c)
558 else Code_Printer.prep_const_syntax (Proof_Context.theory_of ctxt) (the_literals ctxt target) c syn;
560 fun check_tyco_syntax ctxt target tyco syn =
561 if fst syn <> Sign.arity_number (Proof_Context.theory_of ctxt) tyco
562 then error ("Number of arguments mismatch in syntax for type constructor " ^ quote tyco)
566 (* custom symbol names *)
568 fun arrange_name_decls x =
570 fun arrange is_module (sym, target_names) = map (fn (target, some_name) =>
571 (target, (sym, Option.map (check_name is_module) some_name))) target_names;
573 Code_Symbol.maps_attr' (arrange false) (arrange false) (arrange false)
574 (arrange false) (arrange false) (arrange true) x
577 fun cert_name_decls ctxt = cert_syms ctxt #> arrange_name_decls;
579 fun read_name_decls ctxt = read_syms ctxt #> arrange_name_decls;
581 fun set_identifier (target, sym_name) = map_identifiers target (Code_Symbol.set_data sym_name);
583 fun gen_set_identifiers prep_name_decl raw_name_decls thy =
584 fold set_identifier (prep_name_decl (Proof_Context.init_global thy) raw_name_decls) thy;
586 val set_identifiers = gen_set_identifiers cert_name_decls;
587 val set_identifiers_cmd = gen_set_identifiers read_name_decls;
590 (* custom printings *)
592 fun arrange_printings prep_const ctxt =
594 fun arrange check (sym, target_syns) =
595 map (fn (target, some_syn) => (target, (sym, Option.map (check ctxt target sym) some_syn))) target_syns;
597 Code_Symbol.maps_attr'
598 (arrange check_const_syntax) (arrange check_tyco_syntax)
599 (arrange ((K o K o K) I)) (arrange ((K o K o K) I)) (arrange ((K o K o K) I))
600 (arrange (fn ctxt => fn _ => fn _ => fn (raw_content, raw_cs) =>
601 (Code_Printer.str raw_content, map (prep_const ctxt) raw_cs)))
604 fun cert_printings ctxt = cert_syms ctxt #> arrange_printings cert_const ctxt;
606 fun read_printings ctxt = read_syms ctxt #> arrange_printings read_const ctxt;
608 fun set_printing (target, sym_syn) = map_printings target (Code_Symbol.set_data sym_syn);
610 fun gen_set_printings prep_print_decl raw_print_decls thy =
611 fold set_printing (prep_print_decl (Proof_Context.init_global thy) raw_print_decls) thy;
613 val set_printings = gen_set_printings cert_printings;
614 val set_printings_cmd = gen_set_printings read_printings;
617 (* concrete syntax *)
619 fun parse_args f args =
620 case Scan.read Token.stopper f args
622 | NONE => error "Bad serializer arguments";
627 fun parse_single_symbol_pragma parse_keyword parse_isa parse_target =
628 parse_keyword |-- Parse.!!! (parse_isa --| (@{keyword "\<rightharpoonup>"} || @{keyword "=>"})
629 -- Parse.and_list1 (@{keyword "("} |-- (Parse.name --| @{keyword ")"} -- Scan.option parse_target)));
631 fun parse_symbol_pragma parse_const parse_tyco parse_class parse_classrel parse_inst parse_module =
632 parse_single_symbol_pragma @{keyword "constant"} Parse.term parse_const
634 || parse_single_symbol_pragma @{keyword "type_constructor"} Parse.type_const parse_tyco
636 || parse_single_symbol_pragma @{keyword "type_class"} Parse.class parse_class
638 || parse_single_symbol_pragma @{keyword "class_relation"} parse_classrel_ident parse_classrel
640 || parse_single_symbol_pragma @{keyword "class_instance"} parse_inst_ident parse_inst
642 || parse_single_symbol_pragma @{keyword "code_module"} Parse.name parse_module
643 >> Code_Symbol.Module;
645 fun parse_symbol_pragmas parse_const parse_tyco parse_class parse_classrel parse_inst parse_module =
646 Parse.enum1 "|" (Parse.group (fn () => "code symbol pragma")
647 (parse_symbol_pragma parse_const parse_tyco parse_class parse_classrel parse_inst parse_module));
649 val code_expr_argsP = Scan.optional (@{keyword "("} |-- Args.parse --| @{keyword ")"}) [];
651 fun code_expr_inP all_public raw_cs =
652 Scan.repeat (@{keyword "in"} |-- Parse.!!! (Parse.name
653 -- Scan.optional (@{keyword "module_name"} |-- Parse.name) ""
654 -- Scan.optional (@{keyword "file"} |-- Parse.name) ""
656 >> (fn seri_args => export_code_cmd all_public raw_cs seri_args);
658 fun code_expr_checkingP all_public raw_cs =
659 (@{keyword "checking"} |-- Parse.!!!
660 (Scan.repeat (Parse.name -- ((@{keyword "?"} |-- Scan.succeed false) || Scan.succeed true)
661 -- code_expr_argsP)))
662 >> (fn seri_args => check_code_cmd all_public raw_cs seri_args);
664 val code_exprP = (Scan.optional (@{keyword "open"} |-- Scan.succeed true) false
665 -- Scan.repeat1 Parse.term)
666 :|-- (fn (all_public, raw_cs) => (code_expr_checkingP all_public raw_cs || code_expr_inP all_public raw_cs));
669 Outer_Syntax.command @{command_spec "code_reserved"}
670 "declare words as reserved for target language"
671 (Parse.name -- Scan.repeat1 Parse.name
672 >> (fn (target, reserveds) => (Toplevel.theory o fold (add_reserved target)) reserveds));
675 Outer_Syntax.command @{command_spec "code_identifier"} "declare mandatory names for code symbols"
676 (parse_symbol_pragmas Parse.name Parse.name Parse.name Parse.name Parse.name Parse.name
677 >> (Toplevel.theory o fold set_identifiers_cmd));
680 Outer_Syntax.command @{command_spec "code_printing"} "declare dedicated printing for code symbols"
681 (parse_symbol_pragmas (Code_Printer.parse_const_syntax) (Code_Printer.parse_tyco_syntax)
682 Parse.string (Parse.minus >> K ()) (Parse.minus >> K ())
683 (Parse.text -- Scan.optional (@{keyword "attach"} |-- Scan.repeat1 Parse.term) [])
684 >> (Toplevel.theory o fold set_printings_cmd));
687 Outer_Syntax.command @{command_spec "export_code"} "generate executable code for constants"
688 (Parse.!!! code_exprP >> (fn f => Toplevel.keep (f o Toplevel.context_of)));
691 (** external entrance point -- for codegen tool **)
693 fun codegen_tool thyname cmd_expr =
695 val ctxt = Proof_Context.init_global (Thy_Info.get_theory thyname);
696 val parse = Scan.read Token.stopper (Parse.!!! code_exprP) o
697 (filter Token.is_proper o Outer_Syntax.scan Position.none);
698 in case parse cmd_expr
699 of SOME f => (writeln "Now generating code..."; f ctxt)
700 | NONE => error ("Bad directive " ^ quote cmd_expr)
706 val setup = antiq_setup;