diff -r 111bbd2b12db -r 686963dbf6cd src/Pure/Isar/expression.ML --- a/src/Pure/Isar/expression.ML Fri Nov 21 15:54:53 2008 +0100 +++ b/src/Pure/Isar/expression.ML Fri Nov 21 18:01:39 2008 +0100 @@ -7,13 +7,13 @@ signature EXPRESSION = sig - type map + type 'term map type 'morph expr val empty_expr: 'morph expr - type expression = (string * map) expr * (Name.binding * string option * mixfix) list - type expression_i = Morphism.morphism expr * (Name.binding * typ option * mixfix) list + type expression = (string * string map) expr * (Name.binding * string option * mixfix) list +(* type expression_i = Morphism.morphism expr * (Name.binding * typ option * mixfix) list *) (* Declaring locales *) val add_locale: string -> bstring -> expression -> Element.context list -> theory -> @@ -22,12 +22,8 @@ val add_locale_i: string -> bstring -> expression_i -> Element.context_i list -> theory -> string * Proof.context *) - (* Debugging and development *) val parse_expression: OuterParse.token list -> expression * OuterParse.token list - val debug_parameters: expression -> Proof.context -> Proof.context - val debug_context: expression -> Proof.context -> Proof.context - end; @@ -39,14 +35,13 @@ (*** Expressions ***) -datatype map = - Positional of string option list | - Named of (string * string) list; +datatype 'term map = + Positional of 'term option list | + Named of (string * 'term) list; datatype 'morph expr = Expr of (string * 'morph) list; -type expression = (string * map) expr * (Name.binding * string option * mixfix) list; -type expression_i = Morphism.morphism expr * (Name.binding * typ option * mixfix) list; +type expression = (string * string map) expr * (Name.binding * string option * mixfix) list; val empty_expr = Expr []; @@ -184,31 +179,47 @@ (** Read instantiation **) +(* Parse positional or named instantiation *) + local -fun prep_inst parse_term parms (prfx, insts) ctxt = +fun prep_inst parse_term parms (Positional insts) ctxt = + (insts ~~ parms) |> map (fn + (NONE, p) => Syntax.parse_term ctxt p | + (SOME t, _) => parse_term ctxt t) + | prep_inst parse_term parms (Named insts) ctxt = + parms |> map (fn p => case AList.lookup (op =) insts p of + SOME t => parse_term ctxt t | + NONE => Syntax.parse_term ctxt p); + +in + +fun parse_inst x = prep_inst Syntax.parse_term x; +fun make_inst x = prep_inst (K I) x; + +end; + +(* Prepare type inference problem for Syntax.check_terms *) + +fun varify_indexT i ty = ty |> Term.map_atyps + (fn TFree (a, S) => TVar ((a, i), S) + | TVar (ai, _) => raise TYPE ("Illegal schematic variable: " ^ + quote (Term.string_of_vname ai), [ty], [])); + +(* Instantiation morphism *) + +fun inst_morph (parm_names, parm_types) (prfx, insts') ctxt = let (* parameters *) - val (parm_names, parm_types) = split_list parms; val type_parm_names = fold Term.add_tfreesT parm_types [] |> map fst; - (* parameter instantiations *) - val insts' = case insts of - Positional insts => (insts ~~ parm_names) |> map (fn - (NONE, p) => parse_term ctxt p | - (SOME t, _) => parse_term ctxt t) | - Named insts => parm_names |> map (fn - p => case AList.lookup (op =) insts p of - SOME t => parse_term ctxt t | - NONE => parse_term ctxt p); - (* type inference and contexts *) val parm_types' = map (TypeInfer.paramify_vars o Logic.varifyT) parm_types; val type_parms = fold Term.add_tvarsT parm_types' [] |> map (Logic.mk_type o TVar); val arg = type_parms @ map2 TypeInfer.constrain parm_types' insts'; val res = Syntax.check_terms ctxt arg; val ctxt' = ctxt |> fold Variable.auto_fixes res; - + (* instantiation *) val (type_parms'', res') = chop (length type_parms) res; val insts'' = (parm_names ~~ res') |> map_filter @@ -221,97 +232,6 @@ Morphism.name_morphism (Name.qualified prfx), ctxt') end; -in - -fun read_inst x = prep_inst Syntax.parse_term x; -(* fun cert_inst x = prep_inst (K I) x; *) - -end; - - -(** Test code **) - -fun debug_parameters raw_expr ctxt = - let - val thy = ProofContext.theory_of ctxt; - val expr = apfst (intern thy) raw_expr; - val (expr', fixed) = parameters_of thy expr; - in ctxt end; - - -fun debug_context (raw_expr, fixed) ctxt = - let - val thy = ProofContext.theory_of ctxt; - val expr = intern thy raw_expr; - val (expr', fixed) = parameters_of thy (expr, fixed); - - fun declare_parameters fixed ctxt = - let - val (fixed', ctxt') = ProofContext.add_fixes fixed ctxt; - in - (fixed', ctxt') - end; - - fun rough_inst loc prfx insts ctxt = - let - (* locale data *) - val (parm_names, parm_types) = loc |> NewLocale.params_of thy |> - map (fn (b, SOME T, _) => (Name.name_of b, T)) |> split_list; - - (* type parameters *) - val type_parm_names = fold Term.add_tfreesT parm_types [] |> map fst; - - (* parameter instantiations *) - val insts' = case insts of - Positional insts => (insts ~~ parm_names) |> map (fn - (NONE, p) => Syntax.parse_term ctxt p | - (SOME t, _) => Syntax.parse_term ctxt t) | - Named insts => parm_names |> map (fn - p => case AList.lookup (op =) insts p of - SOME t => Syntax.parse_term ctxt t | - NONE => Syntax.parse_term ctxt p); - - (* type inference and contexts *) - val parm_types' = map (TypeInfer.paramify_vars o Logic.varifyT) parm_types; - val type_parms = fold Term.add_tvarsT parm_types' [] |> map (Logic.mk_type o TVar); - val arg = type_parms @ map2 TypeInfer.constrain parm_types' insts'; - val res = Syntax.check_terms ctxt arg; - val ctxt' = ctxt |> fold Variable.auto_fixes res; - - (* instantiation *) - val (type_parms'', res') = chop (length type_parms) res; - val insts'' = (parm_names ~~ res') |> map_filter - (fn (inst as (x, Free (y, _))) => if x = y then NONE else SOME inst | - inst => SOME inst); - val instT = Symtab.make (type_parm_names ~~ map Logic.dest_type type_parms''); - val inst = Symtab.make insts''; - in - (Element.inst_morphism thy (instT, inst) $> - Morphism.name_morphism (Name.qualified prfx), ctxt') - end; - - fun add_declarations loc morph ctxt = - let - (* locale data *) - val parms = loc |> NewLocale.params_of thy |> - map (fn (b, SOME T, mx) => ((Name.name_of b, T), mx)); - val (typ_decls, term_decls) = NewLocale.declarations_of thy loc; - - (* declarations from locale *) - val ctxt'' = ctxt |> - fold_rev (fn decl => Context.proof_map (decl morph)) typ_decls |> - fold_rev (fn decl => Context.proof_map (decl morph)) term_decls; - in - ctxt'' - end; - - val Expr [(loc1, (prfx1, insts1))] = expr'; - val ctxt0 = ProofContext.init thy; - val (parms, ctxt') = declare_parameters fixed ctxt0; - val (morph1, ctxt'') = rough_inst loc1 prfx1 insts1 ctxt'; - val ctxt'' = add_declarations loc1 morph1 ctxt'; - in ctxt0 end; - (*** Locale processing ***) @@ -346,14 +266,17 @@ (defs ~~ propps) |> map (fn ((b, _), [propp]) => (b, propp)) |> Defines | restore_elem (Notes notes, _) = Notes notes; -fun check_autofix_elems elems concl ctxt = +fun check_autofix insts elems concl ctxt = let - val termss = elems |> map extract_elem; - val all_terms' = (burrow o burrow_fst) (Syntax.check_terms ctxt) (concl @ flat termss); + val instss = map (snd o snd) insts |> (map o map) (fn t => (t, [])); + val elemss = elems |> map extract_elem; + val all_terms' = (burrow o burrow_fst) (Syntax.check_terms ctxt) (concl @ instss @ flat elemss); (* val (ctxt', all_props') = ProofContext.check_propp_schematic (ctxt, concl @ flat propss); *) - val (concl', terms') = chop (length concl) all_terms'; - val ctxt'' = (fold o fold) (fn (t, _) => Variable.auto_fixes t) terms' ctxt; - in (terms' |> unflat termss |> curry (op ~~) elems |> map restore_elem, concl', ctxt'') end; + val ctxt'' = (fold o fold) (fn (t, _) => Variable.auto_fixes t) all_terms' ctxt; + val (concl', mores') = chop (length concl) all_terms'; + val (insts', elems') = chop (length instss) mores'; + in (insts' |> (map o map) fst |> curry (op ~~) insts |> map (fn ((l, (p, _)), is) => (l, (p, is))), + elems' |> unflat elemss |> curry (op ~~) elems |> map restore_elem, concl', ctxt'') end; (** Prepare locale elements **) @@ -363,14 +286,12 @@ in ctxt |> ProofContext.add_fixes_i vars |> snd end | declare_elem prep_vars (Constrains csts) ctxt = ctxt |> prep_vars (map (fn (x, T) => (Name.binding x, SOME T, NoSyn)) csts) |> snd - | declare_elem _ (Assumes asms) ctxt = ctxt - | declare_elem _ (Defines defs) ctxt = ctxt + | declare_elem _ (Assumes _) ctxt = ctxt + | declare_elem _ (Defines _) ctxt = ctxt | declare_elem _ (Notes _) ctxt = ctxt; (** Finish locale elements, extract specification text **) -local - val norm_term = Envir.beta_norm oo Term.subst_atomic; fun abstract_thm thy eq = @@ -390,18 +311,20 @@ (Term.add_frees b' xs, (Free (y, T), b') :: env, th :: ths) end; -fun eval_text _ (Fixes _) text = text - | eval_text _ (Constrains _) text = text - | eval_text _ (Assumes asms) +fun eval_text _ _ (Fixes _) text = text + | eval_text _ _ (Constrains _) text = text + | eval_text _ is_ext (Assumes asms) (((exts, exts'), (ints, ints')), (xs, env, defs)) = let val ts = maps (map #1 o #2) asms; val ts' = map (norm_term env) ts; - val spec' = ((exts @ ts, exts' @ ts'), (ints, ints')); + val spec' = + if is_ext then ((exts @ ts, exts' @ ts'), (ints, ints')) + else ((exts, exts'), (ints @ ts, ints' @ ts')); in (spec', (fold Term.add_frees ts' xs, env, defs)) end - | eval_text ctxt (Defines defs) (spec, binds) = + | 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 _ _ (Notes _) text = text; fun closeup _ _ false elem = elem | closeup ctxt parms true elem = @@ -424,26 +347,44 @@ | e => e) end; -fun finish_ext_elem parms _ (Fixes fixes) = Fixes (map (fn (binding, _, mx) => +fun finish_primitive parms _ (Fixes fixes) = Fixes (map (fn (binding, _, mx) => let val x = Name.name_of binding in (binding, AList.lookup (op =) parms x, mx) end) fixes) - | finish_ext_elem _ _ (Constrains _) = Constrains [] - | finish_ext_elem _ close (Assumes asms) = close (Assumes asms) - | finish_ext_elem _ close (Defines defs) = close (Defines defs) - | finish_ext_elem _ _ (Notes facts) = Notes facts; + | finish_primitive _ _ (Constrains _) = Constrains [] + | finish_primitive _ close (Assumes asms) = close (Assumes asms) + | finish_primitive _ close (Defines defs) = close (Defines defs) + | finish_primitive _ _ (Notes facts) = Notes facts; + +fun finish_inst ctxt parms do_close (loc, (prfx, inst)) text = + let + val thy = ProofContext.theory_of ctxt; + val (parm_names, parm_types) = NewLocale.params_of thy loc |> + map (fn (b, SOME T, _) => (Name.name_of b, T)) |> split_list; + val (asm, defs) = NewLocale.specification_of thy loc; + val (morph, _) = inst_morph (parm_names, parm_types) (prfx, inst) ctxt; + 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 [(Attrib.no_binding, [(the asm', [])])]) + else I) |> + (if not (null defs) + then eval_text ctxt false (Defines (map (fn def => (Attrib.no_binding, (def, []))) defs')) + else I) +(* FIXME clone from new_locale.ML *) + in ((loc, morph), text') end; fun finish_elem ctxt parms do_close elem text = let - val elem' = finish_ext_elem parms (closeup ctxt parms do_close) elem; - val text' = eval_text ctxt elem' text; + val elem' = finish_primitive parms (closeup ctxt parms do_close) elem; + val text' = eval_text ctxt true elem' text; in (elem', text') end -in - -fun finish_elems ctxt parms do_close elems text = - fold_map (finish_elem ctxt parms do_close) elems text; - -end; +fun finish ctxt parms do_close insts elems text = + let + val (deps, text') = fold_map (finish_inst ctxt parms do_close) insts text; + val (elems', text'') = fold_map (finish_elem ctxt parms do_close) elems text'; + in (deps, elems', text'') end; local @@ -455,38 +396,59 @@ fun fold_prefixes f xs y = fold_suffixes (f o rev) (rev xs) y; *) -fun prep_elems parse_typ parse_prop prep_vars do_close context raw_elems raw_concl = +fun prep_elems parse_typ parse_prop parse_inst prep_vars + do_close context fixed raw_insts raw_elems raw_concl = let - fun prep_elem raw_elem (elems, ctxt) = + val thy = ProofContext.theory_of context; + + fun prep_inst (loc, (prfx, inst)) (i, ids, insts, ctxt) = + let + val (parm_names, parm_types) = NewLocale.params_of thy loc |> + map (fn (b, SOME T, _) => (Name.name_of b, T)) |> split_list; + val inst' = parse_inst parm_names inst ctxt; + val parm_types' = map (TypeInfer.paramify_vars o varify_indexT i) parm_types; + val inst'' = map2 TypeInfer.constrain parm_types' inst'; + val insts' = insts @ [(loc, (prfx, inst''))]; + val (insts'', _, _, ctxt') = check_autofix insts' [] [] ctxt; + val inst''' = insts'' |> List.last |> snd |> snd; + val (morph, _) = inst_morph (parm_names, parm_types) (prfx, inst''') ctxt; + val (ids', ctxt'') = NewLocale.activate_declarations loc morph thy ids ctxt; + in (i+1, ids', insts', ctxt'') end; + + fun prep_elem raw_elem (insts, elems, ctxt) = let val ctxt' = declare_elem prep_vars raw_elem ctxt; val elems' = elems @ [parse_elem parse_typ parse_prop ctxt' raw_elem]; (* FIXME term bindings *) - val (_, _, ctxt'') = check_autofix_elems elems' [] ctxt'; - in (elems', ctxt'') end; + val (_, _, _, ctxt'') = check_autofix insts elems' [] ctxt'; + in (insts, elems', ctxt') end; - fun prep_concl raw_concl (elems, ctxt) = + fun prep_concl raw_concl (insts, elems, ctxt) = let val concl = (map o map) (fn (t, ps) => (parse_prop ctxt t, map (parse_prop ctxt) ps)) raw_concl; - in check_autofix_elems elems concl ctxt end; + in check_autofix insts elems concl ctxt end; - val (elems, concl, ctxt) = fold prep_elem raw_elems ([], context) |> - prep_concl raw_concl; + val fors = prep_vars fixed context |> fst; + val ctxt = context |> ProofContext.add_fixes_i fors |> snd; + val (_, _, insts', ctxt') = fold prep_inst raw_insts (0, NewLocale.empty, [], ctxt); + val (_, elems'', ctxt'') = fold prep_elem raw_elems (insts', [], ctxt'); + val (insts, elems, concl, ctxt) = prep_concl raw_concl (insts', elems'', ctxt''); - (* Retrieve parameter types *) + (* Retrieve parameter types *) val xs = fold (fn Fixes fixes => (fn ps => ps @ map (Name.name_of o #1) fixes) | - _ => fn ps => ps) elems []; + _ => fn ps => ps) (Fixes fors :: elems) []; val (Ts, ctxt') = fold_map ProofContext.inferred_param xs ctxt; val parms = xs ~~ Ts; - val (elems', text) = finish_elems ctxt' parms do_close elems ((([], []), ([], [])), ([], [], [])); + val Fixes fors' = finish_primitive parms I (Fixes fors); + val (deps, elems', text) = finish ctxt' parms do_close insts elems ((([], []), ([], [])), ([], [], [])); (* text has the following structure: (((exts, exts'), (ints, ints')), (xs, env, defs)) where - exts: external assumptions (terms in external assumes elements) + exts: external assumptions (terms in assumes elements) exts': dito, normalised wrt. env - ints: internal assumptions (terms in internal assumes elements) + 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 @@ -502,12 +464,14 @@ - Facts unchanged *) - in ((parms, elems', concl), text) end + in ((parms, fors', deps, elems', concl), text) end in -fun read_elems x = prep_elems Syntax.parse_typ Syntax.parse_prop ProofContext.read_vars x; -fun cert_elems x = prep_elems (K I) (K I) ProofContext.cert_vars x; +fun read_elems x = prep_elems Syntax.parse_typ Syntax.parse_prop parse_inst + ProofContext.read_vars x; +fun cert_elems x = prep_elems (K I) (K I) make_inst + ProofContext.cert_vars x; end; @@ -521,35 +485,26 @@ let val thy = ProofContext.theory_of context; - val (expr, fixed) = parameters_of thy (apfst (prep_expr thy) imprt); + val (Expr expr, fixed) = parameters_of thy (apfst (prep_expr thy) imprt); val ctxt = context |> ProofContext.add_fixes fixed |> snd; + (* FIXME push inside prep_elems *) + val ((parms, fors, deps, elems, concl), (spec, (_, _, defs))) = + prep_elems do_close context fixed expr elements raw_concl; + (* FIXME activate deps *) + val ((elems', _), ctxt') = + Element.activate elems (ProofContext.set_stmt true ctxt); in - case expr of - Expr [] => let - val ((parms, elems, concl), (spec, (_, _, defs))) = prep_elems do_close - context elements raw_concl; - val ((elems', _), ctxt') = - Element.activate elems (ProofContext.set_stmt true ctxt); - in - (((ctxt', elems'), (parms, spec, defs)), concl) - end -(* - | Expr [(name, insts)] => let - val parms = parameters_of thy name |> map (fn (b, SOME T, _) => (Name.name_of b, T)); - val (morph, ctxt') = read_inst parms insts context; - in - - end -*) -end + (((fors, deps), (ctxt', elems'), (parms, spec, defs)), concl) + end in fun read_context imprt body ctxt = #1 (prep_context_statement intern read_elems true imprt body [] ctxt); +(* fun cert_context imprt body ctxt = #1 (prep_context_statement (K I) cert_elems true imprt body [] ctxt); - +*) end; @@ -700,7 +655,7 @@ end | defines_to_notes _ e defns = (e, defns); -fun gen_add_locale prep_ctxt +fun gen_add_locale prep_context bname predicate_name raw_imprt raw_body thy = let val thy_ctxt = ProofContext.init thy; @@ -708,28 +663,31 @@ val _ = NewLocale.test_locale thy name andalso error ("Duplicate definition of locale " ^ quote name); - val ((body_ctxt, body_elems), text as (parms, ((_, exts'), _), defs)) = - prep_ctxt raw_imprt raw_body thy_ctxt; - val ((statement, intro, axioms), _, thy') = + val ((fors, deps), (_, body_elems), text as (parms, ((_, exts'), _), defs)) = + prep_context raw_imprt raw_body thy_ctxt; + val ((a_statement, a_intro, a_axioms), (b_statement, b_intro, b_axioms), thy') = define_preds predicate_name text thy; val extraTs = fold Term.add_tfrees exts' [] \\ fold Term.add_tfreesT (map snd parms) []; val _ = if null extraTs then () else warning ("Additional type variable(s) in locale specification " ^ quote bname); - val params = body_elems |> - map_filter (fn Fixes fixes => SOME fixes | _ => NONE) |> flat; - + val satisfy = Element.satisfy_morphism b_axioms; + val params = fors @ + (body_elems |> map_filter (fn Fixes fixes => SOME fixes | _ => NONE) |> flat); val (body_elems', defns) = fold_map (defines_to_notes thy) body_elems []; val notes = body_elems' |> - (fn elems => fold_map assumes_to_notes elems (map Element.conclude_witness axioms)) |> - fst |> + (fn elems => fold_map assumes_to_notes elems (map Element.conclude_witness a_axioms)) |> + fst |> map (Element.morph_ctxt satisfy) |> map_filter (fn Notes notes => SOME notes | _ => NONE); + val deps' = map (fn (l, morph) => (l, morph $> satisfy)) deps; + val loc_ctxt = thy' |> - NewLocale.register_locale name (extraTs, params) (statement, defns) ([], []) - (map (fn n => (n, stamp ())) notes |> rev) [] |> + NewLocale.register_locale name (extraTs, params) + (if is_some b_statement then b_statement else a_statement, map prop_of defs) ([], []) + (map (fn n => (n, stamp ())) notes |> rev) (map (fn d => (d, stamp ())) deps' |> rev) |> NewLocale.init name in (name, loc_ctxt) end;