support for structure statements in 'assume', 'presume';
authorwenzelm
Fri, 13 Nov 2015 11:41:11 +0100
changeset 61654 4a28eec739e9
parent 61653 71da80a379c6
child 61655 f217bbe4e93e
support for structure statements in 'assume', 'presume';
src/Pure/Isar/isar_syn.ML
src/Pure/Isar/obtain.ML
src/Pure/Isar/parse_spec.ML
src/Pure/Isar/proof.ML
src/Pure/logic.ML
--- a/src/Pure/Isar/isar_syn.ML	Thu Nov 12 11:30:56 2015 +0100
+++ b/src/Pure/Isar/isar_syn.ML	Fri Nov 13 11:41:11 2015 +0100
@@ -488,6 +488,15 @@
 
 (* statements *)
 
+val structured_statement =
+  Parse_Spec.statement -- Parse_Spec.cond_statement -- Parse.for_fixes
+    >> (fn ((shows, (strict, assumes)), fixes) => (strict, fixes, assumes, shows));
+
+val structured_statement' =
+  Parse_Spec.statement -- Parse_Spec.if_statement' -- Parse.for_fixes
+    >> (fn ((shows, assumes), fixes) => (fixes, assumes, shows));
+
+
 fun theorem spec schematic descr =
   Outer_Syntax.local_theory_to_proof' spec
     ("state " ^ descr)
@@ -506,10 +515,6 @@
 val _ = theorem @{command_keyword schematic_goal} true "schematic goal";
 
 
