Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file exsubst.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132openBasicopenFormatopenTerm(** An extended substitution is a function mapping
- a variable (location, identifier and DB index)
- applied to a given number of arguments
- under a given number of lambda abstractions
to a term.
A substitution raises Not_found meaning that the variable is not subsituted. *)typeex_substitution=loc->ident->int->int->int->term(** [apply_exsubst subst n t] applies [subst] to [t] under [n] lambda abstractions.
- Variables with DB index [k] < [n] are considered "locally bound" and are never substituted.
- Variables with DB index [k] >= [n] may be substituted if [k-n] is mapped in [sigma]
and if they occur applied to enough arguments (substitution's arity). *)letapply_exsubst(subst:ex_substitution)(n:int)(te:term):term*bool=letct=ref0in(* aux increments this counter every time a substitution occurs.
* Terms are reused when no substitution occurs in recursive calls. *)letrecauxkt=matchtwith(* k counts the number of local lambda abstractions *)|DB(l,x,n)whenn>=k->((* a free variable *)tryletres=substlxn0kinincrct;reswithNot_found->t)|App((DB(l,x,n)asdb),a,args)whenn>=k->(* an applied free variable *)letct'=!ctinletf'=tryletres=substlxn(1+List.lengthargs)kinincrct;reswithNot_found->dbinleta',args'=(auxka,List.map(auxk)args)inif!ct=ct'thentelsemk_Appf'a'args'|App(f,a,args)->letct'=!ctinletf',a',args'=(auxkf,auxka,List.map(auxk)args)inif!ct=ct'thentelsemk_Appf'a'args'|Lam(l,x,a,f)->letct'=!ctinleta',f'=(map_opt(auxk)a,aux(k+1)f)inif!ct=ct'thentelsemk_Lamlxa'f'|Pi(l,x,a,b)->letct'=!ctinleta',b'=(auxka,aux(k+1)b)inif!ct=ct'thentelsemk_Pilxa'b'|_->tinletres=auxntein(res,!ct>0)moduleIntMap=Map.Make(structtypet=intletcompare=compareend)moduleExSubst=structtypet=(int*term)IntMap.t(* Maps a DB index to an arity and a lambda-lifted substitute *)letidentity=IntMap.emptyletis_identity=IntMap.is_empty(** Substitution function corresponding to given ExSubst.t instance [sigma].
We lookup the table at index: (DB index) [n] - (nb of local binders) [k]
When the variable is under applied it is simply not substituted.
Otherwise we return the reduct is shifted up by (nb of local binders) [k] *)letsubst(sigma:t)__nnargsk=letarity,t=IntMap.find(n-k)sigmainifnargs>=aritythenSubst.shiftktelseraiseNot_found(** Special substitution function corresponding to given ExSubst.t instance [sigma]
"in a smaller context":
Assume [sigma] a substitution in a context Gamma = Gamma' ; Delta with |Delta|=[i].
Then this function represents the substitution [sigma] in the context Gamma'.
All variables of Delta are ignored and substitutes of the variables of Gamma'
are unshifted. This may therefore raise UnshiftExn in case substitutes of
variables of Gamma' refers to variables of Delta.
*)letsubst2(sigma:t)(i:int)__nnargsk=letargmin,t=IntMap.find(n+i+1-k)sigmainifnargs>=argminthenSubst.shiftk(Subst.unshift(i+1)t)elseraiseNot_foundletapply'(sigma:t):int->term->term*bool=ifis_identitysigmathenfun_t->(t,false)elseapply_exsubst(substsigma)letapply2'(sigma:t)(i:int):int->term->term*bool=ifis_identitysigmathenfun_t->(t,false)elseapply_exsubst(subst2sigmai)letapplysigmait=fst(apply'sigmait)letapply2sigmanit=fst(apply2'sigmanit)letadd(sigma:t)(n:int)(nargs:int)(t:term):t=assert((not(IntMap.memnsigma))||fst(IntMap.findnsigma)>nargs);if(not(IntMap.memnsigma))||fst(IntMap.findnsigma)>nargsthenIntMap.addn(nargs,t)sigmaelsesigmaletapplys(sigma:t):t->t*bool=ifis_identitysigmathenfunt->(t,false)elsefunsigma'->letmodified=reffalseinletapplysigma(n,t)=letres,flag=apply'sigma0tinifflagthenmodified:=true;(n,res)in(IntMap.mapapplysigmasigma',!modified)letrecmk_idempotent(sigma:t):t=letsigma',flag=applyssigmasigmainifflagthenmk_idempotentsigma'elsesigmaletpp(name:int->ident)(fmt:formatter)(sigma:t):unit=letpp_auxi(n,t)=fprintffmt" %a[%i](%i args) -> %a\n"pp_ident(namei)inpp_termtinIntMap.iterpp_auxsigmaend