1 (* Title: Pure/ML/ml_context.ML
5 ML context and antiquotations.
8 signature BASIC_ML_CONTEXT =
10 val store_thm: string * thm -> thm
11 val store_thms: string * thm list -> thm list
12 val bind_thm: string * thm -> unit
13 val bind_thms: string * thm list -> unit
14 val thm: xstring -> thm
15 val thms: xstring -> thm list
18 signature ML_CONTEXT =
20 include BASIC_ML_CONTEXT
21 val the_generic_context: unit -> Context.generic
22 val the_global_context: unit -> theory
23 val the_local_context: unit -> Proof.context
24 val exec: (unit -> unit) -> Context.generic -> Context.generic
25 val stored_thms: thm list ref
26 val ml_store_thm: string * thm -> unit
27 val ml_store_thms: string * thm list -> unit
28 val add_keywords: string list -> unit
29 val inline_antiq: string ->
30 (Context.generic * Args.T list -> string * (Context.generic * Args.T list)) -> unit
31 val value_antiq: string ->
32 (Context.generic * Args.T list -> (string * string) * (Context.generic * Args.T list)) -> unit
33 val proj_value_antiq: string -> (Context.generic * Args.T list ->
34 (string * string * string) * (Context.generic * Args.T list)) -> unit
35 val eval_antiquotes_fn: (string * Position.T -> string * string) ref (* FIXME tmp *)
37 val eval: bool -> Position.T -> string -> unit
38 val eval_file: Path.T -> unit
39 val eval_in: Context.generic option -> bool -> Position.T -> string -> unit
40 val evaluate: (string -> unit) * (string -> 'b) -> bool ->
41 string * (unit -> 'a) option ref -> string -> 'a
42 val expression: Position.T -> string -> string -> string -> Context.generic -> Context.generic
45 structure ML_Context: ML_CONTEXT =
48 (** implicit ML context **)
50 val the_generic_context = Context.the_thread_data;
51 val the_global_context = Context.theory_of o the_generic_context;
52 val the_local_context = Context.proof_of o the_generic_context;
54 fun exec (e: unit -> unit) context =
55 (case Context.setmp_thread_data (SOME context) (fn () => (e (); Context.thread_data ())) () of
56 SOME context' => context'
57 | NONE => error "Missing context after execution");
60 (* theorem bindings *)
62 val store_thms = PureThy.smart_store_thms;
63 fun store_thm (name, th) = the_single (store_thms (name, [th]));
65 val stored_thms: thm list ref = ref [];
68 if name = "" then true
69 else if ML_Syntax.is_identifier name then false
70 else error ("Cannot bind theorem(s) " ^ quote name ^ " as ML value");
72 val use_text_verbose = use_text (0, "") Output.ml_output true;
74 fun ml_store_thm (name, th) =
75 let val th' = store_thm (name, th) in
77 else setmp stored_thms [th']
78 (fn () => use_text_verbose ("val " ^ name ^ " = hd (! ML_Context.stored_thms);")) ()
81 fun ml_store_thms (name, ths) =
82 let val ths' = store_thms (name, ths) in
84 else setmp stored_thms ths'
85 (fn () => use_text_verbose ("val " ^ name ^ " = ! ML_Context.stored_thms;")) ()
88 fun bind_thm (name, thm) = ml_store_thm (name, Drule.standard thm);
89 fun bind_thms (name, thms) = ml_store_thms (name, map Drule.standard thms);
93 (** ML antiquotations **)
95 (* maintain keywords *)
97 val global_lexicon = ref Scan.empty_lexicon;
99 fun add_keywords keywords = CRITICAL (fn () =>
100 change global_lexicon (Scan.extend_lexicon (map Symbol.explode keywords)));
103 (* maintain commands *)
105 datatype antiq = Inline of string | ProjValue of string * string * string;
106 val global_parsers = ref (Symtab.empty:
107 (Context.generic * Args.T list -> antiq * (Context.generic * Args.T list)) Symtab.table);
111 fun add_item kind name scan = CRITICAL (fn () =>
112 change global_parsers (fn tab =>
113 (if not (Symtab.defined tab name) then ()
114 else warning ("Redefined ML antiquotation: " ^ quote name);
115 Symtab.update (name, scan >> kind) tab)));
119 val inline_antiq = add_item Inline;
120 val proj_value_antiq = add_item ProjValue;
121 fun value_antiq name scan = proj_value_antiq name (scan >> (fn (a, s) => (a, s, "")));
128 fun syntax scan src =
129 #1 (Args.context_syntax "ML antiquotation" scan src (the_local_context ()));
132 let val ((name, _), pos) = Args.dest_src src in
133 (case Symtab.lookup (! global_parsers) name of
134 NONE => error ("Unknown ML antiquotation command: " ^ quote name ^ Position.str_of pos)
135 | SOME scan => syntax scan src)
141 structure T = OuterLex;
142 structure P = OuterParse;
145 P.!!! (P.position P.xname -- P.arguments --| Scan.ahead P.eof)
146 >> (fn ((x, pos), y) => Args.src ((x, y), pos));
149 (* input/output wrappers *)
153 val isabelle_struct = enclose "structure Isabelle =\nstruct\n" "end;";
154 val isabelle_struct0 = isabelle_struct "";
156 fun eval_antiquotes txt_pos =
158 val ants = Antiquote.scan_antiquotes txt_pos;
160 fun expand (Antiquote.Text s) names = (("", Symbol.escape s), names)
161 | expand (Antiquote.Antiq x) names =
162 (case command (Antiquote.scan_arguments (! global_lexicon) antiq x) of
163 Inline s => (("", s), names)
164 | ProjValue (a, s, f) =>
166 val a' = if ML_Syntax.is_identifier a then a else "val";
167 val ([b], names') = Name.variants [a'] names;
168 val binding = "val " ^ b ^ " = " ^ s ^ ";\n";
170 if f = "" then "Isabelle." ^ b
171 else "(" ^ f ^ " Isabelle." ^ b ^ ")";
172 in ((binding, value), names') end);
175 NAMED_CRITICAL "ML" (fn () => fold_map expand ants ML_Syntax.reserved)
176 |> #1 |> split_list |> pairself implode;
177 in (isabelle_struct decls, body) end;
181 val eval_antiquotes_fn = ref eval_antiquotes;
183 val trace = ref false;
185 fun eval_wrapper pr verbose pos txt =
187 val (txt1, txt2) = ! eval_antiquotes_fn (txt, pos); (* FIXME tmp hook *)
188 val _ = if ! trace then tracing (cat_lines [txt1, txt2]) else ();
190 use_text (the_default 1 (Position.line_of p), the_default "ML" (Position.file_of p)) pr;
192 NAMED_CRITICAL "ML" (fn () =>
193 (eval Position.none false txt1;
194 eval pos verbose txt2;
195 eval Position.none false isabelle_struct0))
203 val eval = eval_wrapper Output.ml_output;
204 fun eval_file path = eval true (Position.path path) (File.read path);
206 fun eval_in context verbose pos txt =
207 Context.setmp_thread_data context (fn () => eval verbose pos txt) ();
209 fun evaluate pr verbose (ref_name, r) txt = NAMED_CRITICAL "ML" (fn () =>
212 val _ = eval_wrapper pr verbose Position.none
213 ("val _ = (" ^ ref_name ^ " := SOME (fn () => " ^ txt ^ "))");
214 in (case ! r of NONE => error ("Bad evaluation for " ^ ref_name) | SOME e => e) end) ();
216 fun expression pos bind body txt =
217 exec (fn () => eval false pos
218 ("Context.set_thread_data (SOME (let " ^ bind ^ " = " ^ txt ^ " in " ^ body ^
219 " end (ML_Context.the_generic_context ())));"));
222 (* basic antiquotations *)
224 fun context x = (Scan.state >> Context.proof_of) x;
228 val _ = value_antiq "context" (Scan.succeed ("context", "ML_Context.the_local_context ()"));
230 val _ = inline_antiq "sort" (context -- Scan.lift Args.name >> (fn (ctxt, s) =>
231 ML_Syntax.atomic (ML_Syntax.print_sort (Syntax.read_sort ctxt s))));
233 val _ = inline_antiq "typ" (Args.typ >> (ML_Syntax.atomic o ML_Syntax.print_typ));
234 val _ = inline_antiq "term" (Args.term >> (ML_Syntax.atomic o ML_Syntax.print_term));
235 val _ = inline_antiq "prop" (Args.prop >> (ML_Syntax.atomic o ML_Syntax.print_term));
237 val _ = value_antiq "ctyp" (Args.typ >> (fn T =>
239 "Thm.ctyp_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_typ T))));
241 val _ = value_antiq "cterm" (Args.term >> (fn t =>
243 "Thm.cterm_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))));
245 val _ = value_antiq "cprop" (Args.prop >> (fn t =>
247 "Thm.cterm_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))));
249 fun type_ syn = (context -- Scan.lift Args.name >> (fn (ctxt, c) =>
250 #1 (Term.dest_Type (ProofContext.read_tyname ctxt c))
251 |> syn ? Sign.base_name
252 |> ML_Syntax.print_string));
254 val _ = inline_antiq "type_name" (type_ false);
255 val _ = inline_antiq "type_syntax" (type_ true);
257 fun const syn = context -- Scan.lift Args.name >> (fn (ctxt, c) =>
258 #1 (Term.dest_Const (ProofContext.read_const_proper ctxt c))
259 |> syn ? ProofContext.const_syntax_name ctxt
260 |> ML_Syntax.print_string);
262 val _ = inline_antiq "const_name" (const false);
263 val _ = inline_antiq "const_syntax" (const true);
265 val _ = inline_antiq "const"
266 (context -- Scan.lift Args.name --
267 Scan.optional (Scan.lift (Args.$$$ "(") |-- Args.enum1 "," Args.typ --| Scan.lift (Args.$$$ ")")) []
268 >> (fn ((ctxt, c), Ts) =>
270 val (c, _) = Term.dest_Const (ProofContext.read_const_proper ctxt c);
271 in ML_Syntax.atomic (ML_Syntax.print_term (ProofContext.mk_const ctxt (c, Ts))) end));
277 (** fact references **)
279 fun thm name = ProofContext.get_thm (the_local_context ()) name;
280 fun thms name = ProofContext.get_thms (the_local_context ()) name;
285 fun print_interval (Facts.FromTo arg) =
286 "Facts.FromTo " ^ ML_Syntax.print_pair ML_Syntax.print_int ML_Syntax.print_int arg
287 | print_interval (Facts.From i) = "Facts.From " ^ ML_Syntax.print_int i
288 | print_interval (Facts.Single i) = "Facts.Single " ^ ML_Syntax.print_int i;
290 fun thm_antiq kind get get_name = value_antiq kind
291 (context -- Scan.lift (Args.position Args.name -- Scan.option Args.thm_sel)
292 >> (fn (ctxt, ((name, pos), sel)) =>
294 val _ = get ctxt (Facts.Named ((name, pos), sel));
296 "(Facts.Named ((" ^ ML_Syntax.print_string name ^ ", Position.none), " ^
297 ML_Syntax.print_option (ML_Syntax.print_list print_interval) sel ^ "))";
298 in (name, get_name ^ " (ML_Context.the_local_context ()) " ^ txt) end));
302 val _ = add_keywords ["(", ")", "-", ","];
303 val _ = thm_antiq "thm" ProofContext.get_fact_single "ProofContext.get_fact_single";
304 val _ = thm_antiq "thms" ProofContext.get_fact "ProofContext.get_fact";
308 val _ = proj_value_antiq "cpat" (Scan.lift Args.name >>
310 "Thm.cterm_of (ML_Context.the_global_context ()) (Syntax.read_term \
311 \(ProofContext.set_mode ProofContext.mode_pattern (ML_Context.the_local_context ()))"
312 ^ ML_Syntax.print_string name ^ ")", "")));
316 structure Basic_ML_Context: BASIC_ML_CONTEXT = ML_Context;
317 open Basic_ML_Context;