improved treatment of Element.Obtains via Expression.prepare_stmt;
authorwenzelm
Sun, 14 Jun 2015 23:22:08 +0200
changeset 60477 051b200f7578
parent 60476 05fd100e7971
child 60478 d1a9d098f870
improved treatment of Element.Obtains via Expression.prepare_stmt; discontinued pointless all_types ctxt: prep_var is always sequential;
NEWS
src/Pure/Isar/expression.ML
src/Pure/Isar/obtain.ML
src/Pure/Isar/specification.ML
--- a/NEWS	Sun Jun 14 20:10:21 2015 +0200
+++ b/NEWS	Sun Jun 14 23:22:08 2015 +0200
@@ -12,6 +12,9 @@
 * Command 'obtain' binds term abbreviations (via 'is' patterns) in the
 proof body as well, abstracted over relevant parameters.
 
+* Improved type-inference for theorem statement 'obtains': separate
+parameter scope for of each clause.
+
 * Term abbreviations via 'is' patterns also work for schematic
 statements: result is abstracted over unknowns.
 
--- a/src/Pure/Isar/expression.ML	Sun Jun 14 20:10:21 2015 +0200
+++ b/src/Pure/Isar/expression.ML	Sun Jun 14 23:22:08 2015 +0200
@@ -13,10 +13,10 @@
   type expression = (xstring * Position.T, string) expr * (binding * string option * mixfix) list
 
   (* Processing of context statements *)
-  val cert_statement: Element.context_i list -> (term * term list) list list ->
-    Proof.context -> (term * term list) list list * Proof.context
-  val read_statement: Element.context list -> (string * string list) list list ->
-    Proof.context -> (term * term list) list list * Proof.context
+  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) ->
@@ -217,13 +217,20 @@
     fact = I,
     attrib = I};
 
-fun parse_concl prep_term ctxt concl =
-  (map o map) (fn (t, ps) =>
-    (prep_term (Proof_Context.set_mode Proof_Context.mode_schematic ctxt) t,
-      map (prep_term (Proof_Context.set_mode Proof_Context.mode_pattern ctxt)) ps)) concl;
+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;
+      in map (fn (b, t) => ((b, []), [(t, [])])) obtains end);
 
 
-(** Simultaneous type inference: instantiations + elements + conclusion **)
+(** Simultaneous type inference: instantiations + elements + statement **)
 
 local
 
@@ -275,7 +282,7 @@
   let
     val inst_cs = map extract_inst insts;
     val elem_css = map extract_elem elems;
