package lambdapi
Proof assistant for the λΠ-calculus modulo rewriting
Install
dune-project
Dependency
Authors
Maintainers
Sources
lambdapi-3.0.0.tbz
sha256=1066aed2618fd8e6a400c5147dbf55ea977ce8d3fe2e518ac6785c6775a1b8be
sha512=f7f499626aba92e070ae69581299a58525973fdbfd04a160ed3ac89209fb6cbe307b816d0b23e1b75bc83467ce8b4b0530c6f9816eaf58f7a07fde65a450106c
doc/src/lambdapi.core/libTerm.ml.html
Source file libTerm.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
(** Basic operations on terms. *) open Term open Lplib open Extra (** [is_kind t] tells whether [t] is of the form Π x1, .., Π xn, TYPE. *) let rec is_kind : term -> bool = fun t -> match unfold t with | Type -> true | Prod(_,b) -> is_kind (subst b mk_Kind) | _ -> false (** [to_var t] returns [x] if [t] is of the form [Vari x] and fails otherwise. *) let to_var : term -> var = fun t -> match t with Vari(x) -> x | _ -> assert false (** {b NOTE} the [Array.map to_var] function is useful when working with multiple binders. For example, this is the case when manipulating pattern variables ([Patt] constructor) or metatavariables ([Meta] constructor). Remark that it is important for these constructors to hold an array of terms, rather than an array of variables: a variable can only be substituted when if it is injected in a term (using the [Vari] constructor). *) (** {b NOTE} the result of {!val:to_var} can generally NOT be precomputed. A first reason is that we cannot know in advance what variable identifier is going to arise when working under binders, for which fresh variables will often be generated. A second reason is that free variables should never be “marshaled” (e.g., by the {!module:Sign} module), as this would break the freshness invariant of new variables. *) (** Given a symbol [s], [remove_impl_args s ts] returns the non-implicit arguments of [s] among [ts]. *) let remove_impl_args : sym -> term list -> term list = fun s ts -> let rec remove bs ts = match (bs, ts) with | (true::bs , _::ts) -> remove bs ts | (false::bs, t::ts) -> t :: remove bs ts | (_ , _ ) -> ts in remove s.sym_impl ts (** [iter f t] applies the function [f] to every node of the term [t] with bound variables replaced by [Kind]. Note: [f] is called on already unfolded terms only. *) let iter : (term -> unit) -> term -> unit = fun action -> let rec iter t = let t = unfold t in action t; match t with | Bvar _ -> assert false | Wild | Plac _ | TRef(_) | Vari(_) | Type | Kind | Symb(_) -> () | Patt(_,_,ts) | Meta(_,ts) -> Array.iter iter ts | Prod(a,b) | Abst(a,b) -> iter a; iter (subst b mk_Kind) | Appl(t,u) -> iter t; iter u | LLet(a,t,u) -> iter a; iter t; iter (subst u mk_Kind) in iter (** [distinct_vars ctx ts] checks that the terms [ts] are distinct variables. If so, the variables are returned. *) let distinct_vars : ctxt -> term array -> var array option = fun ctx ts -> let exception Not_unique_var in let open Stdlib in let vars = ref VarSet.empty in let to_var t = match Ctxt.unfold ctx t with | Vari(x) -> if VarSet.mem x !vars then raise Not_unique_var; vars := VarSet.add x !vars; x | _ -> raise Not_unique_var in try Some (Array.map to_var ts) with Not_unique_var -> None (** If [ts] is not made of variables or function symbols prefixed by ['$'] only, then [nl_distinct_vars ts] returns [None]. Otherwise, it returns a pair [(vs, map)] where [vs] is an array of variables made of the linear variables of [ts] and fresh variables for the non-linear variables and the symbols prefixed by ['$'], and [map] records by which variable each linear symbol prefixed by ['$'] is replaced. The symbols prefixed by ['$'] are introduced by [infer.ml] which converts metavariables into fresh symbols, and those metavariables are introduced by [sr.ml] which replaces pattern variables by metavariables. *) let nl_distinct_vars : term array -> (var array * var StrMap.t) option = fun ts -> let exception Not_a_var in let open Stdlib in let vars = ref VarSet.empty (* variables already seen (linear or not) *) and nl_vars = ref VarSet.empty (* variables occurring more then once *) and patt_vars = ref StrMap.empty in (* map from pattern variables to actual variables *) let rec to_var t = match unfold t with | Vari(v) -> if VarSet.mem v !vars then nl_vars := VarSet.add v !nl_vars else vars := VarSet.add v !vars; v | Symb(f) when f.sym_name <> "" && f.sym_name.[0] = '$' -> (* Symbols replacing pattern variables are considered as variables. *) let v = try StrMap.find f.sym_name !patt_vars with Not_found -> let v = new_var f.sym_name in patt_vars := StrMap.add f.sym_name v !patt_vars; v in to_var (mk_Vari v) | _ -> raise Not_a_var in let replace_nl_var v = if VarSet.mem v !nl_vars then new_var "_" else v in try let vs = Array.map to_var ts in let vs = Array.map replace_nl_var vs in (* We remove non-linear variables from [!patt_vars] as well. *) let fn n v m = if VarSet.mem v !nl_vars then m else StrMap.add n v m in let map = StrMap.fold fn !patt_vars StrMap.empty in Some (vs, map) with Not_a_var -> None (** [sym_to_var m t] replaces in [t] every symbol [f] by a variable according to the map [map]. *) let sym_to_var : var StrMap.t -> term -> term = fun map -> let rec to_var t = match unfold t with | Symb f -> (try mk_Vari (StrMap.find f.sym_name map) with Not_found -> t) | Prod(a,b) -> mk_Prod (to_var a, to_var_binder b) | Abst(a,b) -> mk_Abst (to_var a, to_var_binder b) | LLet(a,t,u) -> mk_LLet (to_var a, to_var t, to_var_binder u) | Appl(a,b) -> mk_Appl(to_var a, to_var b) | Meta(m,ts) -> mk_Meta(m, Array.map to_var ts) | Patt _ -> assert false | TRef _ -> assert false | _ -> t and to_var_binder b = let (x,b) = unbind b in bind_var x (to_var b) in fun t -> if StrMap.is_empty map then t else to_var t (** [eq_alpha a b] tests the equality modulo alpha of [a] and [b]. *) let rec eq_alpha a b = match unfold a, unfold b with | Vari x, Vari y -> Term.eq_vars x y | Type, Type | Kind, Kind -> true | Symb s1, Symb s2 -> s1==s2 | Prod(a1,b1), Prod(a2,b2) | Abst(a1,b1), Abst(a2,b2) -> eq_alpha a1 a2 && let _,b1,b2 = Term.unbind2 b1 b2 in eq_alpha b1 b2 | Appl(a1,b1), Appl(a2,b2) -> eq_alpha a1 a2 && eq_alpha b1 b2 | Meta(m1,a1), Meta(m2,a2) -> m1 == m2 && Array.for_all2 eq_alpha a1 a2 | LLet(a1,t1,u1), LLet(a2,t2,u2) -> eq_alpha a1 a2 && eq_alpha t1 t2 && let _,u1,u2 = Term.unbind2 u1 u2 in eq_alpha u1 u2 | Patt(Some i,_,ts), Patt(Some j,_,us) -> i=j && Array.for_all2 eq_alpha ts us | Patt(None,_,_), _ | _, Patt(None,_,_) -> assert false | TRef _, _| _, TRef _ -> assert false | _ -> false (** [fold id t a] returns term binder [b] with binder name [id] such that [subst b t ≡ a]. *) let fold (x:var) (t:term): term -> term = let rec aux u = if eq_alpha t u then mk_Vari x else match unfold u with | Appl(a,b) -> mk_Appl(aux a, aux b) | Abst(a,b) -> let x,b = Term.unbind b in mk_Abst(aux a, Term.bind_var x b) | Prod(a,b) -> let x,b = Term.unbind b in mk_Prod(aux a, Term.bind_var x b) | LLet(a,d,b) -> let x,b = Term.unbind b in mk_LLet(aux a, aux d, Term.bind_var x b) | Meta(m,us) -> mk_Meta(m,Array.map aux us) | _ -> u in aux (** Free variables of a term. *) let rec free_vars (t:term): VarSet.t = match unfold t with | Vari x -> VarSet.add x VarSet.empty | Appl(u,v) -> VarSet.union (free_vars u) (free_vars v) | Abst(a,b) | Prod(a,b) -> VarSet.union (free_vars a) (let x,b = unbind b in VarSet.remove x (free_vars b)) | LLet(a,t,b) -> VarSet.union (free_vars a) (VarSet.union (free_vars t) (let x,b = unbind b in VarSet.remove x (free_vars b))) | Meta(_,ts) -> Array.fold_right (fun t acc -> VarSet.union acc (free_vars t)) ts VarSet.empty | _ -> VarSet.empty
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>