normalizing of type variables before evaluation with explicit resubstitution function: make nbe work with funny type variables like \<AA>;
authorhaftmann
Fri, 09 May 2014 08:13:26 +0200
changeset 56920 d651b944c67e
parent 56919 6389a8c1268a
child 56921 5bf71b4da706
normalizing of type variables before evaluation with explicit resubstitution function: make nbe work with funny type variables like \<AA>; tuned naming; dropped dead parameters;
src/HOL/Tools/Quickcheck/narrowing_generators.ML
src/Tools/Code/code_preproc.ML
src/Tools/Code/code_runtime.ML
src/Tools/Code/code_simp.ML
src/Tools/Code/code_target.ML
src/Tools/Code/code_thingol.ML
src/Tools/nbe.ML
--- a/src/HOL/Tools/Quickcheck/narrowing_generators.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/HOL/Tools/Quickcheck/narrowing_generators.ML	Fri May 09 08:13:26 2014 +0200
@@ -305,9 +305,9 @@
 
 fun dynamic_value_strict opts cookie ctxt postproc t =
   let
-    fun evaluator program ((_, vs_ty), t) deps =
+    fun evaluator program _ vs_ty_t deps =
       Exn.interruptible_capture (value opts ctxt cookie)
-        (Code_Target.evaluator ctxt target program deps true (vs_ty, t));
+        (Code_Target.evaluator ctxt target program deps true vs_ty_t);
   in Exn.release (Code_Thingol.dynamic_value ctxt (Exn.map_result o postproc) evaluator t) end;
 
 (** counterexample generator **)
--- a/src/Tools/Code/code_preproc.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/Code/code_preproc.ML	Fri May 09 08:13:26 2014 +0200
@@ -24,14 +24,14 @@
   val pretty: Proof.context -> code_graph -> Pretty.T
   val obtain: bool -> theory -> string list -> term list -> code_algebra * code_graph
   val dynamic_conv: Proof.context
-    -> (code_algebra -> code_graph -> (string * sort) list -> term -> conv) -> conv
+    -> (code_algebra -> code_graph -> term -> conv) -> conv
   val dynamic_value: Proof.context -> ((term -> term) -> 'a -> 'a)