-val structured_statement =
-  Parse_Spec.statement -- Parse_Spec.cond_statement -- Parse.for_fixes
-    >> (fn ((shows, (strict, assumes)), fixes) => (strict, fixes, assumes, shows));
-
 val _ =
   Outer_Syntax.command @{command_keyword have} "state local goal"
     (structured_statement >> (fn (a, b, c, d) =>
@@ -572,11 +577,11 @@
 
 val _ =
   Outer_Syntax.command @{command_keyword assume} "assume propositions"
-    (Parse_Spec.statement >> (Toplevel.proof o Proof.assume_cmd));
+    (structured_statement' >> (fn (a, b, c) => Toplevel.proof (Proof.assume_cmd a b c)));
 
 val _ =
   Outer_Syntax.command @{command_keyword presume} "assume propositions, to be established later"
-    (Parse_Spec.statement >> (Toplevel.proof o Proof.presume_cmd));
+    (structured_statement' >> (fn (a, b, c) => Toplevel.proof (Proof.presume_cmd a b c)));
 
 val _ =
   Outer_Syntax.command @{command_keyword def} "local definition (non-polymorphic)"
--- a/src/Pure/Isar/obtain.ML	Thu Nov 12 11:30:56 2015 +0100
+++ b/src/Pure/Isar/obtain.ML	Fri Nov 13 11:41:11 2015 +0100
@@ -229,7 +229,7 @@
         state'
         |> Proof.fix vars
         |> Proof.map_context declare_asms
-        |> Proof.assm (obtain_export params_ctxt rule cparams) asms
+        |> Proof.assm (obtain_export params_ctxt rule cparams) [] [] asms
       end;
   in
     state
@@ -384,7 +384,7 @@
         |> Proof.fix (map (fn ((x, T), mx) => (Binding.name x, SOME T, mx)) parms)
         |> `Proof.context_of |-> (fn fix_ctxt => Proof.assm
           (obtain_export fix_ctxt rule (map (Thm.cterm_of ctxt) ts))
-            [(Thm.empty_binding, asms)])
+            [] [] [(Thm.empty_binding, asms)])
         |> Proof.map_context (fold Variable.unbind_term Auto_Bind.no_facts)
       end;
 
--- a/src/Pure/Isar/parse_spec.ML	Thu Nov 12 11:30:56 2015 +0100
+++ b/src/Pure/Isar/parse_spec.ML	Fri Nov 13 11:41:11 2015 +0100
@@ -23,6 +23,8 @@
   val locale_keyword: string parser
   val locale_expression: Expression.expression parser
   val context_element: Element.context parser
+  val statement': (string * string list) list list parser
+  val if_statement': (string * string list) list list parser
   val statement: (Attrib.binding * (string * string list) list) list parser
   val if_statement: (Attrib.binding * (string * string list) list) list parser
   val cond_statement: (bool * (Attrib.binding * (string * string list) list) list) parser
@@ -132,6 +134,9 @@
 
 (* statements *)
 
+val statement' = Parse.and_list1 (Scan.repeat1 Parse.propp);
+val if_statement' = Scan.optional (Parse.$$$ "if" |-- Parse.!!! statement') [];
+
 val statement = Parse.and_list1 (opt_thm_name ":" -- Scan.repeat1 Parse.propp);
 val if_statement = Scan.optional (Parse.$$$ "if" |-- Parse.!!! statement) [];
 
--- a/src/Pure/Isar/proof.ML	Thu Nov 12 11:30:56 2015 +0100
+++ b/src/Pure/Isar/proof.ML	Fri Nov 13 11:41:11 2015 +0100
@@ -49,14 +49,24 @@
   val write_cmd: Syntax.mode -> (string * mixfix) list -> state -> state
   val fix: (binding * typ option * mixfix) list -> state -> state
   val fix_cmd: (binding * string option * mixfix) list -> state -> state
-  val assm: Assumption.export ->
-    (Thm.binding * (term * term list) list) list -> state -> state
-  val assm_cmd: Assumption.export ->
-    (Attrib.binding * (string * string list) list) list -> state -> state
-  val assume: (Thm.binding * (term * term list) list) list -> state -> state
-  val assume_cmd: (Attrib.binding * (string * string list) list) list -> state -> state
-  val presume: (Thm.binding * (term * term list) list) list -> state -> state
-  val presume_cmd: (Attrib.binding * (string * string list) list) list -> state -> state
+  val assm: Assumption.export -> (binding * typ option * mixfix) list ->
+    (term * term list) list list -> (Thm.binding * (term * term list) list) list ->
+    state -> state
+  val assm_cmd: Assumption.export -> (binding * string option * mixfix) list ->
+    (string * string list) list list -> (Attrib.binding * (string * string list) list) list ->
+    state -> state
+  val assume: (binding * typ option * mixfix) list ->
+    (term * term list) list list -> (Thm.binding * (term * term list) list) list ->
+    state -> state
+  val assume_cmd: (binding * string option * mixfix) list ->
+    (string * string list) list list -> (Attrib.binding * (string * string list) list) list ->
+    state -> state
+  val presume: (binding * typ option * mixfix) list ->
+    (term * term list) list list -> (Thm.binding * (term * term list) list) list ->
+    state -> state
+  val presume_cmd: (binding * string option * mixfix) list ->
+    (string * string list) list list -> (Attrib.binding * (string * string list) list) list ->
+    state -> state
   val def: (Thm.binding * ((binding * mixfix) * (term * term list))) list -> state -> state
   val def_cmd: (Attrib.binding * ((binding * mixfix) * (string * string list))) list -> state -> state
   val chain: state -> state
@@ -618,22 +628,86 @@
 end;
 
 
-(* assume etc. *)
+(* structured clause *)
+
+fun export_binds ctxt' ctxt binds =
+  let
+    val rhss =
+      map (the_list o snd) binds
+      |> burrow (Variable.export_terms ctxt' ctxt)
+      |> map (try the_single);
+  in map fst binds ~~ rhss end;
+
+fun prep_clause prep_var prep_propp raw_fixes raw_assumes raw_shows ctxt =
+  let
+    (*fixed variables*)
+    val ((xs', vars), fix_ctxt) = ctxt
+      |> fold_map prep_var raw_fixes
+      |-> (fn vars => Proof_Context.add_fixes vars ##>> pair vars);
+
+    (*propositions with term bindings*)
+    val (all_propss, binds) = prep_propp fix_ctxt (raw_assumes @ raw_shows);
+    val (assumes_propss, shows_propss) = chop (length raw_assumes) all_propss;
+
+    (*params*)
+    val (ps, params_ctxt) = fix_ctxt
+      |> (fold o fold) Variable.declare_term all_propss
+      |> fold Variable.bind_term binds
+      |> fold_map Proof_Context.inferred_param xs';
+    val xs = map (Variable.check_name o #1) vars;
+    val params = xs ~~ map Free ps;
+
+    val _ = Variable.warn_extra_tfrees fix_ctxt params_ctxt;
+
+    (*result term bindings*)
+    val shows_props = flat shows_propss;
+    val binds' =
+      (case try List.last shows_props of
+        NONE => []
+      | SOME prop => map (apsnd (SOME o Auto_Bind.abs_params prop)) binds);
+    val result_binds =
+      (Auto_Bind.facts params_ctxt shows_props @ binds')
+      |> (map o apsnd o Option.map) (fold_rev Term.dependent_lambda_name params)
+      |> export_binds params_ctxt ctxt;
+  in ((params, assumes_propss, shows_propss, result_binds), params_ctxt) end;
+
+
+(* assume *)
 
 local
 
-fun gen_assume asm prep_att exp args state =
-  state
-  |> assert_forward
-  |> map_context_result (asm exp (Attrib.map_specs (map (prep_att (context_of state))) args))
-  |> these_factss [] |> #2;
+fun gen_assume prep_var prep_propp prep_att export raw_fixes raw_prems raw_concls state =
+  let
+    val ctxt = context_of state;
+
+    val bindings = map (apsnd (map (prep_att ctxt)) o fst) raw_concls;
+    val (params, prems_propss, concl_propss, result_binds) =
+      #1 (prep_clause prep_var prep_propp raw_fixes raw_prems (map snd raw_concls) ctxt);
+
+    fun close prop =
+      fold_rev Logic.all_name params (Logic.list_implies (flat prems_propss, prop));
+    val propss = (map o map) close concl_propss;
+  in
+    state
+    |> assert_forward
+    |> map_context_result (fn ctxt =>
+      ctxt
+      |> (fold o fold) Variable.declare_term propss
+      |> fold Variable.maybe_bind_term result_binds
+      |> fold_burrow (Assumption.add_assms export o map (Thm.cterm_of ctxt)) propss
+      |-> (fn premss =>
+        Proof_Context.note_thmss "" (bindings ~~ (map o map) (fn th => ([th], [])) premss)))
+    |> these_factss [] |> #2
+  end;
 
 in
 
-val assm = gen_assume Proof_Context.add_assms (K I);
-val assm_cmd = gen_assume Proof_Context.add_assms_cmd Attrib.attribute_cmd;
+val assm = gen_assume Proof_Context.cert_var Proof_Context.cert_propp (K I);
+val assm_cmd = gen_assume Proof_Context.read_var Proof_Context.read_propp Attrib.attribute_cmd;
+
 val assume = assm Assumption.assume_export;
 val assume_cmd = assm_cmd Assumption.assume_export;
+
 val presume = assm Assumption.presume_export;
 val presume_cmd = assm_cmd Assumption.presume_export;
 
@@ -788,7 +862,7 @@
       asms |> map (fn (a, ts) => ((Binding.qualified true a binding, []), map (rpair []) ts));
   in
     state'
-    |> assume assumptions
+    |> assume [] [] assumptions
     |> map_context (fold Variable.unbind_term Auto_Bind.no_facts)
     |> `the_facts |-> (fn thms => note_thmss [((binding, atts), [(thms, [])])])
   end;
@@ -982,18 +1056,6 @@
 
 (* local goals *)
 
-local
-
-fun export_binds ctxt' ctxt binds =
-  let
-    val rhss =
-      map (the_list o snd) binds
-      |> burrow (Variable.export_terms ctxt' ctxt)
-      |> map (try the_single);
-  in map fst binds ~~ rhss end;
-
-in
-
 fun local_goal print_results prep_att prep_propp prep_var strict_asm
     kind before_qed after_qed raw_fixes raw_assumes raw_shows state =
   let
@@ -1002,57 +1064,26 @@
     val add_assumes =
       Assumption.add_assms
         (if strict_asm then Assumption.assume_export else Assumption.presume_export);
+
     val (assumes_bindings, shows_bindings) =
       apply2 (map (apsnd (map (prep_att ctxt)) o fst)) (raw_assumes, raw_shows);
-    val (assumes_propp, shows_propp) = apply2 (map snd) (raw_assumes, raw_shows);
 
-    val (goal_ctxt, goal_propss, result_binds, that_fact) =
-      let
-        (*fixed variables*)
-        val ((xs', vars), fix_ctxt) = ctxt
-          |> fold_map prep_var raw_fixes
-          |-> (fn vars => Proof_Context.add_fixes vars ##>> pair vars);
-
-        (*propositions with term bindings*)
-        val (all_propss, binds) = prep_propp fix_ctxt (assumes_propp @ shows_propp);
-        val (assumes_propss, shows_propss) = chop (length assumes_propp) all_propss;
-
-        (*params*)
-        val (ps, params_ctxt) = fix_ctxt
-          |> (fold o fold) Variable.declare_term all_propss
-          |> fold Variable.bind_term binds
-          |> fold_map Proof_Context.inferred_param xs';
-        val xs = map (Variable.check_name o #1) vars;
-        val params = xs ~~ map Free ps;
+    val ((params, assumes_propss, shows_propss, result_binds), params_ctxt) = ctxt
+      |> prep_clause prep_var prep_propp raw_fixes (map snd raw_assumes) (map snd raw_shows);
 
-        (*prems*)
-        val (that_fact, goal_ctxt) = params_ctxt
-          |> fold_burrow add_assumes ((map o map) (Thm.cterm_of params_ctxt) assumes_propss)
-          |> (fn (premss, ctxt') =>
-              let
-                val prems = Assumption.local_prems_of ctxt' ctxt;
-                val ctxt'' =
-                  ctxt'
-                  |> not (null assumes_propss) ?
-                    (snd o Proof_Context.note_thmss ""
-                      [((Binding.name Auto_Bind.thatN, []), [(prems, [])])])
-                  |> (snd o Proof_Context.note_thmss ""
-                      (assumes_bindings ~~ map (map (fn th => ([th], []))) premss))
-              in (prems, ctxt'') end);
-
-        val _ = Variable.warn_extra_tfrees fix_ctxt goal_ctxt;
-
-        (*result term bindings*)
-        val shows_props = flat shows_propss;
-        val binds' =
-          (case try List.last shows_props of
-            NONE => []
-          | SOME prop => map (apsnd (SOME o Auto_Bind.abs_params prop)) binds);
-        val result_binds =
-          (Auto_Bind.facts goal_ctxt shows_props @ binds')
-          |> (map o apsnd o Option.map) (fold_rev Term.dependent_lambda_name params)
-          |> export_binds goal_ctxt ctxt;
-      in (goal_ctxt, shows_propss, result_binds, that_fact) end;
+    val (that_fact, goal_ctxt) = params_ctxt
+      |> fold_burrow add_assumes ((map o map) (Thm.cterm_of params_ctxt) assumes_propss)
+      |> (fn (premss, ctxt') =>
+          let
+            val prems = Assumption.local_prems_of ctxt' ctxt;
+            val ctxt'' =
+              ctxt'
+              |> not (null assumes_propss) ?
+                (snd o Proof_Context.note_thmss ""
+                  [((Binding.name Auto_Bind.thatN, []), [(prems, [])])])
+              |> (snd o Proof_Context.note_thmss ""
+                  (assumes_bindings ~~ map (map (fn th => ([th], []))) premss))
+          in (prems, ctxt'') end);
 
     fun after_qed' (result_ctxt, results) state' = state'
       |> local_results (shows_bindings ~~ burrow (Proof_Context.export result_ctxt ctxt) results)
@@ -1060,12 +1091,10 @@
       |> after_qed (result_ctxt, results);
   in
     state
-    |> generic_goal kind before_qed (after_qed', K I) goal_ctxt goal_propss result_binds
+    |> generic_goal kind before_qed (after_qed', K I) goal_ctxt shows_propss result_binds
     |> pair that_fact
   end;
 
-end;
-
 fun local_qeds arg =
   end_proof false arg
   #> Seq.map_result (generic_qed #-> (fn ((after_qed, _), results) => after_qed results));
--- a/src/Pure/logic.ML	Thu Nov 12 11:30:56 2015 +0100
+++ b/src/Pure/logic.ML	Fri Nov 13 11:41:11 2015 +0100
@@ -9,6 +9,7 @@
 sig
   val all_const: typ -> term
   val all: term -> term -> term
+  val all_name: string * term -> term -> term
   val is_all: term -> bool
   val dest_all: term -> (string * typ) * term
   val list_all: (string * typ) list * term -> term
@@ -98,6 +99,7 @@
 fun all_const T = Const ("Pure.all", (T --> propT) --> propT);
 
 fun all v t = all_const (Term.fastype_of v) $ lambda v t;
+fun all_name (x, v) t = all_const (Term.fastype_of v) $ Term.lambda_name (x, v) t;
 
 fun is_all (Const ("Pure.all", _) $ Abs _) = true
   | is_all _ = false;