| author | bulwahn | 
| Mon, 06 Dec 2010 10:52:48 +0100 | |
| changeset 40976 | 8df0a190df1e | 
| parent 39817 | 5228c6b20273 | 
| child 41307 | bb8468ae414e | 
| permissions | -rw-r--r-- | 
| 37745 
6315b6426200
checking generated code for various target languages
 haftmann parents: 
37528diff
changeset | 1 | (* Title: Tools/Code/code_target.ML | 
| 24219 | 2 | Author: Florian Haftmann, TU Muenchen | 
| 3 | ||
| 38910 | 4 | Generic infrastructure for target language data. | 
| 24219 | 5 | *) | 
| 6 | ||
| 7 | signature CODE_TARGET = | |
| 8 | sig | |
| 36471 | 9 | val cert_tyco: theory -> string -> string | 
| 10 | val read_tyco: theory -> string -> string | |
| 39057 
c6d146ed07ae
manage statement selection for presentation wholly through markup
 haftmann parents: 
39056diff
changeset | 11 | val read_const_exprs: theory -> string list -> string list | 
| 36471 | 12 | |
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 13 | val export_code_for: theory -> Path.T option -> string -> int option -> string -> Token.T list | 
| 38918 | 14 | -> Code_Thingol.naming -> Code_Thingol.program -> string list -> unit | 
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 15 | val produce_code_for: theory -> string -> int option -> string -> Token.T list | 
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 16 | -> Code_Thingol.naming -> Code_Thingol.program -> string list -> string * string option list | 
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 17 | val present_code_for: theory -> string -> int option -> string -> Token.T list | 
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 18 | -> Code_Thingol.naming -> Code_Thingol.program -> string list * string list -> string | 
| 38918 | 19 | val check_code_for: theory -> string -> bool -> Token.T list | 
| 20 | -> Code_Thingol.naming -> Code_Thingol.program -> string list -> unit | |
| 21 | ||
| 22 | val export_code: theory -> string list | |
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 23 | -> (((string * string) * Path.T option) * Token.T list) list -> unit | 
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 24 | val produce_code: theory -> string list | 
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 25 | -> string -> int option -> string -> Token.T list -> string * string option list | 
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 26 | val present_code: theory -> string list -> (Code_Thingol.naming -> string list) | 
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 27 | -> string -> int option -> string -> Token.T list -> string | 
| 38918 | 28 | val check_code: theory -> string list | 
| 29 | -> ((string * bool) * Token.T list) list -> unit | |
| 30 | ||
| 28054 | 31 | type serializer | 
| 34152 | 32 | type literals = Code_Printer.literals | 
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 33 |   val add_target: string * { serializer: serializer, literals: literals,
 | 
| 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 34 |     check: { env_var: string, make_destination: Path.T -> Path.T,
 | 
| 38863 
9070a7c356c9
code checking: compiler invocation happens in same directory as generated file -- avoid problem with different path representations on cygwin
 haftmann parents: 
38784diff
changeset | 35 | make_command: string -> string -> string } } -> theory -> theory | 
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 36 | val extend_target: string * | 
| 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 37 | (string * (Code_Thingol.naming -> Code_Thingol.program -> Code_Thingol.program)) | 
| 28054 | 38 | -> theory -> theory | 
| 39 | val assert_target: theory -> string -> string | |
| 38918 | 40 | val the_literals: theory -> string -> literals | 
| 28054 | 41 | type serialization | 
| 36959 
f5417836dbea
renamed structure OuterLex to Token and type token to Token.T, keeping legacy aliases for some time;
 wenzelm parents: 