-    val concl_cs = (map o map) mk_propp concl;
+    val concl_cs = (map o map) mk_propp (map snd concl);
     (* Type inference *)
     val (inst_cs' :: css', ctxt') =
       (fold_burrow o fold_burrow) check (inst_cs :: elem_css @ [concl_cs]) ctxt;
@@ -283,7 +290,7 @@
   in
     ((map restore_inst (insts ~~ inst_cs'),
       map restore_elem (elems ~~ elem_css'),
-      concl_cs'), ctxt')
+      map fst concl ~~ concl_cs'), ctxt')
   end;
 
 end;
@@ -351,15 +358,15 @@
 end;
 
 
-(** Process full context statement: instantiations + elements + conclusion **)
+(** Process full context statement: instantiations + elements + statement **)
 
 (* Interleave incremental parsing and type inference over entire parsed stretch. *)
 
 local
 
 fun prep_full_context_statement
-    parse_typ parse_prop prep_var_elem prep_inst prep_var_inst prep_expr
-    {strict, do_close, fixed_frees} raw_import init_body raw_elems raw_concl ctxt1 =
+    parse_typ parse_prop prep_obtains prep_var_elem prep_inst prep_var_inst prep_expr
+    {strict, do_close, fixed_frees} raw_import init_body raw_elems raw_stmt ctxt1 =
   let
     val thy = Proof_Context.theory_of ctxt1;
 
@@ -393,8 +400,8 @@
     val ctxt2 = ctxt1 |> Proof_Context.add_fixes fors |> snd;
     val (_, insts', ctxt3) = fold prep_insts_cumulative raw_insts (0, [], ctxt2);
 
-    fun prep_concl elems ctxt =
-      check_autofix insts' elems (parse_concl parse_prop ctxt raw_concl) ctxt;
+    fun prep_stmt elems ctxt =
+      check_autofix insts' elems (prepare_stmt parse_prop prep_obtains ctxt raw_stmt) ctxt;
 
     val _ =
       if fixed_frees then ()
@@ -407,7 +414,7 @@
     val ((insts, elems', concl), ctxt4) = ctxt3
       |> init_body
       |> fold_map prep_elem raw_elems
-      |-> prep_concl;
+      |-> prep_stmt;
 
 
     (* parameters from expression and elements *)
@@ -426,29 +433,29 @@
 in
 
 fun cert_full_context_statement x =
-  prep_full_context_statement (K I) (K I) Proof_Context.cert_var
-  make_inst Proof_Context.cert_var (K I) x;
+  prep_full_context_statement (K I) (K I) Obtain.cert_obtains
+    Proof_Context.cert_var make_inst Proof_Context.cert_var (K I) x;
 
 fun cert_read_full_context_statement x =
-  prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Proof_Context.read_var
-  make_inst Proof_Context.cert_var (K I) x;
+  prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Obtain.parse_obtains
+    Proof_Context.read_var make_inst Proof_Context.cert_var (K I) x;
 
 fun read_full_context_statement x =
-  prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Proof_Context.read_var
-  parse_inst Proof_Context.read_var check_expr x;
+  prep_full_context_statement Syntax.parse_typ Syntax.parse_prop Obtain.parse_obtains
+    Proof_Context.read_var parse_inst Proof_Context.read_var check_expr x;
 
 end;
 
 
-(* Context statement: elements + conclusion *)
+(* Context statement: elements + statement *)
 
 local
 
-fun prep_statement prep activate raw_elems raw_concl context =
+fun prep_statement prep activate raw_elems raw_stmt context =
   let
     val ((_, _, elems, concl), _) =
       prep {strict = true, do_close = false, fixed_frees = true}
-        ([], []) I raw_elems raw_concl context;
+        ([], []) I raw_elems raw_stmt context;
     val (_, context') = context
       |> Proof_Context.set_stmt true
       |> fold_map activate elems;
@@ -473,7 +480,7 @@
   let
     val ((fixed, deps, elems, _), (parms, ctxt')) =
       prep {strict = false, do_close = true, fixed_frees = false}
-        raw_import init_body raw_elems [] context;
+        raw_import init_body raw_elems (Element.Shows []) context;
     (* Declare parameters and imported facts *)
     val context' = context |>
       fix_params fixed |>
@@ -509,7 +516,8 @@
     val thy = Proof_Context.theory_of context;
 
     val ((fixed, deps, _, _), _) =
-      prep {strict = true, do_close = true, fixed_frees = true} expression I [] [] context;
+      prep {strict = true, do_close = true, fixed_frees = true} expression I []
+        (Element.Shows []) context;
     (* proof obligations *)
     val propss = map (props_of thy) deps;
 
--- a/src/Pure/Isar/obtain.ML	Sun Jun 14 20:10:21 2015 +0200
+++ b/src/Pure/Isar/obtain.ML	Sun Jun 14 23:22:08 2015 +0200
@@ -6,11 +6,11 @@
 
 signature OBTAIN =
 sig
+  val obtain_thesis: Proof.context -> ((string * typ) * term) * Proof.context
   val obtains_attributes: ('typ, 'term) Element.obtain list -> attribute list
-  val parse_clause: Proof.context -> term ->
-    (binding * typ option * mixfix) list -> string list -> term
   val read_obtains: Proof.context -> term -> Element.obtains -> (binding * term) list
   val cert_obtains: Proof.context -> term -> Element.obtains_i -> (binding * term) list
+  val parse_obtains: Proof.context -> term -> Element.obtains -> (binding * term) list
   val consider: Element.obtains_i -> bool -> Proof.state -> Proof.state
   val consider_cmd: Element.obtains -> bool -> Proof.state -> Proof.state
   val obtain: binding -> (binding * typ option * mixfix) list ->
@@ -92,38 +92,38 @@
 
 local
 
-fun prepare_clause parse_prop ctxt thesis vars raw_props =
+val mk_all_external = Logic.all_constraint o Variable.default_type;
+fun mk_all_internal _ (y, z) t =
+  let val T = the (AList.lookup (op =) (Term.add_frees t []) z);
+  in Logic.all_const T $ Term.lambda_name (y, Free (z, T)) t end;
+
+fun prepare_clause prep_var parse_prop mk_all ctxt thesis raw_vars raw_props =
   let
-    val (xs', ctxt') = ctxt |> Proof_Context.add_fixes vars;
+    val ((xs', vars), ctxt') = ctxt
+      |> fold_map prep_var raw_vars
+      |-> (fn vars => Proof_Context.add_fixes vars ##>> pair vars);
     val xs = map (Variable.check_name o #1) vars;
   in
     Logic.list_implies (map (parse_prop ctxt') raw_props, thesis)
-    |> fold_rev (Logic.all_constraint (Variable.default_type ctxt')) (xs ~~ xs')
+    |> fold_rev (mk_all ctxt') (xs ~~ xs')
   end;
 
-fun prepare_obtains prep_var parse_prop ctxt thesis raw_obtains =
+fun prepare_obtains prep_clause check_terms
+    ctxt thesis (raw_obtains: ('typ, 'term) Element.obtain list) =
   let
-    val all_types =
-      fold_map prep_var (maps (fn (_, (vs, _)) => vs) raw_obtains)
-        (ctxt |> Context_Position.set_visible false)
-      |> #1 |> map_filter (fn (_, opt_T, _) => opt_T);
-    val types_ctxt = fold Variable.declare_typ all_types ctxt;
+    val clauses = raw_obtains
+      |> map (fn (_, (raw_vars, raw_props)) => prep_clause ctxt thesis raw_vars raw_props)
+      |> check_terms ctxt;
+  in map fst raw_obtains ~~ clauses end;
 
-    val clauses =
-      raw_obtains |> map (fn (_, (raw_vars, raw_props)) =>
-        let
-          val (vars, vars_ctxt) = fold_map prep_var raw_vars types_ctxt;
-          val clause = prepare_clause parse_prop vars_ctxt thesis vars raw_props;
-        in clause end)
-      |> Syntax.check_terms ctxt;
-  in map fst raw_obtains ~~ clauses end;
+val parse_clause = prepare_clause Proof_Context.read_var Syntax.parse_prop mk_all_external;
+val cert_clause = prepare_clause Proof_Context.cert_var (K I) mk_all_internal;
 
 in
 
-val parse_clause = prepare_clause Syntax.parse_prop;
-
-val read_obtains = prepare_obtains Proof_Context.read_var Syntax.parse_prop;
-val cert_obtains = prepare_obtains Proof_Context.cert_var (K I);
+val read_obtains = prepare_obtains parse_clause Syntax.check_terms;
+val cert_obtains = prepare_obtains cert_clause (K I);
+val parse_obtains = prepare_obtains parse_clause (K I);
 
 end;
 
--- a/src/Pure/Isar/specification.ML	Sun Jun 14 20:10:21 2015 +0200
+++ b/src/Pure/Isar/specification.ML	Sun Jun 14 23:22:08 2015 +0200
@@ -318,56 +318,30 @@
 
 local
 
-fun prep_statement prep_att prep_stmt elems concl ctxt =
-  (case concl of
-    Element.Shows shows =>
-      let
-        val (propp, elems_ctxt) = prep_stmt elems (map snd shows) ctxt;
-        val prems = Assumption.local_prems_of elems_ctxt ctxt;
-        val stmt = Attrib.map_specs (map prep_att) (map fst shows ~~ propp);
-        val goal_ctxt = (fold o fold) (Variable.auto_fixes o fst) propp elems_ctxt;
-      in (([], prems, stmt, NONE), goal_ctxt) end
-  | Element.Obtains obtains =>
-      let
-        val constraints = obtains |> map (fn (_, (vars, _)) =>
-          Element.Constrains
-            (vars |> map_filter (fn (x, SOME T, _) => SOME (Variable.check_name x, T) | _ => NONE)));
-
-        val raw_propp = obtains |> map (fn (_, (_, props)) => map (rpair []) props);
-        val (propp, elems_ctxt) = prep_stmt (elems @ constraints) raw_propp ctxt;
-
-        val thesis = Object_Logic.fixed_judgment ctxt Auto_Bind.thesisN;
+fun prep_statement prep_att prep_stmt raw_elems raw_stmt ctxt =
+  let
+    val (stmt, elems_ctxt) = prep_stmt raw_elems raw_stmt ctxt;
+    val prems = Assumption.local_prems_of elems_ctxt ctxt;
+    val stmt_ctxt = fold (fold (Variable.auto_fixes o fst) o snd) stmt elems_ctxt;
+  in
+    (case raw_stmt of
+      Element.Shows _ =>
+        let val stmt' = Attrib.map_specs (map prep_att) stmt
+        in (([], prems, stmt', NONE), stmt_ctxt) end
+    | Element.Obtains raw_obtains =>
+        let
+          val asms_ctxt = stmt_ctxt
+            |> fold (fn ((name, _), asm) =>
+                snd o Proof_Context.add_assms Assumption.assume_export
+                  [((name, [Context_Rules.intro_query NONE]), asm)]) stmt;
+          val that = Assumption.local_prems_of asms_ctxt stmt_ctxt;
+          val ([(_, that')], that_ctxt) = asms_ctxt
+            |> Proof_Context.note_thmss "" [((Binding.name Auto_Bind.thatN, []), [(that, [])])];
 
-        fun assume_case ((name, (vars, _)), asms) ctxt' =
-          let
-            val bs = map (fn (b, _, _) => b) vars;
-            val xs = map Variable.check_name bs;
-            val props = map fst asms;
-            val (params, _) = ctxt'
-              |> fold Variable.declare_term props
-              |> fold_map Proof_Context.inferred_param xs
-              |>> map Free;
-            val asm = fold_rev Logic.all params (Logic.list_implies (props, thesis));
-            val _ = ctxt' |> Proof_Context.add_fixes (map (fn b => (b, NONE, NoSyn)) bs);
-          in
-            ctxt'
-            |> Variable.auto_fixes asm
-            |> Proof_Context.add_assms Assumption.assume_export
-              [((name, [Context_Rules.intro_query NONE]), [(asm, [])])]
-            |>> (fn [(_, [th])] => th)
-          end;
-
-        val more_atts = map (Attrib.internal o K) (Obtain.obtains_attributes obtains);
-        val prems = Assumption.local_prems_of elems_ctxt ctxt;
-        val stmt = [((Binding.empty, []), [(thesis, [])])];
-
-        val (facts, goal_ctxt) = elems_ctxt
-          |> (snd o Proof_Context.add_fixes [(Binding.name Auto_Bind.thesisN, NONE, NoSyn)])
-          |> fold_map assume_case (obtains ~~ propp)
-          |-> (fn ths =>
-            Proof_Context.note_thmss "" [((Binding.name Auto_Bind.thatN, []), [(ths, [])])] #>
-            #2 #> pair ths);
-      in ((more_atts, prems, stmt, SOME facts), goal_ctxt) end);
+          val more_atts = map (Attrib.internal o K) (Obtain.obtains_attributes raw_obtains);
+          val stmt' = [((Binding.empty, []), [(#2 (#1 (Obtain.obtain_thesis ctxt)), [])])];
+        in ((more_atts, prems, stmt', SOME that'), that_ctxt) end)
+  end;
 
 fun gen_theorem schematic bundle_includes prep_att prep_stmt
     kind before_qed after_qed (name, raw_atts) raw_includes raw_elems raw_concl int lthy =