signature BASIC_TERM = sig type indexname = string * int type class = string type sort = class list type arity = string * sort list * sort datatype typ = Typeofstring * typ list |
TFree ofstring * sort |
TVar of indexname * sort datatype term = Constofstring * typ |
Free ofstring * typ |
Var of indexname * typ |
Bound of int |
Abs ofstring * typ * term |
$ of term * term
exception TYPEofstring * typ list * term list
exception TERM ofstring * term list val dummyS: sort val dummyT: typ val no_dummyT: typ -> typ val --> : typ * typ -> typ val ---> : typ list * typ -> typ val is_Type: typ -> bool val is_TFree: typ -> bool val is_TVar: typ -> bool val eq_Type_name: typ * typ -> bool val dest_Type: typ -> string * typ list val dest_Type_name: typ -> string val dest_Type_args: typ -> typ list val dest_TFree: typ -> string * sort val dest_TVar: typ -> indexname * sort val is_Bound: term -> bool val is_Const: term -> bool val is_Free: term -> bool val is_Var: term -> bool val eq_Const_name: term * term -> bool val dest_Const: term -> string * typ val dest_Const_name: term -> string val dest_Const_type: term -> typ val dest_Free: term -> string * typ val dest_Var: term -> indexname * typ val dest_comb: term -> term * term val domain_type: typ -> typ val range_type: typ -> typ val dest_funT: typ -> typ * typ val binder_types: typ -> typ list val body_type: typ -> typ val strip_type: typ -> typ list * typ val type_of1: typ list * term -> typ val type_of: term -> typ val fastype_of1: typ list * term -> typ val fastype_of: term -> typ val strip_abs: term -> (string * typ) list * term val strip_abs_body: term -> term val strip_abs_vars: term -> (string * typ) list val strip_qnt_body: string -> term -> term val strip_qnt_vars: string -> term -> (string * typ) list val list_comb: term * term list -> term val strip_comb: term -> term * term list val head_of: term -> term val size_of_term: term -> int val size_of_typ: typ -> int val map_atyps: typ Same.operation -> typ -> typ val map_aterms: term Same.operation -> term -> term val map_types: typ Same.operation -> term -> term val map_type_tvar: (indexname * sort, typ) Same.function -> typ -> typ val map_type_tfree: (string * sort, typ) Same.function -> typ -> typ val fold_atyps: (typ -> 'a -> 'a) -> typ -> 'a -> 'a val fold_atyps_sorts: (typ * sort -> 'a -> 'a) -> typ -> 'a -> 'a val fold_aterms: (term -> 'a -> 'a) -> term -> 'a -> 'a val fold_term_types: (term -> typ -> 'a -> 'a) -> term -> 'a -> 'a val fold_types: (typ -> 'a -> 'a) -> term -> 'a -> 'a val burrow_types: (typ list -> typ list) -> term list -> term list val aconv: term * term -> bool val propT: typ val strip_all_body: term -> term val strip_all_vars: term -> (string * typ) list val incr_bv_same: int -> int -> term Same.operation val incr_bv: int -> int -> term -> term val incr_boundvars: int -> term -> term val add_loose_bnos: term * int * int list -> int list val loose_bnos: term -> int list val loose_bvar: term * int -> bool val loose_bvar1: term * int -> bool val subst_bounds_same: term list -> int -> term Same.operation val subst_bounds: term list * term -> term val subst_bound: term * term -> term val betapply: term * term -> term val betapplys: term * term list -> term val subst_free: (term * term) list -> term -> term val abstract_over: term * term -> term val lambda: term -> term -> term val absfree: string * typ -> term -> term val absdummy: typ -> term -> term val subst_atomic: (term * term) list -> term -> term val typ_subst_atomic: (typ * typ) list -> typ -> typ val subst_atomic_types: (typ * typ) list -> term -> term val typ_subst_TVars: (indexname * typ) list -> typ -> typ val subst_TVars: (indexname * typ) list -> term -> term val subst_Vars: (indexname * term) list -> term -> term val subst_vars: (indexname * typ) list * (indexname * term) list -> term -> term val is_first_order: stringlist -> term -> bool val maxidx_of_typ: typ -> int val maxidx_of_typs: typ list -> int val maxidx_of_term: term -> int val fold_subtypes: (typ -> 'a -> 'a) -> typ -> 'a -> 'a val exists_subtype: (typ -> bool) -> typ -> bool val exists_type: (typ -> bool) -> term -> bool val exists_subterm: (term -> bool) -> term -> bool val exists_Const: (string * typ -> bool) -> term -> bool val is_schematic: term -> bool end;
signature TERM = sig
include BASIC_TERM val map_atyps_same: typ Same.operation -> typ Same.operation val map_aterms_same: term Same.operation -> term Same.operation val map_types_same: typ Same.operation -> term Same.operation val aT: sort -> typ val itselfT: typ -> typ val a_itselfT: typ val argument_type_of: term -> int -> typ val abs: string * typ -> term -> term val args_of: term -> term list val add_tvar_namesT: typ -> indexname list -> indexname list val add_tvar_names: term -> indexname list -> indexname list val add_tvarsT: typ -> (indexname * sort) list -> (indexname * sort) list val add_tvars: term -> (indexname * sort) list -> (indexname * sort) list val add_var_names: term -> indexname list -> indexname list val add_vars: term -> (indexname * typ) list -> (indexname * typ) list val add_tfree_namesT: typ -> stringlist -> stringlist val add_tfree_names: term -> stringlist -> stringlist val add_tfreesT: typ -> (string * sort) list -> (string * sort) list val add_tfrees: term -> (string * sort) list -> (string * sort) list val add_free_names: term -> stringlist -> stringlist val add_frees: term -> (string * typ) list -> (string * typ) list val add_const_names: term -> stringlist -> stringlist val add_consts: term -> (string * typ) list -> (string * typ) list val declare_tfree_namesT: typ -> Name.context -> Name.context val declare_tfree_names: term -> Name.context -> Name.context val declare_tvar_namesT: (int -> bool) -> typ -> Name.context -> Name.context val declare_tvar_names: (int -> bool) -> term -> Name.context -> Name.context val declare_free_names: term -> Name.context -> Name.context val declare_var_names: (int -> bool) -> term -> Name.context -> Name.context val variant_bounds: term -> (string * 'a) list -> (string * 'a) list val hidden_polymorphism: term -> (indexname * sort) list val smash_sortsT_same: sort -> typ Same.operation val smash_sortsT: sort -> typ -> typ val smash_sorts: sort -> term -> term val strip_sortsT_same: typ Same.operation val strip_sortsT: typ -> typ val strip_sorts: term -> term val eq_ix: indexname * indexname -> bool val eq_tvar: (indexname * sort) * (indexname * sort) -> bool val eq_var: (indexname * typ) * (indexname * typ) -> bool val aconv_untyped: term * term -> bool val could_unify: term * term -> bool val strip_abs_eta: int -> term -> (string * typ) list * term val match_bvars: (term * term) -> (string * string) list -> (string * string) list val map_abs_vars: (string -> string) -> term -> term val rename_abs: term -> term -> term -> term option val is_open: term -> bool val is_dependent: term -> bool val term_name: term -> string val dependent_lambda_name: string * term -> term -> term val lambda_name: string * term -> term -> term val close_schematic_term: term -> term val maxidx_typ: typ -> int -> int val maxidx_typs: typ list -> int -> int val maxidx_term: term -> int -> int val could_beta_contract: term -> bool val could_eta_contract: term -> bool val used_free: string -> term -> bool
exception USED_FREE ofstring * term val dest_abs_fresh: string -> term -> (string * typ) * term val dest_abs_global: term -> (string * typ) * term val dummy_pattern: typ -> term val dummy: term val dummy_prop: term val is_dummy_pattern: term -> bool val free_dummy_patterns: term -> Name.context -> term * Name.context val no_dummy_patterns: term -> term val replace_dummy_patterns: term -> int -> term * int val show_dummy_patterns: term -> term val string_of_vname: indexname -> string val string_of_vname': indexname -> string end;
structure Term: TERM = struct
(*Indexnames can be quickly renamed by adding an offset to the integer part,
for resolution.*) type indexname = string * int;
(*Types are classified by sorts.*) type class = string; type sort = class list; type arity = string * sort list * sort;
(*The sorts attached to TFrees and TVars specify the sort of that variable.*) datatype typ = Typeofstring * typ list
| TFree ofstring * sort
| TVar of indexname * sort;
(*Terms. Bound variables are indicated by depth number. Freevariables,(scheme)variablesandconstantshavenames. Antermis"closed"ifeveryboundvariableoflevel"lev" isenclosedbyatleast"lev"abstractions.
Itispossibletocreatemeaninglesstermscontaininglooseboundvars
or type mismatches. But such terms are not allowed in rules. *)
datatype term = Constofstring * typ
| Free ofstring * typ
| Var of indexname * typ
| Bound of int
| Abs ofstring*typ*term
| op $ of term*term;
(*Errors involving type mismatches*)
exception TYPEofstring * typ list * term list;
(*Errors errors involving terms*)
exception TERM ofstring * term list;
(*dummies for type-inference etc.*) val dummyS = [""]; val dummyT = Type ("dummy", []);
fun no_dummyT typ = let fun check (T as Type ("dummy", _)) = raiseTYPE ("Illegal occurrence of '_' dummy type", [T], [])
| check (Type (_, Ts)) = List.app check Ts
| check _ = (); in check typ; typ end;
fun S --> T = Type("fun",[S,T]);
(*handy for multiple args: [T1,...,Tn]--->T gives T1-->(T2--> ... -->T)*) val op ---> = Library.foldr (op -->);
fun eq_Const_name (Const (a, _), Const (b, _)) = a = b
| eq_Const_name _ = false;
(** Destructors **)
fun dest_Const (Const x) = x
| dest_Const t = raise TERM("dest_Const", [t]);
val dest_Const_name = #1 o dest_Const; val dest_Const_type = #2 o dest_Const;
fun dest_Free (Free x) = x
| dest_Free t = raise TERM("dest_Free", [t]);
fun dest_Var (Var x) = x
| dest_Var t = raise TERM("dest_Var", [t]);
fun dest_comb (t1 $ t2) = (t1, t2)
| dest_comb t = raise TERM("dest_comb", [t]);
fun domain_type (Type ("fun", [T, _])) = T;
fun range_type (Type ("fun", [_, U])) = U;
fun dest_funT (Type ("fun", [T, U])) = (T, U)
| dest_funT T = raiseTYPE ("dest_funT", [T], []);
(*maps [T1,...,Tn]--->T to the list [T1,T2,...,Tn]*) fun binder_types (Type ("fun", [T, U])) = T :: binder_types U
| binder_types _ = [];
(*maps [T1,...,Tn]--->T to T*) fun body_type (Type ("fun", [_, U])) = body_type U
| body_type T = T;
(*maps [T1,...,Tn]--->T to ([T1,T2,...,Tn], T)*) fun strip_type T = (binder_types T, body_type T);
(*Compute the type of the term, checking that combinations are well-typed
Ts = [T0,T1,...] holds types of bound variables 0, 1, ...*) fun type_of1 (Ts, Const (_,T)) = T
| type_of1 (Ts, Free (_,T)) = T
| type_of1 (Ts, Bound i) = (nth Ts i handle General.Subscript => raiseTYPE("type_of: bound variable", [], [Bound i]))
| type_of1 (Ts, Var (_,T)) = T
| type_of1 (Ts, Abs (_,T,body)) = T --> type_of1(T::Ts, body)
| type_of1 (Ts, f$u) = letval U = type_of1(Ts,u) and T = type_of1(Ts,f) incase T of Type("fun",[T1,T2]) => if T1=U then T2 elseraiseTYPE
("type_of: type mismatch in application", [T1,U], [f$u])
| _ => raiseTYPE
("type_of: function type is expected in application",
[T,U], [f$u]) end;
fun type_of t : typ = type_of1 ([],t);
(*Determine the type of a term, with minimal checking*)
local
fun fastype_of_term Ts (Abs (_, T, t)) = T --> fastype_of_term (T :: Ts) t
| fastype_of_term Ts (t $ _) = range_type_of Ts t
| fastype_of_term Ts a = fastype_of_atom Ts a and fastype_of_atom _ (Const (_, T)) = T
| fastype_of_atom _ (Free (_, T)) = T
| fastype_of_atom _ (Var (_, T)) = T
| fastype_of_atom Ts (Bound i) = fastype_of_bound Ts i and fastype_of_bound (T :: Ts) i = if i = 0then T else fastype_of_bound Ts (i - 1)
| fastype_of_bound [] i = raise TERM ("fastype_of: Bound", [Bound i]) and range_type_of Ts (Abs (_, T, u)) = fastype_of_term (T :: Ts) u
| range_type_of Ts (t $ u) = range_type_ofT (t $ u) (range_type_of Ts t)
| range_type_of Ts a = range_type_ofT a (fastype_of_atom Ts a) and range_type_ofT _ (Type ("fun", [_, T])) = T
| range_type_ofT t _ = raise TERM ("fastype_of: expected function type", [t]);
in
val fastype_of1 = uncurry fastype_of_term; val fastype_of = fastype_of_term [];
end;
(*Determine the argument type of a function*) fun argument_type_of tm k = let fun argT i (Type ("fun", [T, U])) = if i = 0then T else argT (i - 1) U
| argT _ T = raiseTYPE ("argument_type_of", [T], []);
fun arg 0 _ (Abs (_, T, _)) = T
| arg i Ts (Abs (_, T, t)) = arg (i - 1) (T :: Ts) t
| arg i Ts (t $ _) = arg (i + 1) Ts t
| arg i Ts a = argT i (fastype_of1 (Ts, a)); in arg k [] tm end;
fun abs (x, T) t = Abs (x, T, t);
fun strip_abs (Abs (a, T, t)) = strip_abs t |>> cons (a, T)
| strip_abs t = ([], t);
fun strip_abs_body (Abs (_, _, t)) = strip_abs_body t
| strip_abs_body t = t;
fun strip_abs_vars (Abs (a, T, t)) = strip_abs_vars t |> cons (a, T)
| strip_abs_vars _ = [];
fun strip_qnt_body qnt = let fun strip (tm as Const (c, _) $ Abs (_, _, t)) = if c = qnt then strip t else tm
| strip t = t; in strip end;
fun strip_qnt_vars qnt = let fun strip (Const (c, _) $ Abs (a, T, t)) = if c = qnt then (a, T) :: strip t else []
| strip _ = []; in strip end;
(*maps (f, [t1,...,tn]) to f(t1,...,tn)*) val list_comb : term * term list -> term = Library.foldl (op $);
(*maps f(t1,...,tn) to (f, [t1,...,tn]) ; naturally tail-recursive*) fun strip_comb tm = let fun strip (f $ t, ts) = strip (f, t :: ts)
| strip res = res; in strip (tm, []) end;
val args_of = let fun args (f $ t) ts = args f (t :: ts)
| args _ ts = ts; in build o args end;
(*maps f(t1,...,tn) to f , which is never a combination*) fun head_of (f $ _) = head_of f
| head_of t = t;
(*number of atoms and abstractions in a term*) fun size_of_term tm = let fun add_size (t $ u) n = add_size t (add_size u n)
| add_size (Abs (_ ,_, t)) n = add_size t (n + 1)
| add_size _ n = n + 1; in add_size tm 0end;
(*number of atoms and constructors in a type*) fun size_of_typ ty = let fun add_size (Type (_, tys)) n = fold add_size tys (n + 1)
| add_size _ n = n + 1; in add_size ty 0end;
(* map types and terms *)
fun map_atyps_same f = let fun typ (Type (a, Ts)) = Type (a, Same.map typ Ts)
| typ T = f T; in typ end;
fun map_aterms_same f = let fun term (Abs (x, T, t)) = Abs (x, T, term t)
| term (t $ u) =
(term t $ Same.commit term u handle Same.SAME => t $ term u)
| term a = f a; in term end;
fun map_types_same f = let fun term (Const (c, T)) = Const (c, f T)
| term (Free (x, T)) = Free (x, f T)
| term (Var (xi, T)) = Var (xi, f T)
| term (Bound _) = raise Same.SAME
| term (Abs (x, T, t)) =
(Abs (x, f T, Same.commit term t) handle Same.SAME => Abs (x, T, term t))
| term (t $ u) =
(term t $ Same.commit term u handle Same.SAME => t $ term u); in term end;
val map_atyps = Same.commit o map_atyps_same; val map_aterms = Same.commit o map_aterms_same; val map_types = Same.commit o map_types_same;
fun map_type_tvar f = map_atyps (fn TVar x => f x | _ => raise Same.SAME); fun map_type_tfree f = map_atyps (fn TFree x => f x | _ => raise Same.SAME);
(* fold types and terms *)
fun fold_atyps f (Type (_, Ts)) = fold (fold_atyps f) Ts
| fold_atyps f T = f T;
fun fold_atyps_sorts f =
fold_atyps (fn T as TFree (_, S) => f (T, S) | T as TVar (_, S) => f (T, S));
fun fold_aterms f (t $ u) = fold_aterms f t #> fold_aterms f u
| fold_aterms f (Abs (_, _, t)) = fold_aterms f t
| fold_aterms f a = f a;
fun fold_term_types f (t as Const (_, T)) = f t T
| fold_term_types f (t as Free (_, T)) = f t T
| fold_term_types f (t as Var (_, T)) = f t T
| fold_term_types f (Bound _) = I
| fold_term_types f (t as Abs (_, T, b)) = f t T #> fold_term_types f b
| fold_term_types f (t $ u) = fold_term_types f t #> fold_term_types f u;
fun fold_types f = fold_term_types (K f);
fun replace_types (Const (c, _)) (T :: Ts) = (Const (c, T), Ts)
| replace_types (Free (x, _)) (T :: Ts) = (Free (x, T), Ts)
| replace_types (Var (xi, _)) (T :: Ts) = (Var (xi, T), Ts)
| replace_types (Bound i) Ts = (Bound i, Ts)
| replace_types (Abs (x, _, b)) (T :: Ts) = letval (b', Ts') = replace_types b Ts in (Abs (x, T, b'), Ts') end
| replace_types (t $ u) Ts = let val (t', Ts') = replace_types t Ts; val (u', Ts'') = replace_types u Ts'; in (t' $ u', Ts'') end;
fun burrow_types f ts = let val Ts = rev ((fold o fold_types) cons ts []); val Ts' = f Ts; val (ts', []) = fold_map replace_types ts Ts'; in ts' end;
(*collect variables*) val add_tvar_namesT = fold_atyps (fn TVar (xi, _) => insert (op =) xi | _ => I); val add_tvar_names = fold_types add_tvar_namesT; val add_tvarsT = fold_atyps (fn TVar v => insert (op =) v | _ => I); val add_tvars = fold_types add_tvarsT; val add_var_names = fold_aterms (fn Var (xi, _) => insert (op =) xi | _ => I); val add_vars = fold_aterms (fn Var v => insert (op =) v | _ => I); val add_tfree_namesT = fold_atyps (fn TFree (a, _) => insert (op =) a | _ => I); val add_tfree_names = fold_types add_tfree_namesT; val add_tfreesT = fold_atyps (fn TFree v => insert (op =) v | _ => I); val add_tfrees = fold_types add_tfreesT; val add_free_names = fold_aterms (fn Free (x, _) => insert (op =) x | _ => I); val add_frees = fold_aterms (fn Free v => insert (op =) v | _ => I); val add_const_names = fold_aterms (fn Const (c, _) => insert (op =) c | _ => I); val add_consts = fold_aterms (fn Const c => insert (op =) c | _ => I);
(*renaming variables*) val declare_tfree_namesT = fold_atyps (fn TFree (a, _) => Name.declare a | _ => I); val declare_tfree_names = fold_types declare_tfree_namesT; fun declare_tvar_namesT pred = fold_atyps (fn TVar ((a, i), _) => pred i ? Name.declare a | _ => I); val declare_tvar_names = fold_types o declare_tvar_namesT; val declare_free_names = fold_aterms (fn Free (x, _) => Name.declare x | _ => I); fun declare_var_names pred = fold_aterms (fn Var ((x, i), _) => pred i ? Name.declare x | _ => I); fun variant_bounds t = Name.variant_names_build (declare_free_names t);
(*extra type variables in a term, not covered by its type*) fun hidden_polymorphism t = let val T = fastype_of t; val tvarsT = add_tvarsT T []; val extra_tvars = fold_types (fold_atyps
(fn TVar v => if member (op =) tvarsT v then I else insert (op =) v | _ => I)) t []; in extra_tvars end;
(* sorts *)
fun smash_sortsT_same S' =
map_atyps_same
(fn TFree (x, S) => if S = S' then raise Same.SAME else TFree (x, S')
| TVar (xi, S) => if S = S' then raise Same.SAME else TVar (xi, S'));
val smash_sortsT = Same.commit o smash_sortsT_same; val smash_sorts = map_types o smash_sortsT_same;
val strip_sortsT_same = smash_sortsT_same []; val strip_sortsT = Same.commit strip_sortsT_same; val strip_sorts = map_types strip_sortsT_same;
(** Comparing terms **)
(* variables *)
fun eq_ix ((x, i): indexname, (y, j)) = i = j andalso x = y;
fun eq_tvar ((xi, S: sort), (xi', S')) = eq_ix (xi, xi') andalso S = S'; fun eq_var ((xi, T: typ), (xi', T')) = eq_ix (xi, xi') andalso T = T';
fun aconv_untyped (tm1, tm2) =
pointer_eq (tm1, tm2) orelse
(case (tm1, tm2) of
(t1 $ u1, t2 $ u2) => aconv_untyped (t1, t2) andalso aconv_untyped (u1, u2)
| (Abs (_, _, t1), Abs (_, _, t2)) => aconv_untyped (t1, t2)
| (Const (a, _), Const (b, _)) => a = b
| (Free (x, _), Free (y, _)) => x = y
| (Var (xi, _), Var (yj, _)) => xi = yj
| (Bound i, Bound j) => i = j
| _ => false);
(*A fast unification filter: true unless the two terms cannot be unified.
Terms must be NORMAL. Treats all Vars as distinct. *) fun could_unify (t, u) = let fun matchrands (f $ t) (g $ u) = could_unify (t, u) andalso matchrands f g
| matchrands _ _ = true; in case (head_of t, head_of u) of
(_, Var _) => true
| (Var _, _) => true
| (Const (a, _), Const (b, _)) => a = b andalso matchrands t u
| (Free (a, _), Free (b, _)) => a = b andalso matchrands t u
| (Bound i, Bound j) => i = j andalso matchrands t u
| (Abs _, _) => true(*because of possible eta equality*)
| (_, Abs _) => true
| _ => false end;
(** Connectives of higher order logic **)
fun aT S = TFree (Name.aT, S);
fun itselfT ty = Type ("itself", [ty]); val a_itselfT = itselfT (TFree (Name.aT, []));
val propT : typ = Type ("prop",[]);
(*maps \<And>x1...xn. t to t*) fun strip_all_body (Const ("Pure.all", _) $ Abs (_, _, t)) = strip_all_body t
| strip_all_body t = t;
(*maps \<And>x1...xn. t to [x1, ..., xn]*) fun strip_all_vars (Const ("Pure.all", _) $ Abs (a, T, t)) = (a, T) :: strip_all_vars t
| strip_all_vars t = [];
(*increments a term's non-local bound variables requiredwhenmovingatermwithinabstractions incisincrementforboundvariables
lev is level at which a bound variable is considered 'loose'*) fun incr_bv_same inc = if inc = 0then fn _ => Same.same else let fun term lev (Bound i) = if i >= lev then Bound (i + inc) elseraise Same.SAME
| term lev (Abs (a, T, t)) = Abs (a, T, term (lev + 1) t)
| term lev (t $ u) =
(term lev t $ Same.commit (term lev) u handle Same.SAME => t $ term lev u)
| term _ _ = raise Same.SAME; in term end;
fun incr_bv inc lev = Same.commit (incr_bv_same inc lev);
fun incr_boundvars inc = incr_bv inc 0;
(*Scan a pair of terms; while they are similar, accumulate corresponding bound vars*) fun match_bvs (Abs (x, _, s), Abs (y, _, t)) =
(x <> "" andalso y <> "") ? cons (x, y) #> match_bvs (s, t)
| match_bvs (f $ s, g $ t) = match_bvs (s, t) #> match_bvs (f, g)
| match_bvs _ = I;
(* strip abstractions created by parameters *) val match_bvars = apply2 strip_abs_body #> match_bvs;
fun map_abs_vars_same rename = let fun term (Abs (x, T, t)) = letval y = rename x inif x = y then Abs (x, T, term t) else Abs (y, T, Same.commit term t) end
| term (t $ u) = (term t $ Same.commit term u handle Same.SAME => t $ term u)
| term _ = raise Same.SAME; in term end;
fun map_abs_vars rename = Same.commit (map_abs_vars_same rename);
fun rename_abs pat obj t = let val renaming = Symtab.make_distinct (match_bvs (pat, obj) []); fun rename x = perhaps (Symtab.lookup renaming) x; inif Symtab.forall (op =) renaming then NONE else Same.catch (map_abs_vars_same rename) t end;
(*Accumulate all 'loose' bound vars referring to level 'lev' or beyond.
(Bound 0) is loose at level 0 *) fun add_loose_bnos (Bound i, lev, js) = if i<lev then js else insert (op =) (i - lev) js
| add_loose_bnos (Abs (_,_,t), lev, js) = add_loose_bnos (t, lev+1, js)
| add_loose_bnos (f$t, lev, js) =
add_loose_bnos (f, lev, add_loose_bnos (t, lev, js))
| add_loose_bnos (_, _, js) = js;
fun loose_bnos t = add_loose_bnos (t, 0, []);
(* loose_bvar(t,k) iff t contains a 'loose' bound variable referring to
level k or beyond. *) fun loose_bvar(Bound i,k) = i >= k
| loose_bvar(f$t, k) = loose_bvar(f,k) orelse loose_bvar(t,k)
| loose_bvar(Abs(_,_,t),k) = loose_bvar(t,k+1)
| loose_bvar _ = false;
fun loose_bvar1(Bound i,k) = i = k
| loose_bvar1(f$t, k) = loose_bvar1(f,k) orelse loose_bvar1(t,k)
| loose_bvar1(Abs(_,_,t),k) = loose_bvar1(t,k+1)
| loose_bvar1 _ = false;
fun is_open t = loose_bvar (t, 0); fun is_dependent t = loose_bvar1 (t, 0);
(*Substitute arguments for loose bound variables. Beta-reductionofarg(n-1)...arg0intotreplacing(Boundi)with(argi). Notethatfor((\<lambda>xy.c)ab),theboundvarsincarex=1andy=0 andtheappropriatecallissubst_bounds([b,a],c). Looseboundvariables>=narereducedby"n"to compensateforthedisappearanceoflambdas.
*) fun subst_bounds_same args = if null args then fn _ => Same.same else let val n = length args; fun term lev (Bound i) = if i < lev thenraise Same.SAME (*var is locally bound*) elseif i - lev < n then incr_boundvars lev (nth args (i - lev)) else Bound (i - n) (*loose: change it*)
| term lev (Abs (a, T, t)) = Abs (a, T, term (lev + 1) t)
| term lev (t $ u) =
(term lev t $ Same.commit (term lev) u handle Same.SAME => t $ term lev u)
| term _ _ = raise Same.SAME; in term end;
fun subst_bounds (args: term list, body) : term = if null args then body else Same.commit (subst_bounds_same args 0) body;
(*Special case: one argument*) fun subst_bound (arg, body) : term = let fun term lev (Bound i) = if i < lev thenraise Same.SAME (*var is locally bound*) elseif i = lev then incr_boundvars lev arg else Bound (i - 1) (*loose: change it*)
| term lev (Abs (a, T, t)) = Abs (a, T, term (lev + 1) t)
| term lev (t $ u) =
(term lev t $ Same.commit (term lev) u handle Same.SAME => t $ term lev u)
| term _ _ = raise Same.SAME; in Same.commit (term 0) body end;
(*beta-reduce if possible, else form application*) fun betapply (Abs(_,_,t), u) = subst_bound (u,t)
| betapply (f,u) = f$u;
val betapplys = Library.foldl betapply;
(*unfolding abstractions with substitution
of bound variables and implicit eta-expansion*) fun strip_abs_eta k t = let val used = Name.build_context (fold_aterms declare_free_names t); fun strip_abs t (0, used) = (([], t), (0, used))
| strip_abs (Abs (v, T, t)) (k, used) = let val (v', used') = Name.variant v used; val t' = subst_bound (Free (v', T), t); val ((vs, t''), (k', used'')) = strip_abs t' (k - 1, used'); in (((v', T) :: vs, t''), (k', used'')) end
| strip_abs t (k, used) = (([], t), (k, used)); fun expand_eta [] t _ = ([], t)
| expand_eta (T::Ts) t used = let val (v, used') = Name.variant "" used; val (vs, t') = expand_eta Ts (t $ Free (v, T)) used'; in ((v, T) :: vs, t') end; val ((vs1, t'), (k', used')) = strip_abs t (k, used); val Ts = fst (chop k' (binder_types (fastype_of t'))); val (vs2, t'') = expand_eta Ts t' used'; in (vs1 @ vs2, t'') end;
(*Substitute new for free occurrences of old in a term*) fun subst_free [] = I
| subst_free pairs = letfun substf u = case AList.lookup (op aconv) pairs u of
SOME u' => u'
| NONE => (case u of Abs(a,T,t) => Abs(a, T, substf t)
| t$u' => substf t $ substf u'
| _ => u) in substf end;
(*Abstraction of the term "body" over its occurrences of v, whichmustcontainnolooseboundvariables.
The resulting term is ready to become the body of an Abs.*) fun abstract_over (v, body) = let fun term lev tm = if v aconv tm then Bound lev else
(case tm of
Abs (a, T, t) => Abs (a, T, term (lev + 1) t)
| t $ u =>
(term lev t $ Same.commit (term lev) u handle Same.SAME => t $ term lev u)
| _ => raise Same.SAME); in Same.commit (term 0) body end;
fun term_name (Const (x, _)) = Long_Name.base_name x
| term_name (Free (x, _)) = x
| term_name (Var ((x, _), _)) = x
| term_name _ = Name.uu;
fun dependent_lambda_name (x, v) t = letval t' = abstract_over (v, t) inif is_dependent t' then Abs (if x = "" then term_name v else x, fastype_of v, t') else t end;
fun lambda_name (x, v) t =
Abs (if x = ""then term_name v else x, fastype_of v, abstract_over (v, t));
fun lambda v t = lambda_name ("", v) t;
fun absfree (a, T) body = Abs (a, T, abstract_over (Free (a, T), body)); fun absdummy T body = Abs (Name.uu_, T, body);
(*Replace the ATOMIC term ti by ui; inst = [(t1,u1), ..., (tn,un)].
A simultaneous substitution: [ (a,b), (b,a) ] swaps a and b. *) fun subst_atomic [] tm = tm
| subst_atomic inst tm = let fun subst (Abs (a, T, body)) = Abs (a, T, subst body)
| subst (t $ u) = subst t $ subst u
| subst t = the_default t (AList.lookup (op aconv) inst t); in subst tm end;
(*Replace the ATOMIC type Ti by Ui; inst = [(T1,U1), ..., (Tn,Un)].*) fun typ_subst_atomic [] ty = ty
| typ_subst_atomic inst ty = let fun subst (Type (a, Ts)) = Type (a, map subst Ts)
| subst T = the_default T (AList.lookup (op = : typ * typ -> bool) inst T); in subst ty end;
fun typ_subst_TVars [] ty = ty
| typ_subst_TVars inst ty = let fun subst (Type (a, Ts)) = Type (a, map subst Ts)
| subst (T as TVar (xi, _)) = the_default T (AList.lookup (op =) inst xi)
| subst T = T; in subst ty end;
fun subst_Vars [] tm = tm
| subst_Vars inst tm = let fun subst (t as Var (xi, _)) = the_default t (AList.lookup (op =) inst xi)
| subst (Abs (a, T, t)) = Abs (a, T, subst t)
| subst (t $ u) = subst t $ subst u
| subst t = t; in subst tm end;
fun subst_vars ([], []) tm = tm
| subst_vars ([], inst) tm = subst_Vars inst tm
| subst_vars (instT, inst) tm = let fun subst (Const (a, T)) = Const (a, typ_subst_TVars instT T)
| subst (Free (a, T)) = Free (a, typ_subst_TVars instT T)
| subst (Var (xi, T)) =
(case AList.lookup (op =) inst xi of
NONE => Var (xi, typ_subst_TVars instT T)
| SOME t => t)
| subst (t as Bound _) = t
| subst (Abs (a, T, t)) = Abs (a, typ_subst_TVars instT T, subst t)
| subst (t $ u) = subst t $ subst u; in subst tm end;
fun close_schematic_term t = let val extra_types = map (fn v => Const ("Pure.type", itselfT (TVar v))) (hidden_polymorphism t); val extra_terms = map Var (add_vars t []); in fold lambda (extra_terms @ extra_types) t end;
(** Identifying first-order terms **)
(*Differs from proofterm/is_fun in its treatment of TVar*) fun is_funtype (Type ("fun", [_, _])) = true
| is_funtype _ = false;
(*Argument Ts is a reverse list of binder types, needed if term t contains Bound vars*) fun has_not_funtype Ts t = not (is_funtype (fastype_of1 (Ts, t)));
(*First order means in all terms of the form f(t1,...,tn) no argument has a functiontype.Thesuppliedquantifiersareexcluded:theirargumentalways
has a function type through a recursive call into its body.*) fun is_first_order quants = letfun first_order1 Ts (Abs (_,T,body)) = first_order1 (T::Ts) body
| first_order1 Ts (Const(q,_) $ Abs(a,T,body)) =
member (op =) quants q andalso (*it is a known quantifier*) not (is_funtype T) andalso first_order1 (T::Ts) body
| first_order1 Ts t = case strip_comb t of
(Var _, ts) => forall (first_order1 Ts andf has_not_funtype Ts) ts
| (Free _, ts) => forall (first_order1 Ts andf has_not_funtype Ts) ts
| (Const _, ts) => forall (first_order1 Ts andf has_not_funtype Ts) ts
| (Bound _, ts) => forall (first_order1 Ts andf has_not_funtype Ts) ts
| (Abs _, ts) => false(*not in beta-normal form*)
| _ => error "first_order: unexpected case" in first_order1 [] end;
(* maximum index of typs and terms *)
fun maxidx_typ (TVar ((_, j), _)) i = Int.max (i, j)
| maxidx_typ (Type (_, Ts)) i = maxidx_typs Ts i
| maxidx_typ (TFree _) i = i and maxidx_typs [] i = i
| maxidx_typs (T :: Ts) i = maxidx_typs Ts (maxidx_typ T i);
fun maxidx_term (Var ((_, j), T)) i = maxidx_typ T (Int.max (i, j))
| maxidx_term (Const (_, T)) i = maxidx_typ T i
| maxidx_term (Free (_, T)) i = maxidx_typ T i
| maxidx_term (Bound _) i = i
| maxidx_term (Abs (_, T, t)) i = maxidx_term t (maxidx_typ T i)
| maxidx_term (t $ u) i = maxidx_term u (maxidx_term t i);
fun maxidx_of_typ T = maxidx_typ T ~1; fun maxidx_of_typs Ts = maxidx_typs Ts ~1; fun maxidx_of_term t = maxidx_term t ~1;
(** misc syntax operations **)
(* substructure *)
fun fold_subtypes f = let fun iter ty =
(case ty ofType (_, Ts) => f ty #> fold iter Ts | _ => f ty); in iter end;
fun exists_subtype P = let fun ex ty = P ty orelse
(case ty ofType (_, Ts) => exists ex Ts | _ => false); in ex end;
fun exists_type P = let fun ex (Const (_, T)) = P T
| ex (Free (_, T)) = P T
| ex (Var (_, T)) = P T
| ex (Bound _) = false
| ex (Abs (_, T, t)) = P T orelse ex t
| ex (t $ u) = ex t orelse ex u; in ex end;
fun exists_subterm P = let fun ex tm = P tm orelse
(case tm of
t $ u => ex t orelse ex u
| Abs (_, _, t) => ex t
| _ => false); in ex end;
fun exists_Const P = exists_subterm (fn Const c => P c | _ => false);
fun is_schematic t =
exists_subterm is_Var t orelse
(exists_type o exists_subtype) is_TVar t;
(* contraction *)
fun could_beta_contract (Abs _ $ _) = true
| could_beta_contract (t $ u) = could_beta_contract t orelse could_beta_contract u
| could_beta_contract (Abs (_, _, b)) = could_beta_contract b
| could_beta_contract _ = false;
fun could_eta_contract (Abs (_, _, _ $ Bound 0)) = true
| could_eta_contract (Abs (_, _, b)) = could_eta_contract b
| could_eta_contract (t $ u) = could_eta_contract t orelse could_eta_contract u
| could_eta_contract _ = false;
(* dest abstraction *)
(*ASSUMPTION: x is fresh wrt. the current context, but the check
of used_free merely guards against gross mistakes*)
fun used_free x = let fun used (Free (y, _)) = (x = y)
| used (t $ u) = used t orelse used u
| used (Abs (_, _, t)) = used t
| used _ = false; in used end;
exception USED_FREE ofstring * term;
fun subst_abs v b = (v, subst_bound (Free v, b));
fun dest_abs_fresh x t =
(case t of
Abs (_, T, b) => if used_free x b thenraise USED_FREE (x, t) else subst_abs (x, T) b
| _ => raise TERM ("dest_abs", [t]));
fun dest_abs_global t =
(case t of
Abs (x, T, b) => if used_free x b then let val used = Name.build_context (declare_free_names b); val x' = #1 (Name.variant x used); in subst_abs (x', T) b end else subst_abs (x, T) b
| _ => raise TERM ("dest_abs", [t]));
(* dummy patterns *)
fun dummy_pattern T = Const ("Pure.dummy_pattern", T); val dummy = dummy_pattern dummyT; val dummy_prop = dummy_pattern propT;
fun no_dummy_patterns tm = ifnot (fold_aterms (fn t => fn b => b orelse is_dummy_pattern t) tm false) then tm elseraise TERM ("Illegal occurrence of '_' dummy pattern", [tm]);
fun free_dummy_patterns (Const ("Pure.dummy_pattern", T)) used = letval [x] = Name.invent used Name.uu 1 in (Free (Name.internal x, T), Name.declare x used) end
| free_dummy_patterns (Abs (x, T, b)) used = letval (b', used') = free_dummy_patterns b used in (Abs (x, T, b'), used') end
| free_dummy_patterns (t $ u) used = let val (t', used') = free_dummy_patterns t used; val (u', used'') = free_dummy_patterns u used'; in (t' $ u', used'') end
| free_dummy_patterns a used = (a, used);
fun replace_dummy Ts (Const ("Pure.dummy_pattern", T)) i =
(list_comb (Var (("_dummy_", i), Ts ---> T), map_range Bound (length Ts)), i + 1)
| replace_dummy Ts (Abs (x, T, t)) i = letval (t', i') = replace_dummy (T :: Ts) t i in (Abs (x, T, t'), i') end
| replace_dummy Ts (t $ u) i = let val (t', i') = replace_dummy Ts t i; val (u', i'') = replace_dummy Ts u i'; in (t' $ u', i'') end
| replace_dummy _ a i = (a, i);
val replace_dummy_patterns = replace_dummy [];
fun show_dummy_patterns (Var (("_dummy_", _), T)) = dummy_pattern T
| show_dummy_patterns (t $ u) = show_dummy_patterns t $ show_dummy_patterns u
| show_dummy_patterns (Abs (x, T, t)) = Abs (x, T, show_dummy_patterns t)
| show_dummy_patterns a = a;
(* display variables *)
fun string_of_vname (x, i) = let val idx = string_of_int i; val dot =
(case rev (Symbol.explode x) of
_ :: "\<^sub>" :: _ => false
| c :: _ => Symbol.is_digit c
| _ => true); in if dot then"?" ^ x ^ "." ^ idx elseif i <> 0then"?" ^ x ^ idx else"?" ^ x end;
fun string_of_vname' (x, ~1) = x
| string_of_vname' xi = string_of_vname xi;
end;
structure Basic_Term: BASIC_TERM = Term; open Basic_Term;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.