(* Title: Pure/Isar/expression.ML Author: Clemens Ballarin, TU Muenchen
Locale expressions and user interface layer of locales.
*)
signature EXPRESSION = sig (* Locale expressions *) datatype'term map = Positional of 'term optionlist | Named of (string * 'term) list type'term rewrites = (Attrib.binding * 'term) list type ('name, 'term) expr = ('name * ((string * bool) * ('term map * 'term rewrites))) list type expression_i = (string, term) expr * (binding * typ option * mixfix) list type expression = (xstring * Position.T, string) expr * (binding * stringoption * mixfix) list
(* Processing of context statements *) val cert_statement: Element.context_i list -> Element.statement_i ->
Proof.context -> (Attrib.binding * (term * term list) list) list * Proof.context val read_statement: Element.context list -> Element.statement ->
Proof.context -> (Attrib.binding * (term * term list) list) list * Proof.context
(* Declaring locales *) val cert_declaration: expression_i -> (Proof.context -> Proof.context) ->
Element.context_i list ->
Proof.context -> (((string * typ) * mixfix) list * (string * morphism) list
* Element.context_i list * Proof.context) * ((string * typ) list * Proof.context) val cert_read_declaration: expression_i -> (Proof.context -> Proof.context) ->
Element.context list ->
Proof.context -> (((string * typ) * mixfix) list * (string * morphism) list
* Element.context_i list * Proof.context) * ((string * typ) list * Proof.context) (*FIXME*) val read_declaration: expression -> (Proof.context -> Proof.context) -> Element.context list->
Proof.context -> (((string * typ) * mixfix) list * (string * morphism) list
* Element.context_i list * Proof.context) * ((string * typ) list * Proof.context) val add_locale: binding -> binding -> Bundle.name list ->
expression_i -> Element.context_i list -> theory -> string * local_theory val add_locale_cmd: binding -> binding -> Bundle.xname list ->
expression -> Element.context list -> theory -> string * local_theory
(* Processing of locale expressions *) val cert_goal_expression: expression_i -> Proof.context ->
(term listlist * term listlist * (string * morphism) list * (Attrib.binding * term) listlist * morphism) * Proof.context val read_goal_expression: expression -> Proof.context ->
(term listlist * term listlist * (string * morphism) list * (Attrib.binding * term) listlist * morphism) * Proof.context end;
structure Expression : EXPRESSION = struct
datatype ctxt = datatype Element.ctxt;
(*** Expressions ***)
datatype'term map =
Positional of'term option list |
Named of (string * 'term) list;
type expression_i = (string, term) expr * (binding * typ option * mixfix) list; type expression = (xstring * Position.T, string) expr * (binding * stringoption * mixfix) list;
(** Internalise locale names in expr **)
fun check_expr ctxt instances = map (apfst (Locale.check ctxt)) instances;
(** Parameters of expression **)
(*Sanity check of instantiations and extraction of implicit parameters. The latter only occurs iff strict = false. Positional instantiations are extended to match full length of parameter list
of instantiated locale.*)
fun parameters_of thy strict (expr, fixed) = let val ctxt = Proof_Context.init_global thy;
fun params_loc loc = Locale.params_of thy loc |> map (apfst #1); fun params_inst (loc, (prfx, (Positional insts, eqns))) = let val ps = params_loc loc; val d = length ps - length insts; val insts' = if d < 0 then
error ("More arguments than parameters in instantiation of locale " ^
quote (Locale.markup_name ctxt loc)) else insts @ replicate d NONE; val ps' = (ps ~~ insts') |>
map_filter (fn (p, NONE) => SOME p | (_, SOME _) => NONE); in (ps', (loc, (prfx, (Positional insts', eqns)))) end
| params_inst (loc, (prfx, (Named insts, eqns))) = let val _ =
reject_dups "Duplicate instantiation of the following parameter(s): "
(map fst insts); val ps' = (insts, params_loc loc) |-> fold (fn (p, _) => fn ps => if AList.defined (op =) ps p then AList.delete (op =) p ps else error (quote p ^ " not a parameter of instantiated expression")); in (ps', (loc, (prfx, (Named insts, eqns)))) end; fun params_expr is = let val (is', ps') = fold_map (fn i => fn ps => let val (ps', i') = params_inst i; val ps'' = distinct parm_eq (ps @ ps'); in (i', ps'') end) is [] in (ps', is') end;
val (implicit, expr') = params_expr expr;
val implicit' = map #1 implicit; val fixed' = map (Variable.check_name o #1) fixed; val _ = reject_dups "Duplicate fixed parameter(s): " fixed'; val implicit'' = if strict then [] else let val _ =
reject_dups "Parameter(s) declared simultaneously in expression and for clause: "
(implicit' @ fixed'); inmap (fn (x, mx) => (Binding.name x, NONE, mx)) implicit end;
in (expr', implicit'' @ fixed) end;
(** Read instantiation **)
(* Parse positional or named instantiation *)
local
fun prep_inst prep_term ctxt parms (Positional insts) =
(insts ~~ parms) |> map
(fn (NONE, p) => Free (p, dummyT)
| (SOME t, _) => prep_term ctxt t)
| prep_inst prep_term ctxt parms (Named insts) =
parms |> map (fn p =>
(case AList.lookup (op =) insts p of
SOME t => prep_term ctxt t |
NONE => Free (p, dummyT)));
in
fun parse_inst x = prep_inst Syntax.parse_term x; fun make_inst x = prep_inst (K I) x;
end;
(* Instantiation morphism *)
fun inst_morphism params ((prfx, mandatory), insts') ctxt = let (* parameters *) val parm_types = map #2 params; val type_parms = fold Term.add_tfreesT parm_types [];
(* type inference *) val parm_types' = map (Type_Infer.paramify_vars o Logic.varifyT_global) parm_types; val type_parms' = fold Term.add_tvarsT parm_types' []; val checked =
(map (Logic.mk_type o TVar) type_parms' @ map2 Type.constraint parm_types' insts')
|> Syntax.check_terms (Config.put Type_Infer.object_logic false ctxt) val (type_parms'', insts'') = chop (length type_parms') checked;
(* context *) val ctxt' = fold Proof_Context.augment checked ctxt; val certT = Thm.trim_context_ctyp o Thm.ctyp_of ctxt'; val cert = Thm.trim_context_cterm o Thm.cterm_of ctxt';
(* instantiation *) val instT =
TFrees.build
(fold2 (fn v => fn T => not (TFree v = T) ? TFrees.add (v, T))
type_parms (map Logic.dest_type type_parms'')); val cert_inst =
Frees.build
(fold2 (fn v => fn t => not (Free v = t) ? Frees.add (v, cert t))
(map #1 params ~~ map (Term_Subst.instantiateT_frees instT) parm_types) insts''); in
(Element.instantiate_normalize_morphism (TFrees.map (K certT) instT, cert_inst) $>
Morphism.binding_morphism "Expression.inst" (Binding.prefix mandatory prfx), ctxt') end;
(*** Locale processing ***)
(** Parsing **)
fun parse_elem prep_typ prep_term ctxt =
Element.map_ctxt
{binding = I,
typ = prep_typ ctxt,
term = prep_term (Proof_Context.set_mode Proof_Context.mode_schematic ctxt),
pattern = prep_term (Proof_Context.set_mode Proof_Context.mode_pattern ctxt),
fact = I,
attrib = I};
fun prepare_stmt prep_prop prep_obtains ctxt stmt =
(case stmt of
Element.Shows raw_shows =>
raw_shows |> (map o apsnd o map) (fn (t, ps) =>
(prep_prop (Proof_Context.set_mode Proof_Context.mode_schematic ctxt) t, map (prep_prop (Proof_Context.set_mode Proof_Context.mode_pattern ctxt)) ps))
| Element.Obtains raw_obtains => let val ((_, thesis), thesis_ctxt) = Obtain.obtain_thesis ctxt; val obtains = prep_obtains thesis_ctxt thesis raw_obtains; inmap (fn (b, t) => ((b, []), [(t, [])])) obtains end);
(** Simultaneous type inference: instantiations + elements + statement **)
local
fun mk_type T = (Logic.mk_type T, []); fun mk_term t = (t, []); fun mk_propp (p, pats) = (Type.constraint propT p, pats);
fun dest_type (T, []) = Logic.dest_type T; fun dest_term (t, []) = t; fun dest_propp (p, pats) = (p, pats);
fun finish_inst ctxt (loc, (prfx, inst)) = let val thy = Proof_Context.theory_of ctxt; val (morph, _) = inst_morphism (map #1 (Locale.params_of thy loc)) (prfx, inst) ctxt; in (loc, morph) end;
fun finish_fixes (parms: (string * typ) list) = map (fn (binding, _, mx) => letval x = Binding.name_of binding in (binding, AList.lookup (op =) parms x, mx) end);
local
fun closeup _ _ false elem = elem
| closeup (outer_ctxt, ctxt) parms true elem = let (* FIXME consider closing in syntactic phase -- before type checking *) fun close_frees t = let val rev_frees =
Term.fold_aterms (fn Free (x, T) => if Variable.is_fixed outer_ctxt x orelse AList.defined (op =) parms x then I else insert (op =) (x, T) | _ => I) t []; in fold (Logic.all o Free) rev_frees t end;
val xs = maps (fn Fixes fixes => map (Variable.check_name o #1) fixes | _ => [])
(Fixes fors :: elems'); val (parms, ctxt5) = fold_map Proof_Context.inferred_param xs ctxt4;
val fors' = finish_fixes parms fors; val fixed = map (fn (b, SOME T, mx) => ((Binding.name_of b, T), mx)) fors'; val deps = map (finish_inst ctxt5) insts; val elems'' = map (finish_elem (ctxt1, ctxt5) parms do_close) elems';
in ((fixed, deps, eqnss', elems'', concl), (parms, ctxt5)) end;
in
fun cert_full_context_statement x =
prep_full_context_statement (K I) (K I) Obtain.cert_obtains
Proof_Context.cert_var make_inst Syntax.check_props (K I) Proof_Context.cert_var (K I) x;
fun cert_read_full_context_statement x =
prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Obtain.parse_obtains
Proof_Context.read_var make_inst Syntax.check_props (K I) Proof_Context.cert_var (K I) x;
fun read_full_context_statement x =
prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Obtain.parse_obtains
Proof_Context.read_var parse_inst Syntax.read_props Attrib.check_src Proof_Context.read_var check_expr x;
end;
(* Context statement: elements + statement *)
local
fun prep_statement prep activate raw_elems raw_stmt ctxt = let val ((_, _, _, elems, concl), _) =
prep {strict = true, do_close = false, fixed_frees = true}
([], []) I raw_elems raw_stmt ctxt; val ctxt' = ctxt
|> Proof_Context.set_stmt true
|> fold_map activate elems |> #2
|> Proof_Context.restore_stmt ctxt; in (concl, ctxt') end;
in
fun cert_statement x = prep_statement cert_full_context_statement Element.activate_i x; fun read_statement x = prep_statement read_full_context_statement Element.activate x;
end;
(* Locale declaration: import + elements *)
fun fix_params params =
Proof_Context.add_fixes (map (fn ((x, T), mx) => (Binding.name x, SOME T, mx)) params) #> snd;
local
fun prep_declaration prep activate raw_import init_body raw_elems ctxt = let val ((fixed, deps, eqnss, elems, _), (parms, ctxt0)) =
prep {strict = false, do_close = true, fixed_frees = false}
raw_import init_body raw_elems (Element.Shows []) ctxt; val _ = null (flat eqnss) orelse error "Illegal rewrites clause(s) in declaration of locale"; (* Declare parameters and imported facts *) val ctxt' = ctxt
|> fix_params fixed
|> fold (Context.proof_map o Locale.activate_facts NONE) deps; val (elems', ctxt'') = ctxt'
|> Proof_Context.set_stmt true
|> fold_map activate elems
||> Proof_Context.restore_stmt ctxt'; in ((fixed, deps, elems', ctxt''), (parms, ctxt0)) end;
in
fun cert_declaration x = prep_declaration cert_full_context_statement Element.activate_i x; fun cert_read_declaration x = prep_declaration cert_read_full_context_statement Element.activate x; fun read_declaration x = prep_declaration read_full_context_statement Element.activate x;
fun prep_goal_expression prep expression ctxt = let val thy = Proof_Context.theory_of ctxt;
val ((fixed, deps, eqnss, _, _), _) =
prep {strict = true, do_close = true, fixed_frees = true} expression I []
(Element.Shows []) ctxt; (* proof obligations *) val propss = map (props_of thy) deps; val eq_propss = (map o map) snd eqnss;
val goal_ctxt = ctxt
|> fix_params fixed
|> (fold o fold) Proof_Context.augment (propss @ eq_propss);
val export = Proof_Context.export_morphism goal_ctxt ctxt; val exp_fact = Drule.zero_var_indexes_list o map Thm.strip_shyps o Morphism.fact export; val exp_term = Term_Subst.zero_var_indexes o Morphism.term export; val exp_typ = Logic.type_map exp_term; val export' =
Morphism.morphism "Expression.prep_goal"
{binding = [], typ = [K exp_typ], term = [K exp_term], fact = [K exp_fact]}; in ((propss, eq_propss, deps, eqnss, export'), goal_ctxt) end;
in
fun cert_goal_expression x = prep_goal_expression cert_full_context_statement x; fun read_goal_expression x = prep_goal_expression read_full_context_statement x;
end;
(*** Locale declarations ***)
(* extract specification text *)
val norm_term = Envir.beta_norm oo Term.subst_atomic;
fun bind_def ctxt eq (env, eqs) = let val _ = Local_Defs.cert_def ctxt (K []) eq; val ((y, T), b) = Local_Defs.abs_def eq; val b' = norm_term env b; fun err msg = error (msg ^ ": " ^ quote y); in
(casefilter (fn (Free (y', _), _) => y = y' | _ => false) env of
[] => ((Free (y, T), b') :: env, eq :: eqs)
| dups => if forall (fn (_, b'') => b' aconv b'') dups then (env, eqs) else err "Attempt to redefine variable") end;
(* text has the following structure: (((exts, exts'), (ints, ints')), (xs, env, defs)) where exts: external assumptions (terms in assumes elements) exts': dito, normalised wrt. env ints: internal assumptions (terms in assumptions from insts) ints': dito, normalised wrt. env xs: the free variables in exts' and ints' and rhss of definitions, this includes parameters except defined parameters env: list of term pairs encoding substitutions, where the first term is a free variable; substitutions represent defines elements and the rhs is normalised wrt. the previous env defs: the equations from the defines elements
*)
fun eval_text _ _ (Fixes _) text = text
| eval_text _ _ (Constrains _) text = text
| eval_text _ is_ext (Assumes asms)
(((exts, exts'), (ints, ints')), (env, defs)) = let val ts = maps (map #1 o #2) asms; val ts' = map (norm_term env) ts; val spec' = if is_ext then ((exts @ ts, exts' @ ts'), (ints, ints')) else ((exts, exts'), (ints @ ts, ints' @ ts')); in (spec', (env, defs)) end
| eval_text ctxt _ (Defines defs) (spec, binds) =
(spec, fold (bind_def ctxt o #1 o #2) defs binds)
| eval_text _ _ (Notes _) text = text
| eval_text _ _ (Lazy_Notes _) text = text;
fun eval_inst ctxt (loc, morph) text = let val thy = Proof_Context.theory_of ctxt; val (asm, defs) = Locale.specification_of thy loc; val asm' = Option.map (Morphism.term morph) asm; val defs' = map (Morphism.term morph) defs; val text' =
text |>
(if is_some asm then
eval_text ctxt false (Assumes [(Binding.empty_atts, [(the asm', [])])]) else I) |>
(ifnot (null defs) then
eval_text ctxt false (Defines (map (fn def => (Binding.empty_atts, (def, []))) defs')) else I) (* FIXME clone from locale.ML *) in text' end;
fun eval_elem ctxt elem text =
eval_text ctxt true elem text;
fun eval ctxt deps elems = let val text' = fold (eval_inst ctxt) deps ((([], []), ([], [])), ([], [])); val ((spec, (_, defs))) = fold (eval_elem ctxt) elems text'; in (spec, defs) end;
(* axiomsN: name of theorem set with destruct rules for locale predicates,
also name suffix of delta predicates and assumptions. *)
val axiomsN = "axioms";
local
(* introN: name of theorems for introduction rules of locale and
delta predicates *)
val introN = "intro";
fun atomize_spec ctxt ts = let val t = Logic.mk_conjunction_balanced ts; val body = Object_Logic.atomize_term ctxt t; val bodyT = Term.fastype_of body; in if bodyT = propT then (t, propT, Thm.reflexive (Thm.cterm_of ctxt t)) else (body, bodyT, Object_Logic.atomize ctxt (Thm.cterm_of ctxt t)) end;
(* achieve plain syntax for locale predicates (without "PROP") *)
fun aprop_tr' n c = let val c' = Lexicon.mark_const c; fun tr' (_: Proof.context) T args = if T <> dummyT andalso length args = n then Syntax.const"_aprop" $ Term.list_comb (Syntax.const c', args) elseraiseMatch; in (c', tr') end;
(* define one predicate including its intro rule and axioms - binding: predicate name - parms: locale parameters - defs: thms representing substitutions from defines elements - ts: terms representing locale assumptions (not normalised wrt. defs) - norm_ts: terms representing locale assumptions (normalised wrt. defs) - thy: the theory
*)
fun def_pred binding parms defs ts norm_ts thy = let val name = Sign.full_name thy binding;
val thy_ctxt = Proof_Context.init_global thy;
val (body, bodyT, body_eq) = atomize_spec thy_ctxt norm_ts; val env = Names.build (Names.add_free_names body); val xs = filter (Names.defined env o #1) parms; val Ts = map #2 xs; val type_tfrees = TFrees.build (fold TFrees.add_tfreesT Ts); val extra_tfrees =
TFrees.build (TFrees.add_tfrees_unless (TFrees.defined type_tfrees) body)
|> TFrees.keys |> map TFree; val predT = map Term.itselfT extra_tfrees ---> Ts ---> bodyT;
val args = map Logic.mk_type extra_tfrees @ map Free xs; val head = Term.list_comb (Const (name, predT), args); val statement = Object_Logic.ensure_propT thy_ctxt head;
fun gen_add_locale prep_include prep_decl
binding raw_predicate_binding raw_includes raw_import raw_body thy = let val name = Sign.full_name thy binding; val _ = Locale.defined thy name andalso
error ("Duplicate definition of locale " ^ quote name);
val ctxt = Proof_Context.init_global thy; val includes = map (prep_include ctxt) raw_includes;
val ((fixed, deps, body_elems, _), (parms, ctxt')) =
ctxt
|> Bundle.includes includes
|> prep_decl raw_import I raw_body; val text as (((_, exts'), _), defs) = eval ctxt' deps body_elems;
val type_tfrees = TFrees.build (fold (TFrees.add_tfreesT o #2) parms); val extra_tfrees =
TFrees.build (fold (TFrees.add_tfrees_unless (TFrees.defined type_tfrees)) exts')
|> TFrees.keys; val _ = if null extra_tfrees then () else warning ("Additional type variable(s) in locale specification " ^
Binding.print binding ^ ": " ^
commas (map (Syntax.string_of_typ ctxt' o TFree) extra_tfrees));
val predicate_binding = if Binding.is_empty raw_predicate_binding then binding else raw_predicate_binding; val ((a_statement, a_intro, a_axioms), (b_statement, b_intro, b_axioms), thy') =
define_preds predicate_binding parms text thy; val pred_ctxt = Proof_Context.init_global thy';
val a_satisfy = Element.satisfy_morphism a_axioms; val b_satisfy = Element.satisfy_morphism b_axioms;
val params = fixed @
maps (fn Fixes fixes => map (fn (b, SOME T, mx) => ((Binding.name_of b, T), mx)) fixes | _ => []) body_elems; val asm = if is_some b_statement then b_statement else a_statement;
val hyp_spec = filter is_hyp body_elems;
val notes = if is_some asm then
[("", [((Binding.suffix_name ("_" ^ axiomsN) binding, []),
[([Assumption.assume pred_ctxt (Thm.cterm_of pred_ctxt (the asm))],
[Attrib.internal \<^here> (K Locale.witness_add)])])])] else [];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.