1 (* Title: Pure/ML/ml_context.ML
5 ML context and antiquotations.
8 signature BASIC_ML_CONTEXT =
10 val the_context: unit -> theory
11 val thm: xstring -> thm
12 val thms: xstring -> thm list
15 signature ML_CONTEXT =
17 include BASIC_ML_CONTEXT
18 val get_context: unit -> Context.generic option
19 val set_context: Context.generic option -> unit
20 val setmp: Context.generic option -> ('a -> 'b) -> 'a -> 'b
21 val the_generic_context: unit -> Context.generic
22 val the_local_context: unit -> Proof.context
23 val pass: Context.generic option -> ('a -> 'b) -> 'a -> 'b * Context.generic option
24 val pass_context: Context.generic -> ('a -> 'b) -> 'a -> 'b * Context.generic
25 val save: ('a -> 'b) -> 'a -> 'b
26 val >> : (theory -> theory) -> unit
27 val add_keywords: string list -> unit
28 val inline_antiq: string ->
29 (Context.generic * Args.T list -> string * (Context.generic * Args.T list)) -> unit
30 val value_antiq: string ->
31 (Context.generic * Args.T list -> (string * string) * (Context.generic * Args.T list)) -> unit
32 val proj_value_antiq: string -> (Context.generic * Args.T list ->
33 (string * string * string) * (Context.generic * Args.T list)) -> unit
34 val eval_antiquotes_fn: (string * Position.T -> string * string) ref (* FIXME tmp *)
36 val use_mltext: bool -> Position.T -> string -> Context.generic option -> unit
37 val use_mltext_update: bool -> Position.T -> string -> Context.generic -> Context.generic
38 val use_let: Position.T -> string -> string -> string -> Context.generic -> Context.generic
39 val use: Path.T -> unit
40 val evaluate: (string -> unit) * (string -> 'b) -> bool ->
41 string * (unit -> 'a) option ref -> string -> 'a
44 structure ML_Context: ML_CONTEXT =
47 (** Implicit ML context **)
50 val current_context = ref (NONE: Context.generic option);
52 fun get_context () = ! current_context;
53 fun set_context opt_context = current_context := opt_context;
54 fun setmp opt_context f x = Library.setmp current_context opt_context f x;
57 fun the_generic_context () =
58 (case get_context () of
59 SOME context => context
60 | _ => error "Unknown context");
62 val the_local_context = Context.proof_of o the_generic_context;
64 val the_context = Context.theory_of o the_generic_context;
66 fun pass opt_context f x =
67 setmp opt_context (fn x => let val y = f x in (y, get_context ()) end) x;
69 fun pass_context context f x =
70 (case pass (SOME context) f x of
71 (y, SOME context') => (y, context')
72 | (_, NONE) => error "Lost context in ML");
74 fun save f x = NAMED_CRITICAL "ML" (fn () => setmp (get_context ()) f x);
76 fun change_theory f = NAMED_CRITICAL "ML" (fn () =>
77 set_context (SOME (Context.map_theory f (the_generic_context ()))));
81 (** ML antiquotations **)
83 (* maintain keywords *)
85 val global_lexicon = ref Scan.empty_lexicon;
87 fun add_keywords keywords = CRITICAL (fn () =>
88 change global_lexicon (Scan.extend_lexicon (map Symbol.explode keywords)));
91 (* maintain commands *)
93 datatype antiq = Inline of string | ProjValue of string * string * string;
94 val global_parsers = ref (Symtab.empty:
95 (Context.generic * Args.T list -> antiq * (Context.generic * Args.T list)) Symtab.table);
99 fun add_item kind name scan = CRITICAL (fn () =>
100 change global_parsers (fn tab =>
101 (if not (Symtab.defined tab name) then ()
102 else warning ("Redefined ML antiquotation: " ^ quote name);
103 Symtab.update (name, scan >> kind) tab)));
107 val inline_antiq = add_item Inline;
108 val proj_value_antiq = add_item ProjValue;
109 fun value_antiq name scan = proj_value_antiq name (scan >> (fn (a, s) => (a, s, "")));
116 fun syntax scan src =
117 #1 (Args.context_syntax "ML antiquotation" scan src (the_local_context ()));
120 let val ((name, _), pos) = Args.dest_src src in
121 (case Symtab.lookup (! global_parsers) name of
122 NONE => error ("Unknown ML antiquotation command: " ^ quote name ^ Position.str_of pos)
123 | SOME scan => syntax scan src)
129 structure T = OuterLex;
130 structure P = OuterParse;
133 P.!!! (P.position P.xname -- P.arguments --| Scan.ahead P.eof)
134 >> (fn ((x, pos), y) => Args.src ((x, y), pos));
137 (* input/output wrappers *)
141 val isabelle_struct = enclose "structure Isabelle =\nstruct\n" "end;";
142 val isabelle_struct0 = isabelle_struct "";
144 fun eval_antiquotes txt_pos =
146 val ants = Antiquote.scan_antiquotes txt_pos;
148 fun expand (Antiquote.Text s) names = (("", Symbol.escape s), names)
149 | expand (Antiquote.Antiq x) names =
150 (case command (Antiquote.scan_arguments (! global_lexicon) antiq x) of
151 Inline s => (("", s), names)
152 | ProjValue (a, s, f) =>
154 val a' = if ML_Syntax.is_identifier a then a else "val";
155 val ([b], names') = Name.variants [a'] names;
156 val binding = "val " ^ b ^ " = " ^ s ^ ";\n";
158 if f = "" then "Isabelle." ^ b
159 else "(" ^ f ^ " Isabelle." ^ b ^ ")";
160 in ((binding, value), names') end);
163 NAMED_CRITICAL "ML" (fn () => fold_map expand ants ML_Syntax.reserved)
164 |> #1 |> split_list |> pairself implode;
165 in (isabelle_struct decls, body) end;
169 val eval_antiquotes_fn = ref eval_antiquotes;
171 val trace = ref false;
173 fun eval_wrapper pr verbose pos txt =
175 val (txt1, txt2) = ! eval_antiquotes_fn (txt, pos); (* FIXME tmp hook *)
176 val _ = if ! trace then tracing (cat_lines [txt1, txt2]) else ();
178 use_text (the_default 1 (Position.line_of p), the_default "ML" (Position.file_of p)) pr;
180 NAMED_CRITICAL "ML" (fn () =>
181 (eval Position.none false txt1;
182 eval pos verbose txt2;
183 eval Position.none false isabelle_struct0))
191 fun use_mltext verbose pos txt opt_context =
192 setmp opt_context (fn () => eval_wrapper Output.ml_output verbose pos txt) ();
194 fun use_mltext_update verbose pos txt context =
195 #2 (pass_context context (fn () => eval_wrapper Output.ml_output verbose pos txt) ());
197 fun use_let pos bind body txt =
198 use_mltext_update false pos
199 ("ML_Context.set_context (SOME (let " ^ bind ^ " = " ^ txt ^ " in " ^ body ^
200 " end (ML_Context.the_generic_context ())));");
202 fun use path = eval_wrapper Output.ml_output true (Position.path path) (File.read path);
204 fun evaluate pr verbose (ref_name, r) txt = NAMED_CRITICAL "ML" (fn () =>
207 val _ = eval_wrapper pr verbose Position.none
208 ("val _ = (" ^ ref_name ^ " := SOME (fn () => " ^ txt ^ "))");
209 in (case ! r of NONE => error ("Bad evaluation for " ^ ref_name) | SOME e => e) end) ();
212 (* basic antiquotations *)
214 fun context x = (Scan.state >> Context.proof_of) x;
218 val _ = value_antiq "context" (Scan.succeed ("context", "ML_Context.the_local_context ()"));
220 val _ = inline_antiq "sort" (context -- Scan.lift Args.name >> (fn (ctxt, s) =>
221 ML_Syntax.atomic (ML_Syntax.print_sort (Syntax.read_sort ctxt s))));
223 val _ = inline_antiq "typ" (Args.typ >> (ML_Syntax.atomic o ML_Syntax.print_typ));
224 val _ = inline_antiq "term" (Args.term >> (ML_Syntax.atomic o ML_Syntax.print_term));
225 val _ = inline_antiq "prop" (Args.prop >> (ML_Syntax.atomic o ML_Syntax.print_term));
227 val _ = value_antiq "ctyp" (Args.typ >> (fn T =>
229 "Thm.ctyp_of (ML_Context.the_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_typ T))));
231 val _ = value_antiq "cterm" (Args.term >> (fn t =>
233 "Thm.cterm_of (ML_Context.the_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))));
235 val _ = value_antiq "cprop" (Args.prop >> (fn t =>
237 "Thm.cterm_of (ML_Context.the_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))));
239 fun type_ syn = (context -- Scan.lift Args.name >> (fn (ctxt, c) =>
240 #1 (Term.dest_Type (ProofContext.read_tyname ctxt c))
241 |> syn ? Sign.base_name
242 |> ML_Syntax.print_string));
244 val _ = inline_antiq "type_name" (type_ false);
245 val _ = inline_antiq "type_syntax" (type_ true);
247 fun const syn = context -- Scan.lift Args.name >> (fn (ctxt, c) =>
248 #1 (Term.dest_Const (ProofContext.read_const_proper ctxt c))
249 |> syn ? ProofContext.const_syntax_name ctxt
250 |> ML_Syntax.print_string);
252 val _ = inline_antiq "const_name" (const false);
253 val _ = inline_antiq "const_syntax" (const true);
255 val _ = inline_antiq "const"
256 (context -- Scan.lift Args.name --
257 Scan.optional (Scan.lift (Args.$$$ "(") |-- Args.enum1 "," Args.typ --| Scan.lift (Args.$$$ ")")) []
258 >> (fn ((ctxt, c), Ts) =>
260 val (c, _) = Term.dest_Const (ProofContext.read_const_proper ctxt c);
261 in ML_Syntax.atomic (ML_Syntax.print_term (ProofContext.mk_const ctxt (c, Ts))) end));
266 (** fact references **)
268 fun thm name = ProofContext.get_thm (the_local_context ()) name;
269 fun thms name = ProofContext.get_thms (the_local_context ()) name;
274 fun print_interval (Facts.FromTo arg) =
275 "Facts.FromTo " ^ ML_Syntax.print_pair ML_Syntax.print_int ML_Syntax.print_int arg
276 | print_interval (Facts.From i) = "Facts.From " ^ ML_Syntax.print_int i
277 | print_interval (Facts.Single i) = "Facts.Single " ^ ML_Syntax.print_int i;
279 fun thm_antiq kind get get_name = value_antiq kind
280 (context -- Scan.lift (Args.position Args.name -- Scan.option Args.thm_sel)
281 >> (fn (ctxt, ((name, pos), sel)) =>
283 val _ = get ctxt (Facts.Named ((name, pos), sel));
285 "(Facts.Named ((" ^ ML_Syntax.print_string name ^ ", Position.none), " ^
286 ML_Syntax.print_option (ML_Syntax.print_list print_interval) sel ^ "))";
287 in (name, get_name ^ " (ML_Context.the_local_context ()) " ^ txt) end));
291 val _ = add_keywords ["(", ")", "-", ","];
292 val _ = thm_antiq "thm" ProofContext.get_fact_single "ProofContext.get_fact_single";
293 val _ = thm_antiq "thms" ProofContext.get_fact "ProofContext.get_fact";
297 val _ = proj_value_antiq "cpat" (Scan.lift Args.name >>
299 "Thm.cterm_of (ML_Context.the_context ()) (Syntax.read_term \
300 \(ProofContext.set_mode ProofContext.mode_pattern (ML_Context.the_local_context ()))"
301 ^ ML_Syntax.print_string name ^ ")", "")));
303 (*final declarations of this structure!*)
305 fun >> f = change_theory f;
309 structure Basic_ML_Context: BASIC_ML_CONTEXT = ML_Context;
310 open Basic_ML_Context;