| author | blanchet | 
| Thu, 20 Sep 2012 17:35:49 +0200 | |
| changeset 49484 | 0194a18f80cf | 
| parent 47576 | b32aae03e3d6 | 
| child 51429 | 48eb29821bd9 | 
| permissions | -rw-r--r-- | 
| 37781 | 1 | (* Title: Tools/misc_legacy.ML | 
| 2 | ||
| 3 | Misc legacy stuff -- to be phased out eventually. | |
| 4 | *) | |
| 5 | ||
| 6 | signature MISC_LEGACY = | |
| 7 | sig | |
| 44121 | 8 | val add_term_names: term * string list -> string list | 
| 9 | val add_typ_tvars: typ * (indexname * sort) list -> (indexname * sort) list | |
| 10 | val add_typ_tfree_names: typ * string list -> string list | |
| 11 | val add_typ_tfrees: typ * (string * sort) list -> (string * sort) list | |
| 12 | val add_term_tvars: term * (indexname * sort) list -> (indexname * sort) list | |
| 13 | val add_term_tfrees: term * (string * sort) list -> (string * sort) list | |
| 14 | val add_term_tfree_names: term * string list -> string list | |
| 15 | val typ_tfrees: typ -> (string * sort) list | |
| 16 | val typ_tvars: typ -> (indexname * sort) list | |
| 17 | val term_tfrees: term -> (string * sort) list | |
| 18 | val term_tvars: term -> (indexname * sort) list | |
| 19 | val add_term_vars: term * term list -> term list | |
| 20 | val term_vars: term -> term list | |
| 21 | val add_term_frees: term * term list -> term list | |
| 22 | val term_frees: term -> term list | |
| 37781 | 23 | val mk_defpair: term * term -> string * term | 
| 24 | val get_def: theory -> xstring -> thm | |
| 25 | val METAHYPS: (thm list -> tactic) -> int -> tactic | |
| 47022 | 26 | val gensym: string -> string | 
| 27 | val freeze_thaw_robust: thm -> thm * (int -> thm -> thm) | |
| 28 | val freeze_thaw: thm -> thm * (thm -> thm) | |
| 37781 | 29 | end; | 
| 30 | ||
| 31 | structure Misc_Legacy: MISC_LEGACY = | |
| 32 | struct | |
| 33 | ||
| 44121 | 34 | (*iterate a function over all types in a term*) | 
| 35 | fun it_term_types f = | |
| 36 | let fun iter(Const(_,T), a) = f(T,a) | |
| 37 | | iter(Free(_,T), a) = f(T,a) | |
| 38 | | iter(Var(_,T), a) = f(T,a) | |
| 39 | | iter(Abs(_,T,t), a) = iter(t,f(T,a)) | |
| 40 | | iter(f$u, a) = iter(f, iter(u, a)) | |
| 41 | | iter(Bound _, a) = a | |
| 42 | in iter end | |
| 43 | ||
| 44 | (*Accumulates the names in the term, suppressing duplicates. | |
| 45 | Includes Frees and Consts. For choosing unambiguous bound var names.*) | |
| 46 | fun add_term_names (Const(a,_), bs) = insert (op =) (Long_Name.base_name a) bs | |
| 47 | | add_term_names (Free(a,_), bs) = insert (op =) a bs | |
| 48 | | add_term_names (f$u, bs) = add_term_names (f, add_term_names(u, bs)) | |
| 49 | | add_term_names (Abs(_,_,t), bs) = add_term_names(t,bs) | |
| 50 | | add_term_names (_, bs) = bs; | |
| 51 | ||
| 52 | (*Accumulates the TVars in a type, suppressing duplicates.*) | |
| 53 | fun add_typ_tvars(Type(_,Ts),vs) = List.foldr add_typ_tvars vs Ts | |
| 54 | | add_typ_tvars(TFree(_),vs) = vs | |
| 55 | | add_typ_tvars(TVar(v),vs) = insert (op =) v vs; | |
| 56 | ||
| 57 | (*Accumulates the TFrees in a type, suppressing duplicates.*) | |
| 58 | fun add_typ_tfree_names(Type(_,Ts),fs) = List.foldr add_typ_tfree_names fs Ts | |
| 59 | | add_typ_tfree_names(TFree(f,_),fs) = insert (op =) f fs | |
| 60 | | add_typ_tfree_names(TVar(_),fs) = fs; | |
| 61 | ||
| 62 | fun add_typ_tfrees(Type(_,Ts),fs) = List.foldr add_typ_tfrees fs Ts | |
| 63 | | add_typ_tfrees(TFree(f),fs) = insert (op =) f fs | |
| 64 | | add_typ_tfrees(TVar(_),fs) = fs; | |
| 65 | ||
| 66 | (*Accumulates the TVars in a term, suppressing duplicates.*) | |
| 67 | val add_term_tvars = it_term_types add_typ_tvars; | |
| 68 | ||
| 69 | (*Accumulates the TFrees in a term, suppressing duplicates.*) | |
| 70 | val add_term_tfrees = it_term_types add_typ_tfrees; | |
| 71 | val add_term_tfree_names = it_term_types add_typ_tfree_names; | |
| 72 | ||
| 73 | (*Non-list versions*) | |
| 74 | fun typ_tfrees T = add_typ_tfrees(T,[]); | |
| 75 | fun typ_tvars T = add_typ_tvars(T,[]); | |
| 76 | fun term_tfrees t = add_term_tfrees(t,[]); | |
| 77 | fun term_tvars t = add_term_tvars(t,[]); | |
| 78 | ||
| 79 | ||
| 80 | (*Accumulates the Vars in the term, suppressing duplicates.*) | |
| 81 | fun add_term_vars (t, vars: term list) = case t of | |
| 82 | Var _ => Ord_List.insert Term_Ord.term_ord t vars | |
| 83 | | Abs (_,_,body) => add_term_vars(body,vars) | |
| 84 | | f$t => add_term_vars (f, add_term_vars(t, vars)) | |
| 85 | | _ => vars; | |
| 86 | ||
| 87 | fun term_vars t = add_term_vars(t,[]); | |
| 88 | ||
| 89 | (*Accumulates the Frees in the term, suppressing duplicates.*) | |
| 90 | fun add_term_frees (t, frees: term list) = case t of | |
| 91 | Free _ => Ord_List.insert Term_Ord.term_ord t frees | |
| 92 | | Abs (_,_,body) => add_term_frees(body,frees) | |
| 93 | | f$t => add_term_frees (f, add_term_frees(t, frees)) | |
| 94 | | _ => frees; | |
| 95 | ||
| 96 | fun term_frees t = add_term_frees(t,[]); | |
| 97 | ||
| 98 | ||
| 37781 | 99 | fun mk_defpair (lhs, rhs) = | 
| 100 | (case Term.head_of lhs of | |
| 101 | Const (name, _) => | |
| 46909 | 102 | (Thm.def_name (Long_Name.base_name name), Logic.mk_equals (lhs, rhs)) | 
| 37781 | 103 |   | _ => raise TERM ("Malformed definition: head of lhs not a constant", [lhs, rhs]));
 | 
