123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114(** Typing context. *)openTermopenLplibopenTimed(** [type_of x ctx] returns the type of [x] in the context [ctx] when it
appears in it, and
@raise [Not_found] otherwise. *)lettype_of:tvar->ctxt->term=funxctx->let(_,a,_)=List.find(fun(y,_,_)->Bindlib.eq_varsxy)ctxina(** [def_of x ctx] returns the definition of [x] in the context [ctx] if it
appears, and [None] otherwise *)letrecdef_of:tvar->ctxt->ctxt*termoption=funxc->matchcwith|[]->[],None|(y,_,d)::c->ifBindlib.eq_varsxythenc,delsedef_ofxc(** [mem x ctx] tells whether variable [x] is mapped in the context [ctx]. *)letmem:tvar->ctxt->bool=funx->List.exists(fun(y,_,_)->Bindlib.eq_varsxy)(** [to_prod ctx t] builds a product by abstracting over the context [ctx], in
the term [t]. It returns the number of products as well. *)letto_prod:ctxt->term->term*int=functxt->letf(t,c)(x,a,v)=letb=Bindlib.bind_varxtinmatchvwith|None->_Prod(lifta)b,c+1|Somev->_LLet(lifta)(liftv)b,cinlett,c=List.fold_leftf(liftt,0)ctxinBindlib.unboxt,c(** [to_prod_box bctx t] is similar to [to_prod bctx t] but operates on boxed
contexts and terms. *)letto_prod_box:bctxt->tbox->tbox*int=funbctxt->letf(t,c)(x,a)=letb=Bindlib.bind_varxtin(_Prodab,c+1)inList.fold_leftf(t,0)bctx(** [box_context ctx] lifts context [ctx] to a boxed context. *)letbox_context:ctxt->bctxt=List.filter_map(fun(x,t,u)->ifu=NonethenSome(x,liftt)elseNone)(** [to_abst ctx t] builds a sequence of abstractions over the context [ctx],
in the term [t]. *)letto_abst:ctxt->term->term=functxt->letft(x,a,_)=_Abst(lifta)(Bindlib.bind_varxt)inBindlib.unbox(List.fold_leftf(liftt)ctx)(** [to_let ctx t] adds the defined variables of [ctx] on top of [t]. *)letto_let:ctxt->term->term=functxt->letft=function|_,_,None->t|x,a,Someu->_LLet(lifta)(liftu)(Bindlib.bind_varxt)inBindlib.unbox(List.fold_leftf(liftt)ctx)(** [sub ctx vs] returns the sub-context of [ctx] made of the variables of
[vs]. *)letsub:ctxt->tvararray->ctxt=functxvs->letf((x,_,_)ashyp)ctx=ifArray.exists(Bindlib.eq_varsx)vsthenhyp::ctxelsectxinList.fold_rightfctx[](** [unfold ctx t] behaves like {!val:Term.unfold} unless term [t] is of the
form [Vari(x)] with [x] defined in [ctx]. In this case, [t] is replaced by
the definition of [x] in [ctx]. In particular, if no operation is carried
out on [t], we have [unfold ctx t == t]. *)letrecunfold:ctxt->term->term=functxt->matchtwith|Meta(m,ts)->beginmatch!(m.meta_value)with|None->t|Some(b)->unfoldctx(Bindlib.msubstbts)end|TEnv(TE_Some(b),ts)->unfoldctx(Bindlib.msubstbts)|TRef(r)->beginmatch!rwith|None->t|Some(v)->unfoldctxvend|Vari(x)->beginmatchdef_ofxctxwith|_,None->t|ctx',Somet->unfoldctx'tend|_->t(** [get_args ctx t] decomposes term [t] as {!val:Term.get_args} does, but
any variable encountered is replaced by its definition in [ctx] (if it
exists). *)letget_args:ctxt->term->term*termlist=functxt->letrecget_argsacct=matchunfoldctxtwith|Appl(t,u)->get_args(u::acc)t|t->(t,acc)inget_args[]t(** [to_map] builds a map from a context. *)letto_map:ctxt->termVarMap.t=letadd_defm(x,_,v)=matchvwithSomev->VarMap.addxvm|None->minList.fold_leftadd_defVarMap.empty