-    -> (code_algebra -> code_graph -> (string * sort) list -> term -> 'a) -> term -> 'a
+    -> (code_algebra -> code_graph -> term -> 'a) -> term -> 'a
   val static_conv: Proof.context -> string list
-    -> (code_algebra -> code_graph -> Proof.context -> (string * sort) list -> term -> conv)
+    -> (code_algebra -> code_graph -> Proof.context -> term -> conv)
     -> Proof.context -> conv
   val static_value: Proof.context -> ((term -> term) -> 'a -> 'a) -> string list
-    -> (code_algebra -> code_graph -> Proof.context -> (string * sort) list -> term -> 'a)
+    -> (code_algebra -> code_graph -> Proof.context -> term -> 'a)
     -> Proof.context -> term -> 'a
 
   val setup: theory -> theory
@@ -462,17 +462,15 @@
   (Wellsorted.change_yield (if ignore_cache then NONE else SOME thy)
     (extend_arities_eqngr (Proof_Context.init_global thy) consts ts));
 
-fun dest_cterm ct = let val t = Thm.term_of ct in (Term.add_tfrees t [], t) end;
-
 fun dynamic_conv ctxt conv = no_variables_conv ctxt (fn ct =>
   let
     val thm1 = preprocess_conv ctxt ctxt ct;
     val ct' = Thm.rhs_of thm1;
-    val (vs', t') = dest_cterm ct';
+    val t' = Thm.term_of ct';
     val consts = fold_aterms
       (fn Const (c, _) => insert (op =) c | _ => I) t' [];
     val (algebra', eqngr') = obtain false (Proof_Context.theory_of ctxt) consts [t'];
-    val thm2 = conv algebra' eqngr' vs' t' ct';
+    val thm2 = conv algebra' eqngr' t' ct';
     val thm3 = postprocess_conv ctxt ctxt (Thm.rhs_of thm2);
   in
     Thm.transitive thm1 (Thm.transitive thm2 thm3) handle THM _ =>
@@ -483,13 +481,12 @@
 fun dynamic_value ctxt postproc evaluator t =
   let
     val (resubst, t') = preprocess_term ctxt ctxt t;
-    val vs' = Term.add_tfrees t' [];
     val consts = fold_aterms
       (fn Const (c, _) => insert (op =) c | _ => I) t' [];
     val (algebra', eqngr') = obtain false (Proof_Context.theory_of ctxt) consts [t'];
   in
     t'
-    |> evaluator algebra' eqngr' vs'
+    |> evaluator algebra' eqngr'
     |> postproc (postprocess_term ctxt ctxt o resubst)
   end;
 
@@ -500,7 +497,7 @@
     val conv' = conv algebra eqngr;
     val post_conv = postprocess_conv ctxt;
   in fn ctxt' => no_variables_conv ctxt' ((pre_conv ctxt')
-    then_conv (fn ct => uncurry (conv' ctxt') (dest_cterm ct) ct)
+    then_conv (fn ct => conv' ctxt' (Thm.term_of ct) ct)
     then_conv (post_conv ctxt'))
   end;
 
@@ -513,7 +510,7 @@
   in fn ctxt' => 
     preproc ctxt'
     #-> (fn resubst => fn t => t
-      |> evaluator' ctxt' (Term.add_tfrees t [])
+      |> evaluator' ctxt'
       |> postproc (postproc' ctxt' o resubst))
   end;
 
--- a/src/Tools/Code/code_runtime.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/Code/code_runtime.ML	Fri May 09 08:13:26 2014 +0200
@@ -112,8 +112,8 @@
     val _ = if ! trace
       then tracing ("Evaluation of term " ^ quote (Syntax.string_of_term ctxt t))
       else ()
-    fun evaluator program ((_, vs_ty), t) deps =
-      evaluation cookie ctxt (obtain_evaluator ctxt some_target program deps) (vs_ty, t) args;
+    fun evaluator program _ vs_ty_t deps =
+      evaluation cookie ctxt (obtain_evaluator ctxt some_target program deps) vs_ty_t args;
   in Code_Thingol.dynamic_value ctxt (Exn.map_result o postproc) evaluator t end;
 
 fun dynamic_value_strict cookie ctxt some_target postproc t args =
@@ -126,7 +126,7 @@
   let
     val evaluator = obtain_evaluator ctxt some_target program (map Constant consts');
     val evaluation' = evaluation cookie ctxt evaluator;
-  in fn _ => fn ((_, vs_ty), t) => fn _ => evaluation' (vs_ty, t) [] end;
+  in fn _ => fn _ => fn vs_ty_t => fn _ => evaluation' vs_ty_t [] end;
 
 fun static_value_exn cookie ctxt some_target postproc consts =
   let
@@ -175,14 +175,14 @@
   (Thm.add_oracle (@{binding holds_by_evaluation},
   fn (ctxt, evaluator, vs_t, ct) => check_holds ctxt evaluator vs_t ct)));
 
-fun check_holds_oracle ctxt evaluator ((_, vs_ty), t) deps ct =
-  raw_check_holds_oracle (ctxt, evaluator, (vs_ty, t), ct);
+fun check_holds_oracle ctxt evaluator vs_ty_t ct =
+  raw_check_holds_oracle (ctxt, evaluator, vs_ty_t, ct);
 
 in
 
 fun dynamic_holds_conv ctxt = Code_Thingol.dynamic_conv ctxt
-  (fn program => fn vs_t => fn deps =>
-    check_holds_oracle ctxt (obtain_evaluator ctxt NONE program deps) vs_t deps)
+  (fn program => fn _ => fn vs_t => fn deps =>
+    check_holds_oracle ctxt (obtain_evaluator ctxt NONE program deps) vs_t)
       o reject_vars ctxt;
 
 fun static_holds_conv ctxt consts =
@@ -190,7 +190,7 @@
     let
       val evaluator' = obtain_evaluator ctxt NONE program (map Constant consts')
     in
-      fn ctxt' => fn vs_t => fn deps => check_holds_oracle ctxt' evaluator' vs_t deps o reject_vars ctxt'
+      fn ctxt' => fn _ => fn vs_t => fn _ => check_holds_oracle ctxt' evaluator' vs_t o reject_vars ctxt'
     end);
 
 (* o reject_vars ctxt'*)
--- a/src/Tools/Code/code_simp.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/Code/code_simp.ML	Fri May 09 08:13:26 2014 +0200
@@ -76,7 +76,7 @@
 (* evaluation with dynamic code context *)
 
 fun dynamic_conv ctxt = Code_Thingol.dynamic_conv ctxt
-  (fn program => fn _ => fn _ => rewrite_modulo ctxt NONE program ctxt);
+  (fn program => fn _ => fn _ => fn _ => rewrite_modulo ctxt NONE program ctxt);
 
 fun dynamic_tac ctxt = CONVERSION (dynamic_conv ctxt)
   THEN' conclude_tac ctxt NONE ctxt;
@@ -96,7 +96,7 @@
 fun static_conv ctxt some_ss consts =
   Code_Thingol.static_conv_simple ctxt consts
     (fn program => let val conv' = rewrite_modulo ctxt some_ss program
-     in fn ctxt' => fn _ => fn _ => conv' ctxt' end);
+     in fn ctxt' => fn _ => conv' ctxt' end);
 
 fun static_tac ctxt some_ss consts =
   let
--- a/src/Tools/Code/code_target.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/Code/code_target.ML	Fri May 09 08:13:26 2014 +0200
@@ -428,7 +428,7 @@
     else Isabelle_System.with_tmp_dir "Code_Test" ext_check
   end;
 
-fun evaluation mounted_serializer prepared_program syms all_public ((vs, ty), t) =
+fun subevaluator mounted_serializer prepared_program syms all_public ((vs, ty), t) =
   let
     val _ = if Code_Thingol.contains_dict_var t then
       error "Term to be evaluated contains free dictionaries" else ();
@@ -449,7 +449,7 @@
   let
     val (mounted_serializer, (_, prepared_program)) =
       mount_serializer ctxt target NONE generatedN [] program syms;
-  in evaluation mounted_serializer prepared_program syms end;
+  in subevaluator mounted_serializer prepared_program syms end;
 
 end; (* local *)
 
--- a/src/Tools/Code/code_thingol.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/Code/code_thingol.ML	Fri May 09 08:13:26 2014 +0200
@@ -86,20 +86,20 @@
   val read_const_exprs: Proof.context -> string list -> string list
   val consts_program: theory -> string list -> program
   val dynamic_conv: Proof.context -> (program
-    -> ((string * sort) list * typscheme) * iterm -> Code_Symbol.T list -> conv)
+    -> (string -> (string * sort)) -> typscheme * iterm -> Code_Symbol.T list -> conv)
     -> conv
   val dynamic_value: Proof.context -> ((term -> term) -> 'a -> 'a) -> (program
-    -> ((string * sort) list * typscheme) * iterm -> Code_Symbol.T list -> 'a)
+    -> (string -> (string * sort)) -> typscheme * iterm -> Code_Symbol.T list -> 'a)
     -> term -> 'a
   val static_conv: Proof.context -> string list -> (program -> string list
-    -> Proof.context -> ((string * sort) list * typscheme) * iterm -> Code_Symbol.T list -> conv)
+    -> Proof.context -> (string -> (string * sort)) -> typscheme * iterm -> Code_Symbol.T list -> conv)
     -> Proof.context -> conv
   val static_conv_simple: Proof.context -> string list
-    -> (program -> Proof.context -> (string * sort) list -> term -> conv)
+    -> (program -> Proof.context -> term -> conv)
     -> Proof.context -> conv
   val static_value: Proof.context -> ((term -> term) -> 'a -> 'a) -> string list ->
     (program -> string list
-      -> Proof.context -> ((string * sort) list * typscheme) * iterm -> Code_Symbol.T list -> 'a)
+      -> Proof.context -> (string -> (string * sort)) -> typscheme * iterm -> Code_Symbol.T list -> 'a)
     -> Proof.context -> term -> 'a
 end;
 
@@ -388,7 +388,7 @@
 
 exception PERMISSIVE of unit;
 
-fun translation_error ctxt program permissive some_thm deps msg sub_msg =
+fun translation_error ctxt permissive some_thm deps msg sub_msg =
   if permissive
   then raise PERMISSIVE ()
   else
@@ -408,14 +408,14 @@
 fun maybe_permissive f prgrm =
   f prgrm |>> SOME handle PERMISSIVE () => (NONE, prgrm);
 
-fun not_wellsorted ctxt program permissive some_thm deps ty sort e =
+fun not_wellsorted ctxt permissive some_thm deps ty sort e =
   let
     val err_class = Sorts.class_error (Context.pretty ctxt) e;
     val err_typ =
       "Type " ^ Syntax.string_of_typ ctxt ty ^ " not of sort " ^
         Syntax.string_of_sort ctxt sort;
   in
-    translation_error ctxt program permissive some_thm deps
+    translation_error ctxt permissive some_thm deps
       "Wellsortedness error" (err_typ ^ "\n" ^ err_class)
   end;
 
@@ -483,7 +483,7 @@
       {class_relation = K (Sorts.classrel_derivation algebra class_relation),
        type_constructor = type_constructor,
        type_variable = type_variable} (ty, proj_sort sort)
-      handle Sorts.CLASS_ERROR e => not_wellsorted ctxt program permissive some_thm deps ty sort e;
+      handle Sorts.CLASS_ERROR e => not_wellsorted ctxt permissive some_thm deps ty sort e;
   in (typarg_witnesses, (deps, program)) end;
 
 
@@ -630,7 +630,7 @@
     val thy = Proof_Context.theory_of ctxt;
     val _ = if (case some_abs of NONE => true | SOME abs => not (c = abs))
         andalso Code.is_abstr thy c
-        then translation_error ctxt program permissive some_thm deps
+        then translation_error ctxt permissive some_thm deps
           "Abstraction violation" ("constant " ^ Code.string_of_const thy c)
       else ()
   in translate_const_proper ctxt algbr eqngr permissive some_thm (c, ty) (deps, program) end
@@ -795,11 +795,18 @@
 
 (* value evaluation *)
 
-fun ensure_value ctxt algbr eqngr t =
+fun normalize_tvars t = 
   let
     val ty = fastype_of t;
-    val vs = fold_term_types (K (fold_atyps (insert (eq_fst op =)
+    val vs_original = fold_term_types (K (fold_atyps (insert (eq_fst op =)
       o dest_TFree))) t [];
+    val vs_normalized = Name.invent_names Name.context Name.aT (map snd vs_original);
+    val normalize = map_type_tfree (TFree o the o AList.lookup (op =) (vs_original ~~ vs_normalized));
+  in ((vs_original, (vs_normalized, normalize ty)), map_types normalize t) end;
+
+fun ensure_value ctxt algbr eqngr t_original =
+  let
+    val ((vs_original, (vs, ty)), t) = normalize_tvars t_original;
     val t' = annotate ctxt algbr eqngr (@{const_name Pure.dummy_pattern}, ty) [] t;
     val dummy_constant = Constant @{const_name Pure.dummy_pattern};
     val stmt_value =
@@ -808,29 +815,27 @@
       ##>> translate_term ctxt algbr eqngr false NONE (t', NONE)
       #>> (fn ((vs, ty), t) => Fun
         (((vs, ty), [(([], t), (NONE, true))]), NONE));
-    fun term_value (deps, program1) =
+    fun term_value (_, program1) =
       let
-        val Fun ((vs_ty, [(([], t), _)]), _) =
+        val Fun ((vs_ty as (vs, _), [(([], t), _)]), _) =
           Code_Symbol.Graph.get_node program1 dummy_constant;
         val deps' = Code_Symbol.Graph.immediate_succs program1 dummy_constant;
         val program2 = Code_Symbol.Graph.del_node dummy_constant program1;
         val deps_all = Code_Symbol.Graph.all_succs program2 deps';
         val program3 = Code_Symbol.Graph.restrict (member (op =) deps_all) program2;
-      in ((program3, ((vs_ty, t), deps')), (deps, program2)) end;
+        val vs_mapping = map fst vs ~~ vs_original;
+      in (((the o AList.lookup (op =) vs_mapping), (program3, ((vs_ty, t), deps'))), (deps', program2)) end;
   in
     ensure_stmt Constant stmt_value @{const_name Pure.dummy_pattern}
     #> snd
     #> term_value
   end;
 
-fun original_sorts vs =
-  map (fn (v, _) => (v, (the o AList.lookup (op =) vs o prefix "'") v));
-
-fun dynamic_evaluator ctxt evaluator algebra eqngr vs t =
+fun dynamic_evaluator ctxt evaluator algebra eqngr t =
   let
-    val ((program, (((vs', ty'), t'), deps)), _) =
+    val ((resubst_tvar, (program, ((vs_ty', t'), deps))), _) =
       invoke_generation false (Proof_Context.theory_of ctxt) (algebra, eqngr) ensure_value t;
-  in evaluator program ((original_sorts vs vs', (vs', ty')), t') deps end;
+  in evaluator program resubst_tvar (vs_ty', t') deps end;
 
 fun dynamic_conv ctxt conv =
   Code_Preproc.dynamic_conv ctxt (dynamic_evaluator ctxt conv);
@@ -838,22 +843,22 @@
 fun dynamic_value ctxt postproc evaluator =
   Code_Preproc.dynamic_value ctxt postproc (dynamic_evaluator ctxt evaluator);
 
-fun lift_evaluation ctxt evaluation algebra eqngr program vs t =
+fun static_subevaluator ctxt subevaluator algebra eqngr program t =
   let
-    val ((_, (((vs', ty'), t'), deps)), _) =
+    val ((resubst_tvar, (_, ((vs_ty', t'), deps))), _) =
       ensure_value ctxt algebra eqngr t ([], program);
-  in evaluation ctxt ((original_sorts vs vs', (vs', ty')), t') deps end;
+  in subevaluator ctxt resubst_tvar (vs_ty', t') deps end;
 
-fun lift_evaluator ctxt evaluator consts algebra eqngr =
+fun static_evaluator ctxt evaluator consts algebra eqngr =
   let
     fun generate_consts ctxt algebra eqngr =
       fold_map (ensure_const ctxt algebra eqngr false);
     val (consts', program) =
       invoke_generation true (Proof_Context.theory_of ctxt) (algebra, eqngr) generate_consts consts;
-    val evaluation = evaluator program consts';
-  in fn ctxt' => lift_evaluation ctxt' evaluation algebra eqngr program end;
+    val subevaluator = evaluator program consts';
+  in fn ctxt' => static_subevaluator ctxt' subevaluator algebra eqngr program end;
 
-fun lift_evaluator_simple ctxt evaluator consts algebra eqngr =
+fun static_evaluator_simple ctxt evaluator consts algebra eqngr =
   let
     fun generate_consts ctxt algebra eqngr =
       fold_map (ensure_const ctxt algebra eqngr false);
@@ -862,13 +867,13 @@
   in evaluator program end;
 
 fun static_conv ctxt consts conv =
-  Code_Preproc.static_conv ctxt consts (lift_evaluator ctxt conv consts);
+  Code_Preproc.static_conv ctxt consts (static_evaluator ctxt conv consts);
 
 fun static_conv_simple ctxt consts conv =
-  Code_Preproc.static_conv ctxt consts (lift_evaluator_simple ctxt conv consts);
+  Code_Preproc.static_conv ctxt consts (static_evaluator_simple ctxt conv consts);
 
 fun static_value ctxt postproc consts evaluator =
-  Code_Preproc.static_value ctxt postproc consts (lift_evaluator ctxt evaluator consts);
+  Code_Preproc.static_value ctxt postproc consts (static_evaluator ctxt evaluator consts);
 
 
 (** constant expressions **)
--- a/src/Tools/nbe.ML	Thu May 08 21:17:23 2014 +0200
+++ b/src/Tools/nbe.ML	Fri May 09 08:13:26 2014 +0200
@@ -502,10 +502,11 @@
 
 (* reconstruction *)
 
-fun typ_of_itype vs (tyco `%% itys) =
-      Type (tyco, map (typ_of_itype vs) itys)
-  | typ_of_itype vs (ITyVar v) =
-      TFree ("'" ^ v, (the o AList.lookup (op =) vs) v);
+fun typ_of_itype resubst_tvar =
+  let
+    fun typ_of (tyco `%% itys) = Type (tyco, map typ_of itys)
+      | typ_of (ITyVar v) = TFree (resubst_tvar v);
+  in typ_of end;
 
 fun term_of_univ ctxt (idx_tab : Code_Symbol.T Inttab.table) t =
   let
@@ -542,11 +543,11 @@
 
 (* evaluation with type reconstruction *)
 
-fun eval_term raw_ctxt (nbe_program, idx_tab) ((vs0, (vs, ty)), t) deps =
+fun eval_term raw_ctxt (nbe_program, idx_tab) resubst_tvar ((vs, ty), t) deps =
   let
     val ctxt = Syntax.init_pretty_global (Proof_Context.theory_of raw_ctxt);
     val string_of_term = Syntax.string_of_term (Config.put show_types true ctxt);
-    val ty' = typ_of_itype vs0 ty;
+    val ty' = typ_of_itype resubst_tvar ty;
     fun type_infer t =
       Syntax.check_term (Config.put Type_Infer_Context.const_sorts false ctxt)
         (Type.constraint ty' t);
@@ -592,11 +593,11 @@
 
 val (_, raw_oracle) = Context.>>> (Context.map_theory_result
   (Thm.add_oracle (@{binding normalization_by_evaluation},
-    fn (ctxt, nbe_program_idx_tab, vsp_ty_t, deps, ct) =>
-      mk_equals ctxt ct (eval_term ctxt nbe_program_idx_tab vsp_ty_t deps))));
+    fn (ctxt, nbe_program_idx_tab, resubst_tvars, vs_ty_t, deps, ct) =>
+      mk_equals ctxt ct (eval_term ctxt nbe_program_idx_tab resubst_tvars vs_ty_t deps))));
 
-fun oracle ctxt nbe_program_idx_tab vsp_ty_t deps ct =
-  raw_oracle (ctxt, nbe_program_idx_tab, vsp_ty_t, deps, ct);
+fun oracle ctxt nbe_program_idx_tab resubst_tvars vs_ty_t deps ct =
+  raw_oracle (ctxt, nbe_program_idx_tab, resubst_tvars, vs_ty_t, deps, ct);
 
 fun dynamic_conv ctxt = lift_triv_classes_conv ctxt
   (Code_Thingol.dynamic_conv ctxt (oracle ctxt o compile false ctxt));