src/Pure/drule.ML
changeset 60794 f21f70d24844
parent 60786 659117cc2963
child 60795 c24fa03f4c71
--- a/src/Pure/drule.ML	Sun Jul 26 22:26:11 2015 +0200
+++ b/src/Pure/drule.ML	Mon Jul 27 00:17:18 2015 +0200
@@ -22,6 +22,7 @@
   val implies_intr_list: cterm list -> thm -> thm
   val instantiate_normalize: ((indexname * sort) * ctyp) list * ((indexname * typ) * cterm) list ->
     thm -> thm
+  val infer_instantiate_vars: Proof.context -> ((indexname * typ) * cterm) list -> thm -> thm
   val infer_instantiate: Proof.context -> (indexname * cterm) list -> thm -> thm
   val cterm_instantiate: (cterm * cterm) list -> thm -> thm
   val instantiate': ctyp option list -> cterm option list -> thm -> thm
@@ -742,55 +743,58 @@
   Thm.adjust_maxidx_thm ~1 (Thm.instantiate instpair th COMP_INCR asm_rl);
 
 (*instantiation with type-inference for variables*)
+fun infer_instantiate_vars _ [] th = th
+  | infer_instantiate_vars ctxt args th =
+      let
+        val thy = Proof_Context.theory_of ctxt;
+
+        fun infer ((xi, T), cu) (tyenv, maxidx) =
+          let
+            val U = Thm.typ_of_cterm cu;
+            val maxidx' = maxidx
+              |> Integer.max (#2 xi)
+              |> Term.maxidx_typ T
+              |> Integer.max (Thm.maxidx_of_cterm cu);
+            val (tyenv', maxidx'') = Sign.typ_unify thy (T, U) (tyenv, maxidx')
+              handle Type.TUNIFY =>
+                let
+                  val t = Var (xi, T);
+                  val u = Thm.term_of cu;
+                in
+                  raise THM ("infer_instantiate: type " ^
+                    Syntax.string_of_typ ctxt (Envir.norm_type tyenv T) ^ " of variable " ^
+                    Syntax.string_of_term ctxt (Term.map_types (Envir.norm_type tyenv) t) ^
+                    "\ncannot be unified with type " ^
+                    Syntax.string_of_typ ctxt (Envir.norm_type tyenv U) ^ " of term " ^
+                    Syntax.string_of_term ctxt (Term.map_types (Envir.norm_type tyenv) u),
+                    0, [th])
+                end;
+          in (tyenv', maxidx'') end;
+
+        val (tyenv, _) = fold infer args (Vartab.empty, 0);
+        val instT =
+          Vartab.fold (fn (xi, (S, T)) =>
+            cons ((xi, S), Thm.ctyp_of ctxt (Envir.norm_type tyenv T))) tyenv [];
+        val inst = args |> map (fn ((xi, T), cu) =>
+          ((xi, Envir.norm_type tyenv T),
+            Thm.instantiate_cterm (instT, []) (Thm.transfer_cterm thy cu)));
+      in instantiate_normalize (instT, inst) th end
+      handle CTERM (msg, _) => raise THM (msg, 0, [th])
+        | TERM (msg, _) => raise THM (msg, 0, [th])
+        | TYPE (msg, _, _) => raise THM (msg, 0, [th]);
+
 fun infer_instantiate _ [] th = th
   | infer_instantiate ctxt args th =
       let
-        val thy = Proof_Context.theory_of ctxt;
-
         val vars = Term.add_vars (Thm.full_prop_of th) [];
         val dups = duplicates (eq_fst op =) vars;
         val _ = null dups orelse
           raise THM ("infer_instantiate: inconsistent types for variables " ^
             commas_quote (map (Syntax.string_of_term (Config.put show_types true ctxt) o Var) dups),
             0, [th]);
-
-        fun infer (xi, cu) (inst, tyenv, maxidx) =
-          (case AList.lookup (op =) vars xi of
-            NONE => (inst, tyenv, maxidx)
-          | SOME T =>
-              let
-                val U = Thm.typ_of_cterm cu;
-                val maxidx' = maxidx
-                  |> Integer.max (#2 xi)
-                  |> Term.maxidx_typ T
-                  |> Integer.max (Thm.maxidx_of_cterm cu);
-                val (tyenv', maxidx'') = Sign.typ_unify thy (T, U) (tyenv, maxidx')
-                  handle Type.TUNIFY =>
-                    let
-                      val t = Var (xi, T);
-                      val u = Thm.term_of cu;
-                    in
-                      raise THM ("infer_instantiate: type " ^
-                        Syntax.string_of_typ ctxt (Envir.norm_type tyenv T) ^ " of variable " ^
-                        Syntax.string_of_term ctxt (Term.map_types (Envir.norm_type tyenv) t) ^
-                        "\ncannot be unified with type " ^
-                        Syntax.string_of_typ ctxt (Envir.norm_type tyenv U) ^ " of term " ^
-                        Syntax.string_of_term ctxt (Term.map_types (Envir.norm_type tyenv) u),
-                        0, [th])
-                    end;
-              in (((xi, T), cu) :: inst, tyenv', maxidx'') end);
-
-        val (inst0, tyenv, _) = fold infer args ([], Vartab.empty, 0);
-        val instT =
-          Vartab.fold (fn (xi, (S, T)) =>
-            cons ((xi, S), Thm.ctyp_of ctxt (Envir.norm_type tyenv T))) tyenv [];
-        val inst = inst0 |> map (fn ((xi, T), cu) =>
-          ((xi, Envir.norm_type tyenv T),
-            Thm.instantiate_cterm (instT, []) (Thm.transfer_cterm thy cu)));
-      in instantiate_normalize (instT, inst) th end
-      handle CTERM (msg, _) => raise THM (msg, 0, [th])
-        | TERM (msg, _) => raise THM (msg, 0, [th])
-        | TYPE (msg, _, _) => raise THM (msg, 0, [th]);
+        val args' = args |> map_filter (fn (xi, cu) =>
+          AList.lookup (op =) vars xi |> Option.map (fn T => ((xi, T), cu)));
+      in infer_instantiate_vars ctxt args' th end;
 
 (*Left-to-right replacements: tpairs = [..., (vi, ti), ...].
   Instantiates distinct Vars by terms, inferring type instantiations.*)
@@ -848,11 +852,11 @@
 
 fun infer_instantiate' ctxt args th =
   let
-    val vars = rev (Term.add_var_names (Thm.full_prop_of th) []);
+    val vars = rev (Term.add_vars (Thm.full_prop_of th) []);
     val args' = zip_options vars args
       handle ListPair.UnequalLengths =>
         raise THM ("infer_instantiate': more instantiations than variables in thm", 0, [th]);
-  in infer_instantiate ctxt args' th end;
+  in infer_instantiate_vars ctxt args' th end;