| 104 | ||
| 105 | ||
| 106 | fun get_def thy = Thm.axiom thy o Name_Space.intern (Theory.axiom_space thy) o Thm.def_name; | |
| 107 | ||
| 108 | ||
| 109 | (**** METAHYPS -- tactical for using hypotheses as meta-level assumptions | |
| 110 | METAHYPS (fn prems => tac prems) i | |
| 111 | ||
| 112 | converts subgoal i, of the form !!x1...xm. [| A1;...;An] ==> A into a new | |
| 113 | proof state A==>A, supplying A1,...,An as meta-level assumptions (in | |
| 114 | "prems"). The parameters x1,...,xm become free variables. If the | |
| 115 | resulting proof state is [| B1;...;Bk] ==> C (possibly assuming A1,...,An) | |
| 116 | then it is lifted back into the original context, yielding k subgoals. | |
| 117 | ||
| 118 | Replaces unknowns in the context by Frees having the prefix METAHYP_ | |
| 119 | New unknowns in [| B1;...;Bk] ==> C are lifted over x1,...,xm. | |
| 120 | DOES NOT HANDLE TYPE UNKNOWNS. | |
| 121 | ||
| 122 | ||
| 123 | NOTE: This version does not observe the proof context, and thus cannot | |
| 124 | work reliably. See also Subgoal.SUBPROOF and Subgoal.FOCUS for | |
| 125 | properly localized variants of the same idea. | |
| 126 | ****) | |
| 127 | ||
| 128 | local | |
| 129 | ||
| 130 | (*Strips assumptions in goal yielding ( [x1,...,xm], [H1,...,Hn], B ) | |
| 131 | H1,...,Hn are the hypotheses; x1...xm are variants of the parameters. | |
| 132 | Main difference from strip_assums concerns parameters: | |
| 133 | it replaces the bound variables by free variables. *) | |
| 134 | fun strip_context_aux (params, Hs, Const ("==>", _) $ H $ B) =
 | |
