106 [Pretty.str "The above error(s) occurred in expression:", Pretty.brk 1, |
106 [Pretty.str "The above error(s) occurred in expression:", Pretty.brk 1, |
107 pretty_expr thy (Expr expr)]) |
107 pretty_expr thy (Expr expr)]) |
108 in error err_msg end; |
108 in error err_msg end; |
109 |
109 |
110 |
110 |
111 (** Internalise locale names **) |
111 (** Internalise locale names in expr **) |
112 |
112 |
113 fun intern_expr thy (Expr instances) = Expr (map (apfst (NewLocale.intern thy)) instances); |
113 fun intern thy (Expr instances) = Expr (map (apfst (NewLocale.intern thy)) instances); |
114 |
114 |
115 |
115 |
116 (** Parameters of expression (not expression_i). |
116 (** Parameters of expression. |
117 Sanity check of instantiations. |
117 Sanity check of instantiations. |
118 Positional instantiations are extended to match full length of parameter list. **) |
118 Positional instantiations are extended to match full length of parameter list. **) |
119 |
119 |
120 fun parameters thy (expr, fixed : (Name.binding * string option * mixfix) list) = |
120 fun parameters_of thy (expr, fixed) = |
121 let |
121 let |
122 fun reject_dups message xs = |
122 fun reject_dups message xs = |
123 let val dups = duplicates (op =) xs |
123 let val dups = duplicates (op =) xs |
124 in |
124 in |
125 if null dups then () else error (message ^ commas dups) |
125 if null dups then () else error (message ^ commas dups) |
128 fun match_bind (n, b) = (n = Name.name_of b); |
128 fun match_bind (n, b) = (n = Name.name_of b); |
129 fun bind_eq (b1, b2) = (Name.name_of b1 = Name.name_of b2); |
129 fun bind_eq (b1, b2) = (Name.name_of b1 = Name.name_of b2); |
130 (* FIXME: cannot compare bindings for equality. *) |
130 (* FIXME: cannot compare bindings for equality. *) |
131 |
131 |
132 fun params_loc loc = |
132 fun params_loc loc = |
133 (NewLocale.params_of thy loc |> map (fn (p, _, mx) => (p, mx)), loc) |
133 (NewLocale.params_of thy loc |> map (fn (p, _, mx) => (p, mx)), loc); |
134 handle ERROR msg => err_in_expr thy msg (Expr [(loc, ("", Named []))]); |
|
135 fun params_inst (expr as (loc, (prfx, Positional insts))) = |
134 fun params_inst (expr as (loc, (prfx, Positional insts))) = |
136 let |
135 let |
137 val (ps, loc') = params_loc loc; |
136 val (ps, loc') = params_loc loc; |
138 val d = length ps - length insts; |
137 val d = length ps - length insts; |
139 val insts' = |
138 val insts' = |
146 (ps', (loc', (prfx, Positional insts'))) |
145 (ps', (loc', (prfx, Positional insts'))) |
147 end |
146 end |
148 | params_inst (expr as (loc, (prfx, Named insts))) = |
147 | params_inst (expr as (loc, (prfx, Named insts))) = |
149 let |
148 let |
150 val _ = reject_dups "Duplicate instantiation of the following parameter(s): " |
149 val _ = reject_dups "Duplicate instantiation of the following parameter(s): " |
151 (map fst insts) |
150 (map fst insts); |
152 handle ERROR msg => err_in_expr thy msg (Expr [expr]); |
|
153 |
151 |
154 val (ps, loc') = params_loc loc; |
152 val (ps, loc') = params_loc loc; |
155 val ps' = fold (fn (p, _) => fn ps => |
153 val ps' = fold (fn (p, _) => fn ps => |
156 if AList.defined match_bind ps p then AList.delete match_bind p ps |
154 if AList.defined match_bind ps p then AList.delete match_bind p ps |
157 else err_in_expr thy (quote p ^" not a parameter of instantiated expression.") |
155 else error (quote p ^" not a parameter of instantiated expression.")) insts ps; |
158 (Expr [expr])) insts ps; |
|
159 in |
156 in |
160 (ps', (loc', (prfx, Named insts))) |
157 (ps', (loc', (prfx, Named insts))) |
161 end; |
158 end; |
162 fun params_expr (Expr is) = |
159 fun params_expr (Expr is) = |
163 let |
160 let |
166 val (ps', i') = params_inst i; |
163 val (ps', i') = params_inst i; |
167 val ps'' = AList.join bind_eq (fn p => fn (mx1, mx2) => |
164 val ps'' = AList.join bind_eq (fn p => fn (mx1, mx2) => |
168 (* FIXME: should check for bindings being the same. |
165 (* FIXME: should check for bindings being the same. |
169 Instead we check for equal name and syntax. *) |
166 Instead we check for equal name and syntax. *) |
170 if mx1 = mx2 then mx1 |
167 if mx1 = mx2 then mx1 |
171 else err_in_expr thy ("Conflicting syntax for parameter" ^ quote (Name.name_of p) ^ " in expression.") |
168 else error ("Conflicting syntax for parameter" ^ quote (Name.name_of p) ^ |
172 (Expr is)) (ps, ps') |
169 " in expression.")) (ps, ps') |
173 in (i', ps'') end) is [] |
170 in (i', ps'') end) is [] |
174 in |
171 in |
175 (ps', Expr is') |
172 (ps', Expr is') |
176 end; |
173 end; |
177 |
174 |
178 val (parms, expr') = params_expr expr; |
175 val (parms, expr') = params_expr expr; |
179 |
176 |
180 val parms' = map (fst #> Name.name_of) parms; |
177 val parms' = map (#1 #> Name.name_of) parms; |
181 val fixed' = map (#1 #> Name.name_of) fixed; |
178 val fixed' = map (#1 #> Name.name_of) fixed; |
182 val _ = reject_dups "Duplicate fixed parameter(s): " fixed'; |
179 val _ = reject_dups "Duplicate fixed parameter(s): " fixed'; |
183 val _ = reject_dups "Parameter(s) declared simultaneously in expression and for clause: " (parms' @ fixed'); |
180 val _ = reject_dups "Parameter(s) declared simultaneously in expression and for clause: " (parms' @ fixed'); |
184 |
181 |
185 in (expr', (parms, fixed)) end; |
182 in (expr', (map (fn (b, mx) => (b, NONE, mx)) parms @ fixed)) end; |
186 |
183 |
187 |
184 |
188 (** Read instantiation **) |
185 (** Read instantiation **) |
189 |
186 |
190 fun read_inst parse_term parms (prfx, insts) ctxt = |
187 local |
|
188 |
|
189 fun prep_inst parse_term parms (prfx, insts) ctxt = |
191 let |
190 let |
192 (* parameters *) |
191 (* parameters *) |
193 val (parm_names, parm_types) = split_list parms; |
192 val (parm_names, parm_types) = split_list parms; |
194 val type_parm_names = fold Term.add_tfreesT parm_types [] |> map fst; |
193 val type_parm_names = fold Term.add_tfreesT parm_types [] |> map fst; |
195 |
194 |
219 val inst = Symtab.make insts''; |
218 val inst = Symtab.make insts''; |
220 in |
219 in |
221 (Element.inst_morphism (ProofContext.theory_of ctxt) (instT, inst) $> |
220 (Element.inst_morphism (ProofContext.theory_of ctxt) (instT, inst) $> |
222 Morphism.name_morphism (Name.qualified prfx), ctxt') |
221 Morphism.name_morphism (Name.qualified prfx), ctxt') |
223 end; |
222 end; |
|
223 |
|
224 in |
|
225 |
|
226 fun read_inst x = prep_inst Syntax.parse_term x; |
|
227 (* fun cert_inst x = prep_inst (K I) x; *) |
|
228 |
|
229 end; |
|
230 |
224 |
231 |
225 |
232 (** Test code **) |
226 (** Debugging **) |
|
227 |
233 |
228 fun debug_parameters raw_expr ctxt = |
234 fun debug_parameters raw_expr ctxt = |
229 let |
235 let |
230 val thy = ProofContext.theory_of ctxt; |
236 val thy = ProofContext.theory_of ctxt; |
231 val expr = apfst (intern_expr thy) raw_expr; |
237 val expr = apfst (intern thy) raw_expr; |
232 val (expr', (parms, fixed)) = parameters thy expr; |
238 val (expr', fixed) = parameters_of thy expr; |
233 in ctxt end; |
239 in ctxt end; |
234 |
240 |
235 |
241 |
236 fun debug_context (raw_expr, fixed) ctxt = |
242 fun debug_context (raw_expr, fixed) ctxt = |
237 let |
243 let |
238 val thy = ProofContext.theory_of ctxt; |
244 val thy = ProofContext.theory_of ctxt; |
239 val expr = intern_expr thy raw_expr; |
245 val expr = intern thy raw_expr; |
240 val (expr', (parms, fixed)) = parameters thy (expr, fixed); |
246 val (expr', fixed) = parameters_of thy (expr, fixed); |
241 |
247 |
242 fun declare_parameters (parms, fixed) ctxt = |
248 fun declare_parameters fixed ctxt = |
243 let |
249 let |
244 val (parms', ctxt') = |
250 val (fixed', ctxt') = ProofContext.add_fixes fixed ctxt; |
245 ProofContext.add_fixes (map (fn (p, mx) => (p, NONE, mx)) parms) ctxt; |
|
246 val (fixed', ctxt'') = |
|
247 ProofContext.add_fixes fixed ctxt'; |
|
248 in |
251 in |
249 (parms' @ fixed', ctxt'') |
252 (fixed', ctxt') |
250 end; |
253 end; |
251 |
254 |
252 fun rough_inst loc prfx insts ctxt = |
255 fun rough_inst loc prfx insts ctxt = |
253 let |
256 let |
254 (* locale data *) |
257 (* locale data *) |
302 ctxt'' |
305 ctxt'' |
303 end; |
306 end; |
304 |
307 |
305 val Expr [(loc1, (prfx1, insts1))] = expr'; |
308 val Expr [(loc1, (prfx1, insts1))] = expr'; |
306 val ctxt0 = ProofContext.init thy; |
309 val ctxt0 = ProofContext.init thy; |
307 val (parms, ctxt') = declare_parameters (parms, fixed) ctxt0; |
310 val (parms, ctxt') = declare_parameters fixed ctxt0; |
308 val (morph1, ctxt'') = rough_inst loc1 prfx1 insts1 ctxt'; |
311 val (morph1, ctxt'') = rough_inst loc1 prfx1 insts1 ctxt'; |
309 val ctxt'' = add_declarations loc1 morph1 ctxt'; |
312 val ctxt'' = add_declarations loc1 morph1 ctxt'; |
310 in ctxt0 end; |
313 in ctxt0 end; |
311 |
314 |
312 |
315 |
346 fun check_autofix_elems elems concl ctxt = |
349 fun check_autofix_elems elems concl ctxt = |
347 let |
350 let |
348 val termss = elems |> map extract_elem; |
351 val termss = elems |> map extract_elem; |
349 val all_terms' = (burrow o burrow_fst) (Syntax.check_terms ctxt) (concl @ flat termss); |
352 val all_terms' = (burrow o burrow_fst) (Syntax.check_terms ctxt) (concl @ flat termss); |
350 (* val (ctxt', all_props') = ProofContext.check_propp_schematic (ctxt, concl @ flat propss); *) |
353 (* val (ctxt', all_props') = ProofContext.check_propp_schematic (ctxt, concl @ flat propss); *) |
351 val _ = "check" |> warning; |
|
352 val _ = PolyML.makestring all_terms' |> warning; |
|
353 val (concl', terms') = chop (length concl) all_terms'; |
354 val (concl', terms') = chop (length concl) all_terms'; |
354 val ctxt'' = (fold o fold) (fn (t, _) => Variable.auto_fixes t) terms' ctxt; |
355 val ctxt'' = (fold o fold) (fn (t, _) => Variable.auto_fixes t) terms' ctxt; |
355 in (terms' |> unflat termss |> curry (op ~~) elems |> map restore_elem, concl', ctxt'') end; |
356 in (terms' |> unflat termss |> curry (op ~~) elems |> map restore_elem, concl', ctxt'') end; |
356 |
357 |
357 |
358 |
474 prep_concl raw_concl; |
475 prep_concl raw_concl; |
475 |
476 |
476 (* Retrieve parameter types *) |
477 (* Retrieve parameter types *) |
477 val xs = fold (fn Fixes fixes => (fn ps => ps @ map (Name.name_of o #1) fixes) | |
478 val xs = fold (fn Fixes fixes => (fn ps => ps @ map (Name.name_of o #1) fixes) | |
478 _ => fn ps => ps) elems []; |
479 _ => fn ps => ps) elems []; |
479 val (Ts, _) = fold_map ProofContext.inferred_param xs ctxt; |
480 val (Ts, ctxt') = fold_map ProofContext.inferred_param xs ctxt; |
480 val parms = xs ~~ Ts; |
481 val parms = xs ~~ Ts; |
481 |
482 |
482 val (elems', text) = finish_elems ctxt parms do_close elems ((([], []), ([], [])), ([], [], [])); |
483 val (elems', text) = finish_elems ctxt' parms do_close elems ((([], []), ([], [])), ([], [], [])); |
483 (* text has the following structure: |
484 (* text has the following structure: |
484 (((exts, exts'), (ints, ints')), (xs, env, defs)) |
485 (((exts, exts'), (ints, ints')), (xs, env, defs)) |
485 where |
486 where |
486 exts: external assumptions (terms in external assumes elements) |
487 exts: external assumptions (terms in external assumes elements) |
487 exts': dito, normalised wrt. env |
488 exts': dito, normalised wrt. env |
518 fun prep_context_statement prep_expr prep_elems |
519 fun prep_context_statement prep_expr prep_elems |
519 do_close imprt elements raw_concl context = |
520 do_close imprt elements raw_concl context = |
520 let |
521 let |
521 val thy = ProofContext.theory_of context; |
522 val thy = ProofContext.theory_of context; |
522 |
523 |
523 val (expr, (params, fors)) = parameters thy (apfst (prep_expr thy) imprt); |
524 val (expr, fixed) = parameters_of thy (apfst (prep_expr thy) imprt); |
524 val ctxt = context |> |
525 val ctxt = context |> ProofContext.add_fixes fixed |> snd; |
525 ProofContext.add_fixes (map (fn (b, mx) => (b, NONE, mx)) params) |> snd |> |
|
526 ProofContext.add_fixes fors |> snd; |
|
527 in |
526 in |
528 case expr of |
527 case expr of |
529 Expr [] => let |
528 Expr [] => let |
530 val ((parms, elems, concl), (spec, (_, _, defs))) = prep_elems do_close |
529 val ((parms, elems, concl), (spec, (_, _, defs))) = prep_elems do_close |
531 context elements raw_concl; |
530 context elements raw_concl; |