eta-expansion now only to common maximum number of arguments
authorhaftmann
Thu, 04 Jan 2007 14:01:39 +0100
changeset 21989 0315ecfd3d5d
parent 21988 e83f3b0988e6
child 21990 d382f901304c
eta-expansion now only to common maximum number of arguments
src/Pure/Tools/codegen_funcgr.ML
--- a/src/Pure/Tools/codegen_funcgr.ML	Thu Jan 04 14:01:38 2007 +0100
+++ b/src/Pure/Tools/codegen_funcgr.ML	Thu Jan 04 14:01:39 2007 +0100
@@ -15,7 +15,8 @@
   val typ: T -> CodegenConsts.const -> typ
   val deps: T -> CodegenConsts.const list -> CodegenConsts.const list list
   val all: T -> CodegenConsts.const list
-  val norm_vars: theory -> thm list -> thm list
+  val norm_varnames: theory -> thm list -> thm list
+  val expand_eta: theory -> int -> thm -> thm
   val print_codethms: theory -> CodegenConsts.const list -> unit
   structure Constgraph : GRAPH
 end;
@@ -50,24 +51,44 @@
 
 (** theorem purification **)
 
-fun abs_norm thy thm =
+fun expand_eta thy k thm =
   let
-    fun eta_expand thm =
-      let
-        val lhs = (fst o Logic.dest_equals o Drule.plain_prop_of) thm;
-        val tys = (fst o strip_type o fastype_of) lhs;
-        val ctxt = Name.make_context (map (fst o fst) (Term.add_vars lhs []));
-        val vs_ct = map (fn (v, ty) => cterm_of thy (Var ((v, 0), ty)))
-          (Name.names ctxt "a" tys);
-      in
-        fold (fn ct => fn thm => Thm.combination thm (Thm.reflexive ct)) vs_ct thm
-      end;
+    val (lhs, rhs) = (Logic.dest_equals o Drule.plain_prop_of) thm;
+    val (head, args) = strip_comb lhs;
+    val l = Int.max (0, k - length args);
+    val used = Name.make_context (map (fst o fst) (Term.add_vars lhs []));
+    fun get_name _ 0 used = ([], used)
+      | get_name (Abs (v, ty, t)) k used =
+          used
+          |> Name.variants [CodegenNames.purify_var v]
+          ||>> get_name t (k - 1)
+          |>> (fn ([v'], vs') => (v', ty) :: vs')
+      | get_name t k used = 
+          let
+            val (tys, _) = (strip_type o fastype_of) t
+          in case tys
+           of [] => raise TERM ("expand_eta", [t])
+            | ty :: _ =>
+                used
+                |> Name.variants [""]
+                |-> (fn [v] => get_name (t $ Var ((v, 0), ty)) (k - 1)
+                #>> (fn vs' => (v, ty) :: vs'))
+          end;
+    val (vs, _) = get_name rhs l used;
+    val vs_refl = map (fn (v, ty) => Thm.reflexive (Thm.cterm_of thy (Var ((v, 0), ty)))) vs;
   in
-    thm
-    |> eta_expand
-    |> Drule.fconv_rule Drule.beta_eta_conversion
+    fold (fn refl => fn thm => Thm.combination thm refl) vs_refl thm
   end;
 
+fun norm_args thy thms =
+  let
+    val num_args_of = length o snd o strip_comb o fst o Logic.dest_equals;
+    val k = fold (curry Int.max o num_args_of o Drule.plain_prop_of) thms 0;
+  in
+    thms
+    |> map (expand_eta thy k)
+    |> map (Drule.fconv_rule Drule.beta_eta_conversion)
+  end;
 
 fun canonical_tvars thy thm =
   let
@@ -105,7 +126,7 @@
     val (_, inst) = fold mk_inst (vars_subst_for thm) (maxidx + 1, []);
   in Thm.instantiate ([], inst) thm end;
 
-fun norm_vars thy thms =
+fun norm_varnames thy thms =
   let
     fun burrow_thms f [] = []
       | burrow_thms f thms =
@@ -115,7 +136,7 @@
           |> Conjunction.elim_list;
   in
     thms
-    |> map (abs_norm thy)
+    |> norm_args thy
     |> burrow_thms (canonical_tvars thy)
     |> map (canonical_vars thy)
     |> map Drule.zero_var_indexes
@@ -219,7 +240,7 @@
     |> Constgraph.new_node (c, [])
     |> pair (SOME c)
   else let
-    val thms = norm_vars thy (CodegenData.these_funcs thy c);
+    val thms = norm_varnames thy (CodegenData.these_funcs thy c);
     val rhs = rhs_of thy (c, thms);
   in
     auxgr
@@ -274,17 +295,17 @@
               end;
             val instmap = map mk_inst tvars;
             val (thms' as thm' :: _) = map (Drule.zero_var_indexes o Thm.instantiate (instmap, [])) thms;
-            val (ty, ty') = pairself (CodegenData.typ_func thy) (thm, thm');
-            val _ = if fst c = ""
-              orelse (is_none o AxClass.class_of_param thy o fst) c andalso
-                Sign.typ_equiv thy (Type.strip_sorts ty, Type.strip_sorts ty')
-              orelse Sign.typ_equiv thy (ty, ty')
-              then ()
-              else raise INVALID ([], "illegal function type instantiation:\n" ^ Sign.string_of_typ thy (CodegenData.typ_func thy thm)
-                ^ "\nto " ^ Sign.string_of_typ thy (CodegenData.typ_func thy thm')
-                ^ ",\nfor constant " ^ CodegenConsts.string_of_const thy c
-                ^ "\nin function theorems\n"
-                ^ (cat_lines o map string_of_thm) thms)
+            val _ = if fst c = "" then ()
+              else case pairself (CodegenData.typ_func thy) (thm, thm')
+               of (ty, ty') => if (is_none o AxClass.class_of_param thy o fst) c
+                  andalso Sign.typ_equiv thy (Type.strip_sorts ty, Type.strip_sorts ty')
+                  orelse Sign.typ_equiv thy (ty, ty')
+                  then ()
+                  else raise INVALID ([], "illegal function type instantiation:\n" ^ Sign.string_of_typ thy (CodegenData.typ_func thy thm)
+                    ^ "\nto " ^ Sign.string_of_typ thy (CodegenData.typ_func thy thm')
+                    ^ ",\nfor constant " ^ CodegenConsts.string_of_const thy c
+                    ^ "\nin function theorems\n"
+                    ^ (cat_lines o map string_of_thm) thms)
           in (c, thms') end;
     fun rhs_of' thy (("", []), thms as [_]) =
           add_things_of thy (cons o snd) (NONE, thms) []