Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file libTerm.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175(** Basic operations on terms. *)openTermopenLplib.Extra(** [to_tvar t] returns [x] if [t] is of the form [Vari x] and fails
otherwise. *)letto_tvar:term->tvar=funt->matchtwithVari(x)->x|_->assertfalse(** {b NOTE} the [Array.map to_tvar] 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_tvar} 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]. *)letremove_impl_args:sym->termlist->termlist=funsts->letrecremovebsts=match(bs,ts)with|(true::bs,_::ts)->removebsts|(false::bs,t::ts)->t::removebsts|(_,_)->tsinremoves.sym_implts(** [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. *)letiter:(term->unit)->term->unit=funaction->letrecitert=lett=unfoldtinactiont;matchtwith|Wild|Plac_|TRef(_)|Vari(_)|Type|Kind|Symb(_)->()|Patt(_,_,ts)|TEnv(_,ts)|Meta(_,ts)->Array.iteriterts|Prod(a,b)|Abst(a,b)->itera;iter(Bindlib.substbmk_Kind)|Appl(t,u)->itert;iteru|LLet(a,t,u)->itera;itert;iter(Bindlib.substumk_Kind)initer(** [unbind_name b s] is like [Bindlib.unbind b] but returns a valid variable
name when [b] binds no variable. The string [s] is the prefix of the
variable's name.*)letunbind_name:string->tbinder->tvar*term=funsb->ifBindlib.binder_occurbthenBindlib.unbindbelseletx=new_tvarsin(x,Bindlib.substb(mk_Varix))(** [unbind2_name b1 b2 s] is like [Bindlib.unbind2 b1 b2] but returns a valid
variable name when [b1] or [b2] binds no variable. The string [s] is the
prefix of the variable's name.*)letunbind2_name:string->tbinder->tbinder->tvar*term*term=funsb1b2->ifBindlib.binder_occurb1||Bindlib.binder_occurb2thenBindlib.unbind2b1b2elseletx=new_tvarsin(x,Bindlib.substb1(mk_Varix),Bindlib.substb2(mk_Varix))(** [distinct_vars ctx ts] checks that the terms [ts] are distinct
variables. If so, the variables are returned. *)letdistinct_vars:ctxt->termarray->tvararrayoption=functxts->letexceptionNot_unique_varinletopenStdlibinletvars=refVarSet.emptyinletto_vart=matchCtxt.unfoldctxtwith|Vari(x)->ifVarSet.memx!varsthenraiseNot_unique_var;vars:=VarSet.addx!vars;x|_->raiseNot_unique_varintrySome(Array.mapto_varts)withNot_unique_var->None(** If [ts] is not made of variables or function symbols prefixed by ['$']
only, then [nl_distinct_vars ctx 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.
Variables defined in [ctx] are unfolded.
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. *)letnl_distinct_vars:ctxt->termarray->(tvararray*tvarStrMap.t)option=functxts->letexceptionNot_a_varinletopenStdlibinletvars=refVarSet.empty(* variables already seen (linear or not) *)andnl_vars=refVarSet.empty(* variables occurring more then once *)andpatt_vars=refStrMap.emptyin(* map from pattern variables to actual Bindlib variables *)letrecto_vart=matchCtxt.unfoldctxtwith|Vari(v)->ifVarSet.memv!varsthennl_vars:=VarSet.addv!nl_varselsevars:=VarSet.addv!vars;v|Symb(f)whenf.sym_name<>""&&f.sym_name.[0]='$'->(* Symbols replacing pattern variables are considered as variables. *)letv=tryStrMap.findf.sym_name!patt_varswithNot_found->letv=new_tvarf.sym_nameinpatt_vars:=StrMap.addf.sym_namev!patt_vars;vinto_var(mk_Variv)|_->raiseNot_a_varinletreplace_nl_varv=ifVarSet.memv!nl_varsthennew_tvar"_"elsevintryletvs=Array.mapto_vartsinletvs=Array.mapreplace_nl_varvsin(* We remove non-linear variables from [!patt_vars] as well. *)letfnnvm=ifVarSet.memv!nl_varsthenmelseStrMap.addnvminletmap=StrMap.foldfn!patt_varsStrMap.emptyinSome(vs,map)withNot_a_var->None(** [sym_to_var m t] replaces in [t] every symbol [f] by a variable according
to the map [map]. *)letsym_to_var:tvarStrMap.t->term->term=funmap->letrecto_vart=matchunfoldtwith|Symbf->(trymk_Vari(StrMap.findf.sym_namemap)withNot_found->t)|Prod(a,b)->mk_Prod(to_vara,to_var_binderb)|Abst(a,b)->mk_Abst(to_vara,to_var_binderb)|LLet(a,t,u)->mk_LLet(to_vara,to_vart,to_var_binderu)|Appl(a,b)->mk_Appl(to_vara,to_varb)|Meta(m,ts)->mk_Meta(m,Array.mapto_varts)|Patt_->assertfalse|TEnv_->assertfalse|TRef_->assertfalse|_->tandto_var_binderb=let(x,b)=Bindlib.unbindbinBindlib.unbox(Bindlib.bind_varx(lift(to_varb)))infunt->ifStrMap.is_emptymapthentelseto_vart(** [term_of_rhs r] converts the RHS (right hand side) of the rewriting rule
[r] into a term. The bound higher-order variables of the original RHS are
substituted using [Patt] constructors. They are thus represented as their
LHS counterparts. This is a more convenient way of representing terms when
analysing confluence or termination. *)letterm_of_rhs:rule->term=funr->letfnix=let(name,arity)=(Bindlib.name_ofx,r.arities.(i))inletvars=Array.initarity(new_tvar_ind"x")inletp=_Patt(Somei)name(Array.map_Varivars)inTE_Some(Bindlib.unbox(Bindlib.bind_mvarvarsp))inBindlib.msubstr.rhs(Array.mapifnr.vars)