| 135 | strip_context_aux (params, H :: Hs, B) | |
| 136 |   | strip_context_aux (params, Hs, Const ("all",_) $ Abs (a, T, t)) =
 | |
| 42284 | 137 | let val (b, u) = Syntax_Trans.variant_abs (a, T, t) | 
| 37781 | 138 | in strip_context_aux ((b, T) :: params, Hs, u) end | 
| 139 | | strip_context_aux (params, Hs, B) = (rev params, rev Hs, B); | |
| 140 | ||
| 141 | fun strip_context A = strip_context_aux ([], [], A); | |
| 142 | ||
| 143 | (*Left-to-right replacements: ctpairs = [...,(vi,ti),...]. | |
| 144 | Instantiates distinct free variables by terms of same type.*) | |
| 145 | fun free_instantiate ctpairs = | |
| 146 | forall_elim_list (map snd ctpairs) o forall_intr_list (map fst ctpairs); | |
| 147 | ||
| 148 | fun free_of s ((a, i), T) = | |
| 149 | Free (s ^ (case i of 0 => a | _ => a ^ "_" ^ string_of_int i), T) | |
| 150 | ||
| 151 | fun mk_inst v = (Var v, free_of "METAHYP1_" v) | |
| 152 | ||
| 153 | fun metahyps_split_prem prem = | |
| 154 | let (*find all vars in the hyps -- should find tvars also!*) | |
| 155 | val hyps_vars = fold Term.add_vars (Logic.strip_assums_hyp prem) [] | |
| 156 | val insts = map mk_inst hyps_vars | |
| 157 | (*replace the hyps_vars by Frees*) | |
| 158 | val prem' = subst_atomic insts prem | |
| 159 | val (params,hyps,concl) = strip_context prem' | |
| 160 | in (insts,params,hyps,concl) end; | |
| 161 | ||
| 162 | fun metahyps_aux_tac tacf (prem,gno) state = | |
| 163 | let val (insts,params,hyps,concl) = metahyps_split_prem prem | |
| 164 | val maxidx = Thm.maxidx_of state | |
| 165 | val cterm = Thm.cterm_of (Thm.theory_of_thm state) | |
| 166 | val chyps = map cterm hyps | |
| 167 | val hypths = map Thm.assume chyps | |
| 168 | val subprems = map (Thm.forall_elim_vars 0) hypths | |
| 169 | val fparams = map Free params | |
| 170 | val cparams = map cterm fparams | |
| 171 | fun swap_ctpair (t,u) = (cterm u, cterm t) | |
| 172 | (*Subgoal variables: make Free; lift type over params*) | |
| 173 | fun mk_subgoal_inst concl_vars (v, T) = | |
| 174 | if member (op =) concl_vars (v, T) | |
| 175 | then ((v, T), true, free_of "METAHYP2_" (v, T)) | |
| 176 | else ((v, T), false, free_of "METAHYP2_" (v, map #2 params ---> T)) | |
| 177 | (*Instantiate subgoal vars by Free applied to params*) | |
| 178 | fun mk_ctpair (v, in_concl, u) = | |
| 179 | if in_concl then (cterm (Var v), cterm u) | |
| 180 | else (cterm (Var v), cterm (list_comb (u, fparams))) | |
| 181 | (*Restore Vars with higher type and index*) | |
| 182 | fun mk_subgoal_swap_ctpair (((a, i), T), in_concl, u as Free (_, U)) = | |
| 183 | if in_concl then (cterm u, cterm (Var ((a, i), T))) | |
| 184 | else (cterm u, cterm (Var ((a, i + maxidx), U))) | |
| 185 | (*Embed B in the original context of params and hyps*) | |
| 46215 
0da9433f959e
discontinued old-style Term.list_all_free in favour of plain Logic.all;
 wenzelm parents: 
45862diff
changeset | 186 | fun embed B = fold_rev Logic.all fparams (Logic.list_implies (hyps, B)) | 
| 37781 | 187 | (*Strip the context using elimination rules*) | 
| 188 | fun elim Bhyp = implies_elim_list (forall_elim_list cparams Bhyp) hypths | |
| 189 | (*A form of lifting that discharges assumptions.*) | |
| 190 | fun relift st = | |
| 191 | let val prop = Thm.prop_of st | |
| 192 | val subgoal_vars = (*Vars introduced in the subgoals*) | |
| 193 | fold Term.add_vars (Logic.strip_imp_prems prop) [] | |
| 194 | and concl_vars = Term.add_vars (Logic.strip_imp_concl prop) [] | |
| 195 | val subgoal_insts = map (mk_subgoal_inst concl_vars) subgoal_vars | |
| 196 | val st' = Thm.instantiate ([], map mk_ctpair subgoal_insts) st | |
| 197 | val emBs = map (cterm o embed) (prems_of st') | |
| 198 | val Cth = implies_elim_list st' (map (elim o Thm.assume) emBs) | |
| 199 | in (*restore the unknowns to the hypotheses*) | |
| 200 | free_instantiate (map swap_ctpair insts @ | |
| 201 | map mk_subgoal_swap_ctpair subgoal_insts) | |
| 202 | (*discharge assumptions from state in same order*) | |
| 203 | (implies_intr_list emBs | |
| 204 | (forall_intr_list cparams (implies_intr_list chyps Cth))) | |
| 205 | end | |
| 206 | (*function to replace the current subgoal*) | |
| 207 | fun next st = Thm.bicompose false (false, relift st, nprems_of st) gno state | |
| 208 | in Seq.maps next (tacf subprems (Thm.trivial (cterm concl))) end; | |
| 209 | ||
| 210 | fun print_vars_terms n thm = | |
| 211 | let | |
| 212 | val thy = theory_of_thm thm | |
| 213 | fun typed s ty = | |
| 214 | " " ^ s ^ " has type: " ^ Syntax.string_of_typ_global thy ty; | |
| 215 | fun find_vars (Const (c, ty)) = | |
| 216 | if null (Term.add_tvarsT ty []) then I | |
| 217 | else insert (op =) (typed c ty) | |
| 218 | | find_vars (Var (xi, ty)) = | |
| 219 | insert (op =) (typed (Term.string_of_vname xi) ty) | |
| 220 | | find_vars (Free _) = I | |
| 221 | | find_vars (Bound _) = I | |
| 222 | | find_vars (Abs (_, _, t)) = find_vars t | |
| 223 | | find_vars (t1 $ t2) = find_vars t1 #> find_vars t2; | |
| 224 | val prem = Logic.nth_prem (n, Thm.prop_of thm) | |
| 225 | val tms = find_vars prem [] | |
| 226 |   in warning (cat_lines ("Found schematic vars in assumptions:" :: tms)) end;
 | |
| 227 | ||
| 228 | in | |
| 229 | ||
| 230 | fun METAHYPS tacf n thm = SUBGOAL (metahyps_aux_tac tacf) n thm | |
| 231 |   handle THM("assume: variables",_,_) => (print_vars_terms n thm; Seq.empty)
 | |
| 232 | ||
| 233 | end; | |
| 234 | ||
| 47022 | 235 | |
| 236 | (* generating identifiers -- often fresh *) | |
| 237 | ||
| 238 | local | |
| 239 | (*Maps 0-61 to A-Z, a-z, 0-9; exclude _ or ' to avoid clash with internal/unusual indentifiers*) | |
| 240 | fun gensym_char i = | |
| 241 | if i<26 then chr (ord "A" + i) | |
| 242 | else if i<52 then chr (ord "a" + i - 26) | |
| 243 | else chr (ord "0" + i - 52); | |
| 244 | ||
| 245 | val char_vec = Vector.tabulate (62, gensym_char); | |
| 246 | fun newid n = implode (map (fn i => Vector.sub (char_vec, i)) (radixpand (62, n))); | |
| 247 | ||
| 248 | val gensym_seed = Unsynchronized.ref (0: int); | |
| 249 | ||
| 250 | in | |
| 251 | fun gensym pre = pre ^ newid (CRITICAL (fn () => Unsynchronized.inc gensym_seed)); | |
| 37781 | 252 | end; | 
| 253 | ||
| 47022 | 254 | |
| 255 | (*Convert all Vars in a theorem to Frees. Also return a function for | |
| 256 | reversing that operation. DOES NOT WORK FOR TYPE VARIABLES.*) | |
| 257 | ||
| 258 | fun freeze_thaw_robust th = | |
| 259 | let val fth = Thm.legacy_freezeT th | |
| 260 | val thy = Thm.theory_of_thm fth | |
| 261 | in | |
| 262 | case Thm.fold_terms Term.add_vars fth [] of | |
| 47576 | 263 | [] => (fth, fn _ => fn x => x) (*No vars: nothing to do!*) | 
| 47022 | 264 | | vars => | 
| 265 | let fun newName (ix,_) = (ix, gensym (string_of_indexname ix)) | |
| 266 | val alist = map newName vars | |
| 267 | fun mk_inst (v,T) = | |
| 268 | (cterm_of thy (Var(v,T)), | |
| 269 | cterm_of thy (Free(((the o AList.lookup (op =) alist) v), T))) | |
| 270 | val insts = map mk_inst vars | |
| 271 | fun thaw i th' = (*i is non-negative increment for Var indexes*) | |
| 272 | th' |> forall_intr_list (map #2 insts) | |
| 273 | |> forall_elim_list (map (Thm.incr_indexes_cterm i o #1) insts) | |
| 274 | in (Thm.instantiate ([],insts) fth, thaw) end | |
| 275 | end; | |
| 276 | ||
| 277 | (*Basic version of the function above. No option to rename Vars apart in thaw. | |
| 278 | The Frees created from Vars have nice names.*) | |
| 279 | fun freeze_thaw th = | |
| 280 | let val fth = Thm.legacy_freezeT th | |
| 281 | val thy = Thm.theory_of_thm fth | |
| 282 | in | |
| 283 | case Thm.fold_terms Term.add_vars fth [] of | |
| 284 | [] => (fth, fn x => x) | |
| 285 | | vars => | |
| 286 | let fun newName (ix, _) (pairs, used) = | |
| 287 | let val v = singleton (Name.variant_list used) (string_of_indexname ix) | |
| 288 | in ((ix,v)::pairs, v::used) end; | |
| 289 | val (alist, _) = | |
| 290 | fold_rev newName vars ([], Thm.fold_terms Term.add_free_names fth []) | |
| 291 | fun mk_inst (v, T) = | |
| 292 | (cterm_of thy (Var(v,T)), | |
| 293 | cterm_of thy (Free(((the o AList.lookup (op =) alist) v), T))) | |
| 294 | val insts = map mk_inst vars | |
| 295 | fun thaw th' = | |
| 296 | th' |> forall_intr_list (map #2 insts) | |
| 297 | |> forall_elim_list (map #1 insts) | |
| 298 | in (Thm.instantiate ([],insts) fth, thaw) end | |
| 299 | end; | |
| 300 | ||
| 301 | end; | |
| 302 |