36537diff
changeset | 42 | val parse_args: 'a parser -> Token.T list -> 'a | 
| 38916 | 43 | val serialization: (int -> Path.T option -> 'a -> unit) | 
| 39102 | 44 | -> (string list -> int -> 'a -> string * (string -> string option)) | 
| 38925 | 45 | -> 'a -> serialization | 
| 38918 | 46 | val set_default_code_width: int -> theory -> theory | 
| 38917 | 47 | |
| 28054 | 48 | val allow_abort: string -> theory -> theory | 
| 34152 | 49 | type tyco_syntax = Code_Printer.tyco_syntax | 
| 37876 | 50 | type const_syntax = Code_Printer.const_syntax | 
| 38923 | 51 | val add_class_syntax: string -> class -> string option -> theory -> theory | 
| 52 | val add_instance_syntax: string -> class * string -> unit option -> theory -> theory | |
| 53 | val add_tyco_syntax: string -> string -> tyco_syntax option -> theory -> theory | |
| 54 | val add_const_syntax: string -> string -> const_syntax option -> theory -> theory | |
| 28054 | 55 | val add_reserved: string -> string -> theory -> theory | 
| 33969 | 56 | val add_include: string -> string * (string * string list) option -> theory -> theory | 
| 39646 | 57 | |
| 39750 
c0099428ca7b
consider quick_and_dirty option before loading theory
 haftmann parents: 
39679diff
changeset | 58 | val codegen_tool: string (*theory name*) -> string (*export_code expr*) -> unit | 
| 24219 | 59 | end; | 
| 60 | ||
| 28054 | 61 | structure Code_Target : CODE_TARGET = | 
| 24219 | 62 | struct | 
| 63 | ||
| 28054 | 64 | open Basic_Code_Thingol; | 
| 34152 | 65 | |
| 66 | type literals = Code_Printer.literals; | |
| 67 | type tyco_syntax = Code_Printer.tyco_syntax; | |
| 37876 | 68 | type const_syntax = Code_Printer.const_syntax; | 
| 34152 | 69 | |
| 24219 | 70 | |
| 38923 | 71 | (** abstract nonsense **) | 
| 24219 | 72 | |
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 73 | datatype destination = Export of Path.T option | Produce | Present of string list; | 
| 39102 | 74 | type serialization = int -> destination -> (string * (string -> string option)) option; | 
| 27014 
a5f53d9d2b60
yet another attempt to circumvent printmode problems
 haftmann parents: 
27001diff
changeset | 75 | |
| 39659 | 76 | fun serialization output _ content width (Export some_path) = | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 77 | (output width some_path content; NONE) | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 78 | | serialization _ string content width Produce = | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 79 | string [] width content |> SOME | 
| 39659 | 80 | | serialization _ string content width (Present stmt_names) = | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 81 | string stmt_names width content | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 82 | |> apfst (Pretty.output (SOME width) o Pretty.str) | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 83 | |> SOME; | 
| 39659 | 84 | |
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 85 | fun export some_path f = (f (Export some_path); ()); | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 86 | fun produce f = the (f Produce); | 
| 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 87 | fun present stmt_names f = fst (the (f (Present stmt_names))); | 
| 38917 | 88 | |
| 24219 | 89 | |
| 28054 | 90 | (** theory data **) | 
| 91 | ||
| 38923 | 92 | datatype symbol_syntax_data = Symbol_Syntax_Data of {
 | 
| 28690 | 93 | class: string Symtab.table, | 
| 30648 
17365ef082f3
clarified relationship of modules Code_Name and Code_Printer
 haftmann parents: 
30513diff
changeset | 94 | instance: unit Symreltab.table, | 
| 34152 | 95 | tyco: Code_Printer.tyco_syntax Symtab.table, | 
| 37876 | 96 | const: Code_Printer.const_syntax Symtab.table | 
| 28054 | 97 | }; | 
| 27000 | 98 | |
| 38923 | 99 | fun make_symbol_syntax_data ((class, instance), (tyco, const)) = | 
| 100 |   Symbol_Syntax_Data { class = class, instance = instance, tyco = tyco, const = const };
 | |
| 101 | fun map_symbol_syntax_data f (Symbol_Syntax_Data { class, instance, tyco, const }) =
 | |
| 102 | make_symbol_syntax_data (f ((class, instance), (tyco, const))); | |
| 103 | fun merge_symbol_syntax_data | |
| 104 |   (Symbol_Syntax_Data { class = class1, instance = instance1, tyco = tyco1, const = const1 },
 | |
| 105 |     Symbol_Syntax_Data { class = class2, instance = instance2, tyco = tyco2, const = const2 }) =
 | |
| 106 | make_symbol_syntax_data ( | |
| 28054 | 107 | (Symtab.join (K snd) (class1, class2), | 
| 30648 
17365ef082f3
clarified relationship of modules Code_Name and Code_Printer
 haftmann parents: 
30513diff
changeset | 108 | Symreltab.join (K snd) (instance1, instance2)), | 
| 28054 | 109 | (Symtab.join (K snd) (tyco1, tyco2), | 
| 110 | Symtab.join (K snd) (const1, const2)) | |
| 111 | ); | |
| 112 | ||
| 39142 | 113 | type serializer = Token.T list | 
| 114 |   -> {
 | |
| 38926 | 115 | labelled_name: string -> string, | 
| 116 | reserved_syms: string list, | |
| 117 | includes: (string * Pretty.T) list, | |
| 118 | module_alias: string -> string option, | |
| 119 | class_syntax: string -> string option, | |
| 120 | tyco_syntax: string -> Code_Printer.tyco_syntax option, | |
| 121 | const_syntax: string -> Code_Printer.activated_const_syntax option, | |
| 39142 | 122 | program: Code_Thingol.program } | 
| 28054 | 123 | -> serialization; | 
| 27000 | 124 | |
| 38909 | 125 | datatype description = Fundamental of { serializer: serializer,
 | 
| 38910 | 126 | literals: literals, | 
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 127 |       check: { env_var: string, make_destination: Path.T -> Path.T,
 | 
| 38863 
9070a7c356c9
code checking: compiler invocation happens in same directory as generated file -- avoid problem with different path representations on cygwin
 haftmann parents: 
38784diff
changeset | 128 | make_command: string -> string -> string } } | 
| 38909 | 129 | | Extension of string * | 
| 130 | (Code_Thingol.naming -> Code_Thingol.program -> Code_Thingol.program); | |
| 28054 | 131 | |
| 132 | datatype target = Target of {
 | |
| 133 | serial: serial, | |
| 37821 | 134 | description: description, | 
| 28054 | 135 | reserved: string list, | 
| 28926 | 136 | includes: (Pretty.T * string list) Symtab.table, | 
| 38925 | 137 | module_alias: string Symtab.table, | 
| 138 | symbol_syntax: symbol_syntax_data | |
| 28054 | 139 | }; | 
| 27103 | 140 | |
| 38925 | 141 | fun make_target ((serial, description), ((reserved, includes), (module_alias, symbol_syntax))) = | 
| 37821 | 142 |   Target { serial = serial, description = description, reserved = reserved, 
 | 
| 38925 | 143 | includes = includes, module_alias = module_alias, symbol_syntax = symbol_syntax }; | 
| 144 | fun map_target f ( Target { serial, description, reserved, includes, module_alias, symbol_syntax } ) =
 | |
| 145 | make_target (f ((serial, description), ((reserved, includes), (module_alias, symbol_syntax)))); | |
| 37821 | 146 | fun merge_target strict target (Target { serial = serial1, description = description,
 | 
| 28054 | 147 | reserved = reserved1, includes = includes1, | 
| 38925 | 148 | module_alias = module_alias1, symbol_syntax = symbol_syntax1 }, | 
| 37821 | 149 |     Target { serial = serial2, description = _,
 | 
| 28054 | 150 | reserved = reserved2, includes = includes2, | 
| 38925 | 151 | module_alias = module_alias2, symbol_syntax = symbol_syntax2 }) = | 
| 28054 | 152 | if serial1 = serial2 orelse not strict then | 
| 37821 | 153 | make_target ((serial1, description), | 
| 37972 
f37a8d488105
restored unusual snd-biased merge/join policy -- required due to non-conservative code setups
 haftmann parents: 
37898diff
changeset | 154 | ((merge (op =) (reserved1, reserved2), Symtab.join (K snd) (includes1, includes2)), | 
| 38925 | 155 | (Symtab.join (K snd) (module_alias1, module_alias2), | 
| 156 | merge_symbol_syntax_data (symbol_syntax1, symbol_syntax2)) | |
| 28054 | 157 | )) | 
| 158 | else | |
| 37821 | 159 |     error ("Incompatible targets: " ^ quote target);
 | 
| 27103 | 160 | |
| 37821 | 161 | fun the_description (Target { description, ... }) = description;
 | 
| 28054 | 162 | fun the_reserved (Target { reserved, ... }) = reserved;
 | 
| 163 | fun the_includes (Target { includes, ... }) = includes;
 | |
| 164 | fun the_module_alias (Target { module_alias , ... }) = module_alias;
 | |
| 38925 | 165 | fun the_symbol_syntax (Target { symbol_syntax = Symbol_Syntax_Data x, ... }) = x;
 | 
| 27437 | 166 | |
| 34248 | 167 | structure Targets = Theory_Data | 
| 34071 | 168 | ( | 
| 169 | type T = (target Symtab.table * string list) * int; | |
| 170 | val empty = ((Symtab.empty, []), 80); | |
| 171 | val extend = I; | |
| 172 | fun merge (((target1, exc1), width1), ((target2, exc2), width2)) : T = | |
| 173 | ((Symtab.join (merge_target true) (target1, target2), | |
| 174 | Library.merge (op =) (exc1, exc2)), Int.max (width1, width2)); | |
| 175 | ); | |
| 27436 | 176 | |
| 34248 | 177 | val abort_allowed = snd o fst o Targets.get; | 
| 34071 | 178 | |
| 34248 | 179 | fun assert_target thy target = if Symtab.defined ((fst o fst) (Targets.get thy)) target | 
| 33969 | 180 | then target | 
| 181 |   else error ("Unknown code target language: " ^ quote target);
 | |
| 28054 | 182 | |
| 183 | fun put_target (target, seri) thy = | |
| 27304 | 184 | let | 
| 34248 | 185 | val lookup_target = Symtab.lookup ((fst o fst) (Targets.get thy)); | 
| 28054 | 186 | val _ = case seri | 
| 37821 | 187 | of Extension (super, _) => if is_some (lookup_target super) then () | 
| 28054 | 188 |           else error ("Unknown code target language: " ^ quote super)
 | 
| 189 | | _ => (); | |
| 37821 | 190 | val overwriting = case (Option.map the_description o lookup_target) target | 
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 191 | of NONE => false | 
| 37821 | 192 | | SOME (Extension _) => true | 
| 193 | | SOME (Fundamental _) => (case seri | |
| 194 |          of Extension _ => error ("Will not overwrite existing target " ^ quote target)
 | |
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 195 | | _ => true); | 
| 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 196 | val _ = if overwriting | 
| 28054 | 197 |       then warning ("Overwriting existing target " ^ quote target)
 | 
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 198 | else (); | 
| 28054 | 199 | in | 
| 200 | thy | |
| 34248 | 201 | |> (Targets.map o apfst o apfst o Symtab.update) | 
| 31599 | 202 | (target, make_target ((serial (), seri), (([], Symtab.empty), | 
| 38925 | 203 | (Symtab.empty, make_symbol_syntax_data ((Symtab.empty, Symreltab.empty), | 
| 204 | (Symtab.empty, Symtab.empty)))))) | |
| 28054 | 205 | end; | 
| 27436 | 206 | |
| 37821 | 207 | fun add_target (target, seri) = put_target (target, Fundamental seri); | 
| 28054 | 208 | fun extend_target (target, (super, modify)) = | 
| 37821 | 209 | put_target (target, Extension (super, modify)); | 
| 27436 | 210 | |
| 28054 | 211 | fun map_target_data target f thy = | 
| 27436 | 212 | let | 
| 28054 | 213 | val _ = assert_target thy target; | 
| 214 | in | |
| 215 | thy | |
| 34248 | 216 | |> (Targets.map o apfst o apfst o Symtab.map_entry target o map_target) f | 
| 28054 | 217 | end; | 
| 27304 | 218 | |
| 28054 | 219 | fun map_reserved target = | 
| 220 | map_target_data target o apsnd o apfst o apfst; | |
| 221 | fun map_includes target = | |
| 222 | map_target_data target o apsnd o apfst o apsnd; | |
| 223 | fun map_module_alias target = | |
| 38925 | 224 | map_target_data target o apsnd o apsnd o apfst; | 
| 225 | fun map_symbol_syntax target = | |
| 226 | map_target_data target o apsnd o apsnd o apsnd o map_symbol_syntax_data; | |
| 27000 | 227 | |
| 34248 | 228 | fun set_default_code_width k = (Targets.map o apsnd) (K k); | 
| 34071 | 229 | |
| 27000 | 230 | |
| 34021 | 231 | (** serializer usage **) | 
| 232 | ||
| 233 | (* montage *) | |
| 234 | ||
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 235 | fun the_fundamental thy = | 
| 34021 | 236 | let | 
| 34248 | 237 | val ((targets, _), _) = Targets.get thy; | 
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 238 | fun fundamental target = case Symtab.lookup targets target | 
| 37821 | 239 | of SOME data => (case the_description data | 
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 240 | of Fundamental data => data | 
| 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 241 | | Extension (super, _) => fundamental super) | 
| 34021 | 242 |       | NONE => error ("Unknown code target language: " ^ quote target);
 | 
| 37822 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 243 | in fundamental end; | 
| 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 244 | |
| 
cf3588177676
use generic description slot for formal code checking
 haftmann parents: 
37821diff
changeset | 245 | fun the_literals thy = #literals o the_fundamental thy; | 
| 34021 | 246 | |
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 247 | fun collapse_hierarchy thy = | 
| 38927 | 248 | let | 
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 249 | val ((targets, _), _) = Targets.get thy; | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 250 | fun collapse target = | 
| 38927 | 251 | let | 
| 252 | val data = case Symtab.lookup targets target | |
| 253 | of SOME data => data | |
| 254 |           | NONE => error ("Unknown code target language: " ^ quote target);
 | |
| 255 | in case the_description data | |
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 256 | of Fundamental _ => (K I, data) | 
| 38927 | 257 | | Extension (super, modify) => let | 
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 258 | val (modify', data') = collapse super | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 259 | in (fn naming => modify' naming #> modify naming, merge_target false target (data', data)) end | 
| 38927 | 260 | end; | 
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 261 | in collapse end; | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 262 | |
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 263 | local | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 264 | |
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 265 | fun activate_target thy target = | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 266 | let | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 267 | val ((targets, abortable), default_width) = Targets.get thy; | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 268 | val (modify, data) = collapse_hierarchy thy target; | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 269 | in (default_width, abortable, data, modify) end; | 
| 38927 | 270 | |
| 34021 | 271 | fun activate_syntax lookup_name src_tab = Symtab.empty | 
| 272 | |> fold_map (fn thing_identifier => fn tab => case lookup_name thing_identifier | |
| 273 | of SOME name => (SOME name, | |
| 274 | Symtab.update_new (name, the (Symtab.lookup src_tab thing_identifier)) tab) | |
| 275 | | NONE => (NONE, tab)) (Symtab.keys src_tab) | |
| 276 | |>> map_filter I; | |
| 277 | ||
| 278 | fun activate_const_syntax thy literals src_tab naming = (Symtab.empty, naming) | |
| 37881 | 279 | |> fold_map (fn c => fn (tab, naming) => | 
| 280 | case Code_Thingol.lookup_const naming c | |
| 34021 | 281 | of SOME name => let | 
| 282 | val (syn, naming') = Code_Printer.activate_const_syntax thy | |
| 37881 | 283 | literals c (the (Symtab.lookup src_tab c)) naming | 
| 34021 | 284 | in (SOME name, (Symtab.update_new (name, syn) tab, naming')) end | 
| 285 | | NONE => (NONE, (tab, naming))) (Symtab.keys src_tab) | |
| 286 | |>> map_filter I; | |
| 287 | ||
| 38927 | 288 | fun activate_symbol_syntax thy literals naming | 
| 289 | class_syntax instance_syntax tyco_syntax const_syntax = | |
| 34021 | 290 | let | 
| 38927 | 291 | val (names_class, class_syntax') = | 
| 292 | activate_syntax (Code_Thingol.lookup_class naming) class_syntax; | |
| 34021 | 293 | val names_inst = map_filter (Code_Thingol.lookup_instance naming) | 
| 38927 | 294 | (Symreltab.keys instance_syntax); | 
| 295 | val (names_tyco, tyco_syntax') = | |
| 296 | activate_syntax (Code_Thingol.lookup_tyco naming) tyco_syntax; | |
| 297 | val (names_const, (const_syntax', _)) = | |
| 298 | activate_const_syntax thy literals const_syntax naming; | |
| 299 | in | |
| 300 | (names_class @ names_inst @ names_tyco @ names_const, | |
| 301 | (class_syntax', tyco_syntax', const_syntax')) | |
| 302 | end; | |
| 303 | ||
| 304 | fun project_program thy abortable names_hidden names1 program2 = | |
| 305 | let | |
| 34021 | 306 | val names2 = subtract (op =) names_hidden names1; | 
| 307 | val program3 = Graph.subgraph (not o member (op =) names_hidden) program2; | |
| 38936 | 308 | val names4 = Graph.all_succs program3 names2; | 
| 34021 | 309 | val empty_funs = filter_out (member (op =) abortable) | 
| 310 | (Code_Thingol.empty_funs program3); | |
| 311 |     val _ = if null empty_funs then () else error ("No code equations for "
 | |
| 312 | ^ commas (map (Sign.extern_const thy) empty_funs)); | |
| 38936 | 313 | val program4 = Graph.subgraph (member (op =) names4) program3; | 
| 314 | in (names4, program4) end; | |
| 38927 | 315 | |
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 316 | fun invoke_serializer thy abortable serializer literals reserved all_includes | 
| 38927 | 317 | module_alias proto_class_syntax proto_instance_syntax proto_tyco_syntax proto_const_syntax | 
| 39058 | 318 | module_name args naming proto_program names = | 
| 38927 | 319 | let | 
| 320 | val (names_hidden, (class_syntax, tyco_syntax, const_syntax)) = | |
| 321 | activate_symbol_syntax thy literals naming | |
| 322 | proto_class_syntax proto_instance_syntax proto_tyco_syntax proto_const_syntax; | |
| 323 | val (names_all, program) = project_program thy abortable names_hidden names proto_program; | |
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 324 | fun select_include (name, (content, cs)) = | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 325 | if null cs orelse exists (fn c => case Code_Thingol.lookup_const naming c | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 326 | of SOME name => member (op =) names_all name | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 327 | | NONE => false) cs | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 328 | then SOME (name, content) else NONE; | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 329 | val includes = map_filter select_include (Symtab.dest all_includes); | 
| 34021 | 330 | in | 
| 38926 | 331 |     serializer args {
 | 
| 38927 | 332 | labelled_name = Code_Thingol.labelled_name thy proto_program, | 
| 38926 | 333 | reserved_syms = reserved, | 
| 334 | includes = includes, | |
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 335 | module_alias = if module_name = "" then Symtab.lookup module_alias else K (SOME module_name), | 
| 38927 | 336 | class_syntax = Symtab.lookup class_syntax, | 
| 337 | tyco_syntax = Symtab.lookup tyco_syntax, | |
| 338 | const_syntax = Symtab.lookup const_syntax, | |
| 39142 | 339 | program = program } | 
| 34021 | 340 | end; | 
| 341 | ||
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 342 | fun mount_serializer thy target some_width module_name args = | 
| 34021 | 343 | let | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 344 | val (default_width, abortable, data, modify) = activate_target thy target; | 
| 38921 | 345 | val serializer = case the_description data | 
| 38927 | 346 | of Fundamental seri => #serializer seri; | 
| 34021 | 347 | val reserved = the_reserved data; | 
| 38779 | 348 | val module_alias = the_module_alias data | 
| 38925 | 349 |     val { class, instance, tyco, const } = the_symbol_syntax data;
 | 
| 34021 | 350 | val literals = the_literals thy target; | 
| 34071 | 351 | val width = the_default default_width some_width; | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 352 | in fn naming => fn program => fn names => | 
| 34021 | 353 | invoke_serializer thy abortable serializer literals reserved | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 354 | (the_includes data) module_alias class instance tyco const module_name args | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 355 | naming (modify naming program) names width | 
| 34021 | 356 | end; | 
| 357 | ||
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 358 | fun assert_module_name "" = error ("Empty module name not allowed.")
 | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 359 | | assert_module_name module_name = module_name; | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 360 | |
| 34021 | 361 | in | 
| 362 | ||
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 363 | fun export_code_for thy some_path target some_width module_name args = | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 364 | export some_path ooo mount_serializer thy target some_width module_name args; | 
| 38918 | 365 | |
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 366 | fun produce_code_for thy target some_width module_name args = | 
| 39102 | 367 | let | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 368 | val serializer = mount_serializer thy target some_width (assert_module_name module_name) args; | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 369 | in fn naming => fn program => fn names => | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 370 | produce (serializer naming program names) |> apsnd (fn deresolve => map deresolve names) | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 371 | end; | 
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 372 | |
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 373 | fun present_code_for thy target some_width module_name args = | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 374 | let | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 375 | val serializer = mount_serializer thy target some_width (assert_module_name module_name) args; | 
| 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 376 | in fn naming => fn program => fn (names, selects) => | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 377 | present selects (serializer naming program names) | 
| 39484 
505f95975a5a
closures separate serializer initialization from serializer invocation as far as appropriate
 haftmann parents: 
39480diff
changeset | 378 | end; | 
| 38918 | 379 | |
| 380 | fun check_code_for thy target strict args naming program names_cs = | |
| 37824 | 381 | let | 
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 382 | val module_name = "Code"; | 
| 37824 | 383 |     val { env_var, make_destination, make_command } =
 | 
| 384 | (#check o the_fundamental thy) target; | |
| 385 | val env_param = getenv env_var; | |
| 386 | fun ext_check env_param p = | |
| 387 | let | |
| 388 | val destination = make_destination p; | |
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 389 | val _ = export (SOME destination) (mount_serializer thy target (SOME 80) | 
| 39661 
6381d18507ef
reverted cs 07549694e2f1 -- use re-printing with current print mode instead after code assembly, avoid Latex.output_typewriter
 haftmann parents: 
39659diff
changeset | 390 | module_name args naming program names_cs); | 
| 38863 
9070a7c356c9
code checking: compiler invocation happens in same directory as generated file -- avoid problem with different path representations on cygwin
 haftmann parents: 
38784diff
changeset | 391 | val cmd = make_command env_param module_name; | 
| 37824 | 392 |       in if bash ("cd " ^ File.shell_path p ^ " && " ^ cmd ^ " 2>&1") <> 0
 | 
| 393 |         then error ("Code check failed for " ^ target ^ ": " ^ cmd)
 | |
| 394 | else () | |
| 395 | end; | |
| 396 | in if env_param = "" | |
| 37825 | 397 | then if strict | 
| 398 | then error (env_var ^ " not set; cannot check code for " ^ target) | |
| 399 | else warning (env_var ^ " not set; skipped checking code for " ^ target) | |
| 37824 | 400 | else Cache_IO.with_tmp_dir "Code_Test" (ext_check env_param) | 
| 401 | end; | |
| 402 | ||
| 34021 | 403 | end; (* local *) | 
| 404 | ||
| 405 | ||
| 406 | (* code generation *) | |
| 407 | ||
| 408 | fun transitivly_non_empty_funs thy naming program = | |
| 409 | let | |
| 410 | val cs = subtract (op =) (abort_allowed thy) (Code_Thingol.empty_funs program); | |
| 411 | val names = map_filter (Code_Thingol.lookup_const naming) cs; | |
| 412 | in subtract (op =) (Graph.all_preds program names) (Graph.keys program) end; | |
| 413 | ||
| 414 | fun read_const_exprs thy cs = | |
| 415 | let | |
| 416 | val (cs1, cs2) = Code_Thingol.read_const_exprs thy cs; | |
| 36271 
2ef9dbddfcb8
optionally ignore errors during translation of equations
 haftmann parents: 
36121diff
changeset | 417 | val (names2, (naming, program)) = Code_Thingol.consts_program thy true cs2; | 
| 
2ef9dbddfcb8
optionally ignore errors during translation of equations
 haftmann parents: 
36121diff
changeset | 418 | val names3 = transitivly_non_empty_funs thy naming program; | 
| 
2ef9dbddfcb8
optionally ignore errors during translation of equations
 haftmann parents: 
36121diff
changeset | 419 | val cs3 = map_filter (fn (c, name) => | 
| 
2ef9dbddfcb8
optionally ignore errors during translation of equations
 haftmann parents: 
36121diff
changeset | 420 | if member (op =) names3 name then SOME c else NONE) (cs2 ~~ names2); | 
| 
2ef9dbddfcb8
optionally ignore errors during translation of equations
 haftmann parents: 
36121diff
changeset | 421 | in union (op =) cs3 cs1 end; | 
| 34021 | 422 | |
| 38918 | 423 | fun prep_destination "" = NONE | 
| 424 | | prep_destination "-" = NONE | |
| 425 | | prep_destination s = SOME (Path.explode s); | |
| 426 | ||
| 34021 | 427 | fun export_code thy cs seris = | 
| 428 | let | |
| 37824 | 429 | val (names_cs, (naming, program)) = Code_Thingol.consts_program thy false cs; | 
| 38918 | 430 | val _ = map (fn (((target, module_name), some_path), args) => | 
| 431 | export_code_for thy some_path target NONE module_name args naming program names_cs) seris; | |
| 34021 | 432 | in () end; | 
| 433 | ||
| 38918 | 434 | fun export_code_cmd raw_cs seris thy = export_code thy (read_const_exprs thy raw_cs) | 
| 435 | ((map o apfst o apsnd) prep_destination seris); | |
| 436 | ||
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 437 | fun produce_code thy cs target some_width some_module_name args = | 
| 38918 | 438 | let | 
| 439 | val (names_cs, (naming, program)) = Code_Thingol.consts_program thy false cs; | |
| 38929 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 440 | in produce_code_for thy target some_width some_module_name args naming program names_cs end; | 
| 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 441 | |
| 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 442 | fun present_code thy cs names_stmt target some_width some_module_name args = | 
| 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 443 | let | 
| 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 444 | val (names_cs, (naming, program)) = Code_Thingol.consts_program thy false cs; | 
| 
d9ac9dee764d
distinguish code production and code presentation
 haftmann parents: 
38928diff
changeset | 445 | in present_code_for thy target some_width some_module_name args naming program (names_cs, names_stmt naming) end; | 
| 34021 | 446 | |
| 37824 | 447 | fun check_code thy cs seris = | 
| 448 | let | |
| 449 | val (names_cs, (naming, program)) = Code_Thingol.consts_program thy false cs; | |
| 38918 | 450 | val _ = map (fn ((target, strict), args) => | 
| 451 | check_code_for thy target strict args naming program names_cs) seris; | |
| 37824 | 452 | in () end; | 
| 453 | ||
| 454 | fun check_code_cmd raw_cs seris thy = check_code thy (read_const_exprs thy raw_cs) seris; | |
| 455 | ||
| 39480 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 456 | local | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 457 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 458 | val parse_const_terms = Scan.repeat1 Args.term | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 459 | >> (fn ts => fn thy => map (Code.check_const thy) ts); | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 460 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 461 | fun parse_names category parse internalize lookup = | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 462 | Scan.lift (Args.parens (Args.$$$ category)) |-- Scan.repeat1 parse | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 463 | >> (fn xs => fn thy => fn naming => map_filter (lookup naming o internalize thy) xs); | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 464 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 465 | val parse_consts = parse_names "consts" Args.term | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 466 | Code.check_const Code_Thingol.lookup_const ; | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 467 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 468 | val parse_types = parse_names "types" (Scan.lift Args.name) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 469 | Sign.intern_type Code_Thingol.lookup_tyco; | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 470 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 471 | val parse_classes = parse_names "classes" (Scan.lift Args.name) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 472 | Sign.intern_class Code_Thingol.lookup_class; | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 473 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 474 | val parse_instances = parse_names "instances" (Scan.lift (Args.name --| Args.$$$ "::" -- Args.name)) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 475 | (fn thy => fn (raw_tyco, raw_class) => (Sign.intern_class thy raw_class, Sign.intern_type thy raw_tyco)) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 476 | Code_Thingol.lookup_instance; | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 477 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 478 | in | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 479 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 480 | val _ = Thy_Output.antiquotation "code_stmts" | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 481 | (parse_const_terms -- Scan.repeat (parse_consts || parse_types || parse_classes || parse_instances) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 482 | -- Scan.lift (Args.parens (Args.name -- Scan.option Parse.int))) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 483 |   (fn {context = ctxt, ...} => fn ((mk_cs, mk_stmtss), (target, some_width)) =>
 | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 484 | let val thy = ProofContext.theory_of ctxt in | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 485 | present_code thy (mk_cs thy) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 486 | (fn naming => maps (fn f => f thy naming) mk_stmtss) | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 487 | target some_width "Example" [] | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 488 | end); | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 489 | |
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 490 | end; | 
| 
a2ed61449dcc
added code_stmts antiquotation from doc-src/more_antiquote.ML
 haftmann parents: 
39142diff
changeset | 491 | |
| 34021 | 492 | |
| 28054 | 493 | (** serializer configuration **) | 
| 27000 | 494 | |
| 495 | (* data access *) | |
| 24219 | 496 | |
| 24992 | 497 | fun cert_class thy class = | 
| 498 | let | |
| 499 | val _ = AxClass.get_info thy class; | |
| 500 | in class end; | |
| 501 | ||
| 27103 | 502 | fun read_class thy = cert_class thy o Sign.intern_class thy; | 
| 24992 | 503 | |
| 504 | fun cert_tyco thy tyco = | |
| 505 | let | |
| 506 | val _ = if Sign.declared_tyname thy tyco then () | |
| 507 |       else error ("No such type constructor: " ^ quote tyco);
 | |
| 508 | in tyco end; | |
| 509 | ||
| 27103 | 510 | fun read_tyco thy = cert_tyco thy o Sign.intern_type thy; | 
| 24219 | 511 | |
| 34071 | 512 | fun cert_inst thy (class, tyco) = | 
| 513 | (cert_class thy class, cert_tyco thy tyco); | |
| 514 | ||
| 515 | fun read_inst thy (raw_tyco, raw_class) = | |
| 516 | (read_class thy raw_class, read_tyco thy raw_tyco); | |
| 517 | ||
| 37844 | 518 | fun gen_add_syntax (mapp, upd, del) prep_x prep_syn target raw_x some_raw_syn thy = | 
| 24219 | 519 | let | 
| 37840 | 520 | val x = prep_x thy raw_x; | 
| 37844 | 521 | val change = case some_raw_syn | 
| 522 | of SOME raw_syn => upd (x, prep_syn thy x raw_syn) | |
| 523 | | NONE => del x; | |
| 38925 | 524 | in (map_symbol_syntax target o mapp) change thy end; | 
| 24219 | 525 | |
| 38923 | 526 | fun gen_add_class_syntax prep_class = | 
| 37844 | 527 | gen_add_syntax (apfst o apfst, Symtab.update, Symtab.delete_safe) prep_class ((K o K) I); | 
| 34071 | 528 | |
| 38923 | 529 | fun gen_add_instance_syntax prep_inst = | 
| 37844 | 530 | gen_add_syntax (apfst o apsnd, Symreltab.update, Symreltab.delete_safe) prep_inst ((K o K) I); | 
| 24219 | 531 | |
| 38923 | 532 | fun gen_add_tyco_syntax prep_tyco = | 
| 37844 | 533 | gen_add_syntax (apsnd o apfst, Symtab.update, Symtab.delete_safe) prep_tyco | 
| 534 | (fn thy => fn tyco => fn syn => if fst syn <> Sign.arity_number thy tyco | |
| 34071 | 535 |       then error ("Number of arguments mismatch in syntax for type constructor " ^ quote tyco)
 | 
| 37844 | 536 | else syn); | 
| 34071 | 537 | |
| 38923 | 538 | fun gen_add_const_syntax prep_const = | 
| 37844 | 539 | gen_add_syntax (apsnd o apsnd, Symtab.update, Symtab.delete_safe) prep_const | 
| 37881 | 540 | (fn thy => fn c => fn syn => | 
| 541 | if Code_Printer.requires_args syn > Code.args_number thy c | |
| 24423 
ae9cd0e92423
overloaded definitions accompanied by explicit constants
 haftmann parents: 
24381diff
changeset | 542 |       then error ("Too many arguments in syntax for constant " ^ quote c)
 | 
| 37881 | 543 | else syn); | 
| 24219 | 544 | |
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 545 | fun add_reserved target sym thy = | 
| 24219 | 546 | let | 
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 547 | val (_, data) = collapse_hierarchy thy target; | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 548 | val _ = if member (op =) (the_reserved data) sym | 
| 24219 | 549 |       then error ("Reserved symbol " ^ quote sym ^ " already declared")
 | 
| 39817 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 550 | else (); | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 551 | in | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 552 | thy | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 553 | |> map_reserved target (insert (op =) sym) | 
| 
5228c6b20273
check whole target hierarchy for existing reserved symbols
 haftmann parents: 
39750diff
changeset | 554 | end; | 
| 24992 | 555 | |
| 28926 | 556 | fun gen_add_include read_const target args thy = | 
| 24992 | 557 | let | 
| 28926 | 558 | fun add (name, SOME (content, raw_cs)) incls = | 
| 24992 | 559 | let | 
| 560 | val _ = if Symtab.defined incls name | |
| 561 |               then warning ("Overwriting existing include " ^ name)
 | |
| 562 | else (); | |
| 28926 | 563 | val cs = map (read_const thy) raw_cs; | 
| 34152 | 564 | in Symtab.update (name, (Code_Printer.str content, cs)) incls end | 
| 28926 | 565 | | add (name, NONE) incls = Symtab.delete name incls; | 
| 566 | in map_includes target (add args) thy end; | |
| 567 | ||
| 33969 | 568 | val add_include = gen_add_include (K I); | 
| 31156 | 569 | val add_include_cmd = gen_add_include Code.read_const; | 
| 24219 | 570 | |
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 571 | fun add_module_alias target (thyname, "") = | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 572 | map_module_alias target (Symtab.delete thyname) | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 573 | | add_module_alias target (thyname, modlname) = | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 574 | let | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 575 | val xs = Long_Name.explode modlname; | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 576 | val xs' = map (Name.desymbolize true) xs; | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 577 | in if xs' = xs | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 578 | then map_module_alias target (Symtab.update (thyname, modlname)) | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 579 |         else error ("Invalid module name: " ^ quote modlname ^ "\n"
 | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 580 | ^ "perhaps try " ^ quote (Long_Name.implode xs')) | 
| 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 581 | end; | 
| 24219 | 582 | |
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 583 | fun gen_allow_abort prep_const raw_c thy = | 
| 24841 | 584 | let | 
| 28663 
bd8438543bf2
code identifier namings are no longer imperative
 haftmann parents: 
28090diff
changeset | 585 | val c = prep_const thy raw_c; | 
| 34248 | 586 | in thy |> (Targets.map o apfst o apsnd) (insert (op =) c) end; | 
| 24841 | 587 | |
| 27000 | 588 | |
| 27103 | 589 | (* concrete syntax *) | 
| 27000 | 590 | |
| 34021 | 591 | local | 
| 592 | ||
| 34152 | 593 | fun zip_list (x::xs) f g = | 
| 594 | f | |
| 37881 | 595 | :|-- (fn y => | 
| 34152 | 596 | fold_map (fn x => g |-- f >> pair x) xs | 
| 37881 | 597 | :|-- (fn xys => pair ((x, y) :: xys))); | 
| 34152 | 598 | |
| 37881 | 599 | fun process_multi_syntax parse_thing parse_syntax change = | 
| 600 | (Parse.and_list1 parse_thing | |
| 601 |   :|-- (fn things => Scan.repeat1 (Parse.$$$ "(" |-- Parse.name --
 | |
| 602 | (zip_list things parse_syntax (Parse.$$$ "and")) --| Parse.$$$ ")"))) | |
| 603 | >> (Toplevel.theory oo fold) | |
| 604 | (fn (target, syns) => fold (fn (raw_x, syn) => change target raw_x syn) syns); | |
| 24219 | 605 | |
| 606 | in | |
| 607 | ||
| 38923 | 608 | val add_class_syntax = gen_add_class_syntax cert_class; | 
| 609 | val add_instance_syntax = gen_add_instance_syntax cert_inst; | |
| 610 | val add_tyco_syntax = gen_add_tyco_syntax cert_tyco; | |
| 611 | val add_const_syntax = gen_add_const_syntax (K I); | |
| 27103 | 612 | val allow_abort = gen_allow_abort (K I); | 
| 28054 | 613 | val add_reserved = add_reserved; | 
| 33969 | 614 | val add_include = add_include; | 
| 24219 | 615 | |
| 38923 | 616 | val add_class_syntax_cmd = gen_add_class_syntax read_class; | 
| 617 | val add_instance_syntax_cmd = gen_add_instance_syntax read_inst; | |
| 618 | val add_tyco_syntax_cmd = gen_add_tyco_syntax read_tyco; | |
| 619 | val add_const_syntax_cmd = gen_add_const_syntax Code.read_const; | |
| 31156 | 620 | val allow_abort_cmd = gen_allow_abort Code.read_const; | 
| 24219 | 621 | |
| 28054 | 622 | fun parse_args f args = | 
| 36959 
f5417836dbea
renamed structure OuterLex to Token and type token to Token.T, keeping legacy aliases for some time;
 wenzelm parents: 
36537diff
changeset | 623 | case Scan.read Token.stopper f args | 
| 28054 | 624 | of SOME x => x | 
| 625 | | NONE => error "Bad serializer arguments"; | |
| 626 | ||
| 627 | ||
| 27304 | 628 | (** Isar setup **) | 
| 27103 | 629 | |
| 37824 | 630 | val (inK, module_nameK, fileK, checkingK) = ("in", "module_name", "file", "checking");
 | 
| 631 | ||
| 632 | val code_expr_argsP = Scan.optional (Parse.$$$ "(" |-- Args.parse --| Parse.$$$ ")") [];
 | |
| 27103 | 633 | |
| 30494 
c150e6fa4e0d
consider exit status of code generation direcitve
 haftmann parents: 
30242diff
changeset | 634 | val code_exprP = | 
| 37824 | 635 | Scan.repeat1 Parse.term_group :|-- (fn raw_cs => | 
| 37825 | 636 | ((Parse.$$$ checkingK |-- Scan.repeat (Parse.name | 
| 637 | -- ((Parse.$$$ "?" |-- Scan.succeed false) || Scan.succeed true) -- code_expr_argsP)) | |
| 37824 | 638 | >> (fn seris => check_code_cmd raw_cs seris) | 
| 639 | || Scan.repeat (Parse.$$$ inK |-- Parse.name | |
| 38933 
bd77e092f67c
avoid strange special treatment of empty module names
 haftmann parents: 
38929diff
changeset | 640 | -- Scan.optional (Parse.$$$ module_nameK |-- Parse.name) "" | 
| 37824 | 641 | -- Scan.optional (Parse.$$$ fileK |-- Parse.name) "" | 
| 642 | -- code_expr_argsP) >> (fn seris => export_code_cmd raw_cs seris))); | |
| 27103 | 643 | |
| 37824 | 644 | val _ = List.app Keyword.keyword [inK, module_nameK, fileK, checkingK]; | 
| 24867 | 645 | |
| 646 | val _ = | |
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 647 | Outer_Syntax.command "code_class" "define code syntax for class" Keyword.thy_decl ( | 
| 37881 | 648 | process_multi_syntax Parse.xname (Scan.option Parse.string) | 
| 38923 | 649 | add_class_syntax_cmd); | 
| 24219 | 650 | |
| 24867 | 651 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 652 | Outer_Syntax.command "code_instance" "define code syntax for instance" Keyword.thy_decl ( | 
| 37881 | 653 | process_multi_syntax (Parse.xname --| Parse.$$$ "::" -- Parse.xname) | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 654 | (Scan.option (Parse.minus >> K ())) | 
| 38923 | 655 | add_instance_syntax_cmd); | 
| 24219 | 656 | |
| 24867 | 657 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 658 | Outer_Syntax.command "code_type" "define code syntax for type constructor" Keyword.thy_decl ( | 
| 37881 | 659 | process_multi_syntax Parse.xname Code_Printer.parse_tyco_syntax | 
| 38923 | 660 | add_tyco_syntax_cmd); | 
| 24219 | 661 | |
| 24867 | 662 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 663 | Outer_Syntax.command "code_const" "define code syntax for constant" Keyword.thy_decl ( | 
| 37881 | 664 | process_multi_syntax Parse.term_group Code_Printer.parse_const_syntax | 
| 38923 | 665 | add_const_syntax_cmd); | 
| 24219 | 666 | |
| 24867 | 667 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 668 | Outer_Syntax.command "code_reserved" "declare words as reserved for target language" | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 669 | Keyword.thy_decl ( | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 670 | Parse.name -- Scan.repeat1 Parse.name | 
| 24219 | 671 | >> (fn (target, reserveds) => (Toplevel.theory o fold (add_reserved target)) reserveds) | 
| 24841 | 672 | ); | 
| 24219 | 673 | |
| 24867 | 674 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 675 | Outer_Syntax.command "code_include" "declare piece of code to be included in generated code" | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 676 | Keyword.thy_decl ( | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 677 | Parse.name -- Parse.name -- (Parse.text :|-- (fn "-" => Scan.succeed NONE | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 678 | | s => Scan.optional (Parse.$$$ "attach" |-- Scan.repeat1 Parse.term) [] >> pair s >> SOME)) | 
| 28926 | 679 | >> (fn ((target, name), content_consts) => | 
| 680 | (Toplevel.theory o add_include_cmd target) (name, content_consts)) | |
| 24992 | 681 | ); | 
| 682 | ||
| 683 | val _ = | |
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 684 | Outer_Syntax.command "code_modulename" "alias module to other name" Keyword.thy_decl ( | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 685 | Parse.name -- Scan.repeat1 (Parse.name -- Parse.name) | 
| 27103 | 686 | >> (fn (target, modlnames) => (Toplevel.theory o fold (add_module_alias target)) modlnames) | 
| 687 | ); | |
| 688 | ||
| 689 | val _ = | |
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 690 | Outer_Syntax.command "code_abort" "permit constant to be implemented as program abort" | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 691 | Keyword.thy_decl ( | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 692 | Scan.repeat1 Parse.term_group >> (Toplevel.theory o fold allow_abort_cmd) | 
| 24841 | 693 | ); | 
| 24219 | 694 | |
| 24867 | 695 | val _ = | 
| 36960 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 696 | Outer_Syntax.command "export_code" "generate executable code for constants" | 
| 
01594f816e3a
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax;
 wenzelm parents: 
36959diff
changeset | 697 | Keyword.diag (Parse.!!! code_exprP >> (fn f => Toplevel.keep (f o Toplevel.theory_of))); | 
| 30494 
c150e6fa4e0d
consider exit status of code generation direcitve
 haftmann parents: 
30242diff
changeset | 698 | |
| 24219 | 699 | end; (*local*) | 
| 700 | ||
| 39646 | 701 | |
| 702 | (** external entrance point -- for codegen tool **) | |
| 703 | ||
| 39750 
c0099428ca7b
consider quick_and_dirty option before loading theory
 haftmann parents: 
39679diff
changeset | 704 | fun codegen_tool thyname cmd_expr = | 
| 39646 | 705 | let | 
| 706 | val thy = Thy_Info.get_theory thyname; | |
| 707 | val parse = Scan.read Token.stopper (Parse.!!! code_exprP) o | |
| 708 | (filter Token.is_proper o Outer_Syntax.scan Position.none); | |
| 709 | in case parse cmd_expr | |
| 710 | of SOME f => (writeln "Now generating code..."; f thy) | |
| 711 |     | NONE => error ("Bad directive " ^ quote cmd_expr)
 | |
| 712 | end; | |
| 713 | ||
| 24219 | 714 | end; (*struct*) |