123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109(** Typing context. *)openTermopenTimed(** [unbind ctx a def b] returns a triple [(x,t,new_ctx)] such that [(x,t)] is
an unbinding of [b] (in the sense of [Bindlib.unbind]) and [new_ctx] is an
extension of the context [ctx] with the declaration that [x] has type [a]
(only if [x] occurs in [t]). If [def] is of the form [Some(u)], the context
also registers the term [u] as the definition of variable [x]. *)letunbind:ctxt->term->termoption->tbinder->tvar*term*ctxt=functxadefb->let(x,t)=Bindlib.unbindbin(x,t,ifBindlib.binder_occurbthen(x,a,def)::ctxelsectx)(** [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_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