123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Terms For Proofs} *)openLogtkmoduleFmt=CCFormatmoduleI_map=Util.Int_mapleterrorfmsg=Util.errorf~where:"llterm"msgmoduleInt_op=structtypet=Leq0|Geq0|Lt0|Gt0|Eq0|Neq0|Divisible_byofZ.t|Not_div_byofZ.tletequalab=matcha,bwith|Divisible_bya,Divisible_byb->Z.equalab|Not_div_bya,Not_div_byb->Z.equalab|Divisible_by_,_|_,Divisible_by_|Not_div_by_,_|_,Not_div_by_->false|_->a=blethash=function|Divisible_byn->Hash.combine210(Z.hashn)|Not_div_byn->Hash.combine220(Z.hashn)|x->Hash.polyxletnot=function|Leq0->Gt0|Geq0->Lt0|Lt0->Geq0|Gt0->Leq0|Eq0->Neq0|Neq0->Eq0|Divisible_byn->Not_div_byn|Not_div_byn->Divisible_bynletppout=function|Leq0->Fmt.fprintfout"=< 0"|Geq0->Fmt.fprintfout">= 0"|Lt0->Fmt.fprintfout"< 0"|Gt0->Fmt.fprintfout"> 0"|Eq0->Fmt.fprintfout"= 0"|Neq0->Fmt.fprintfout"!= 0"|Divisible_byn->Fmt.fprintfout"div_by %a"Z.pp_printn|Not_div_byn->Fmt.fprintfout"not_div_by %a"Z.pp_printnendmoduleRat_op=structtypet=Leq0|Geq0|Lt0|Gt0|Eq0|Neq0letequal:t->t->bool=(=)lethash:t->int=Hash.polyletppout=function|Leq0->Fmt.fprintfout"=< 0"|Geq0->Fmt.fprintfout">= 0"|Lt0->Fmt.fprintfout"< 0"|Gt0->Fmt.fprintfout"> 0"|Eq0->Fmt.fprintfout"= 0"|Neq0->Fmt.fprintfout"!= 0"letnot=function|Leq0->Gt0|Geq0->Lt0|Lt0->Geq0|Gt0->Leq0|Eq0->Neq0|Neq0->Eq0endtypet={view:view;ty:toption;mutableid:int;(** unique ID *)}andview=|Type|ConstofID.t|Appoft*t(** curried application *)|Arrowoft*t(** functional arrow *)|Varofvar(** bound var *)|Bindof{binder:Binder.t;ty_var:t;body:t;}|AppBuiltinofBuiltin.t*tlist|Iteoft*t*t|Int_predofZ.tlinexp*Int_op.t|Rat_predofQ.tlinexp*Rat_op.tandvar=tHVar.tand'alinexp={const:'a;coeffs:(t*'a)I_map.t;}typeterm=ttypety=tmoduletypeNUM=sigtypetvalequal:t->t->boolvalzero:tvalone:tval(+):t->t->tval(-):t->t->tval(*):t->t->tvalto_string:t->stringvalpp_print:tCCFormat.printerendmoduletypeLINEXP=sigtypenumtypet=numlinexpvalzero:tvalis_zero:t->boolvalis_const:t->boolval(+):t->t->tval(-):t->t->tval(*):num->t->tvaladd:num->term->t->tvalconst:num->tvalmonomial:num->term->tvalmonomial1:term->tvalequal:t->t->boolvalmap:(term->term)->t->tvalsubterms:t->termIter.tvalpp:termCCFormat.printer->tCCFormat.printerendmoduleMake_linexp(N:NUM)=structtypenum=N.ttypet=numlinexpletzero:t={const=N.zero;coeffs=I_map.empty}letis_conste=I_map.is_emptye.coeffsletis_zeroe=is_conste&&N.equalN.zeroe.constletmerge_fab:t={const=fa.constb.const;coeffs=I_map.merge_safea.coeffsb.coeffs~f:(fun_o->matchowith|`Leftn|`Rightn->Somen|`Both((t,a),(t2,b))->assert(t==t2);letc=fabinifN.equalN.zerocthenNoneelseSome(t,c))}let(+)=merge_N.(+)let(-)=merge_N.(-)let(*)ce:t=ifN.equalN.zerocthenzeroelse{const=N.(c*e.const);coeffs=I_map.map(fun(t,n)->t,N.(c*n))e.coeffs}letconstc={const=c;coeffs=I_map.empty}letaddcte=let_,n=I_map.get_or~default:(t,N.zero)t.ide.coeffsinletn=N.(n+c)inletcoeffs=ifN.equalN.zeronthenI_map.removet.ide.coeffselseI_map.addt.id(t,n)e.coeffsin{ewithcoeffs;}letmonomialct={const=N.zero;coeffs=I_map.singletont.id(t,c)}letmonomial1t={const=N.zero;coeffs=I_map.singletont.id(t,N.one)}letequale1e2=N.equale1.conste2.const&&I_map.equal(CCEqual.pair(==)N.equal)e1.coeffse2.coeffslethashhash_te=lethash_nn=Hash.string@@N.to_stringninHash.combine310(hash_ne.const)(Hash.seq(Hash.pairhash_thash_n)@@I_map.valuese.coeffs)letmapfe=I_map.fold(fun_(t,n)acc->addn(ft)acc)e.coeffs(conste.const)letsubtermse=I_map.valuese.coeffs|>Iter.mapfstletpppp_tout(e:t):unit=ifis_constethenN.pp_printoute.constelse(letpp_constout()=ifN.equalN.zeroe.constthen()elseFmt.fprintfout"@ + %a"N.pp_printe.constandpp_pairout(t,c)=ifN.equalN.onecthenpp_touttelseFmt.fprintfout"@[<2>%a@ @<1>· %a@]"N.pp_printcpp_ttinFmt.fprintfout"(@[<hv>%a%a@])"Fmt.(iter~sep:(return"@ + ")pp_pair)(I_map.valuese.coeffs)pp_const())endmoduleLinexp_int=Make_linexp(Z)moduleLinexp_rat=Make_linexp(Q)let[@inline]viewt=t.viewlet[@inline]tyt=t.tylet[@inline]ty_exnt=matcht.tywithSomety->ty|None->assertfalselet[@inline]equal(a:t)(b:t):bool=a==blet[@inline]hash(a:t):int=CCHash.inta.idlet[@inline]compare(a:t)(b:t):int=CCInt.comparea.idb.idmoduleH_cons=Hashcons.Make(structtypet=termletequalab=beginmatcha.ty,b.tywith|Somety1,Somety2->equalty1ty2|None,None->true|Some_,None|None,Some_->falseend&&beginmatcha.view,b.viewwith|Type,Type->true|Constid1,Constid2->ID.equalid1id2|App(f1,x1),App(f2,x2)->equalf1f2&&equalx1x2|Arrow(a1,b1),Arrow(a2,b2)->equala1a2&&equalb1b2|Varv1,Varv2->HVar.equalequalv1v2|Bindb1,Bindb2->Binder.equalb1.binderb2.binder&&equalb1.ty_varb2.ty_var&&equalb1.bodyb2.body|AppBuiltin(b1,l1),AppBuiltin(b2,l2)->Builtin.equalb1b2&&CCList.equalequall1l2|Ite(a1,b1,c1),Ite(a2,b2,c2)->equala1a2&&equalb1b2&&equalc1c2|Int_pred(l1,o1),Int_pred(l2,o2)->Int_op.equalo1o2&&Linexp_int.equall1l2|Rat_pred(l1,o1),Rat_pred(l2,o2)->Rat_op.equalo1o2&&Linexp_rat.equall1l2|Type,_|Const_,_|App_,_|Arrow_,_|Var_,_|Bind_,_|AppBuiltin_,_|Ite_,_|Int_pred_,_|Rat_pred_,_->falseendlethash(a:t):int=matcha.viewwith|Type->1|Constid->CCHash.combine210(ID.hashid)|Varv->CCHash.combine220(HVar.hashv)|App(f,x)->CCHash.combine330(hashf)(hashx)|Arrow(a,b)->CCHash.combine335(hasha)(hashb)|Bindb->CCHash.combine440(Binder.hashb.binder)(hashb.ty_var)(hashb.body)|AppBuiltin(b,l)->CCHash.combine350(Builtin.hashb)(CCHash.listhashl)|Ite(a,b,c)->CCHash.combine460(hasha)(hashb)(hashc)|Int_pred(l,o)->Hash.combine370(Linexp_int.hashhashl)(Int_op.hasho)|Rat_pred(l,o)->Hash.combine380(Linexp_rat.hashhashl)(Rat_op.hasho)lettag(i:int)(t:t):unit=assert(t.id=-1);t.id<-iend)letrecpp_recdepthout(t:t)=matchviewtwith|Type->Fmt.stringout"type"|Constid->ID.pp_fullcoutid|App(f,a)->Fmt.fprintfout"@[%a@ %a@]"(pp_recdepth)f(pp_rec_innerdepth)a|Arrow(a,b)->Fmt.fprintfout"@[%a@ @<1>→ %a@]"(pp_rec_innerdepth)a(pp_recdepth)b|Varv->Format.fprintfout"Y%d"(depth-HVar.idv-1)|AppBuiltin(Builtin.Box_opaque,[t])->Format.fprintfout"@<1>⟦@[%a@]@<1>⟧"(pp_recdepth)t|AppBuiltin(b,[a])whenBuiltin.is_prefixb->Format.fprintfout"@[<1>%a@ %a@]"Builtin.ppb(pp_rec_innerdepth)a|AppBuiltin(b,([t1;t2]|[_;t1;t2]))whenBuiltin.fixityb=Builtin.Infix_binary->Format.fprintfout"@[<1>%a %a@ %a@]"(pp_rec_innerdepth)t1Builtin.ppb(pp_rec_innerdepth)t2|AppBuiltin(b,l)whenBuiltin.is_infixb&&List.lengthl>0->Format.fprintfout"@[<hv>%a@]"(pp_infix_depthb)l|AppBuiltin(b,[])->Builtin.ppoutb|AppBuiltin(b,l)->Format.fprintfout"(@[<hv>%a@ %a@])"Builtin.ppb(Util.pp_list(pp_rec_innerdepth))l|Bind{ty_var;binder;body}->Fmt.fprintfout"@[%a (@[Y%d:%a@]).@ %a@]"Binder.ppbinderdepth(pp_recdepth)ty_var(pp_rec@@depth+1)body|Ite(a,b,c)->Fmt.fprintfout"@[<hv2>ite %a@ %a@ %a@]"(pp_rec_innerdepth)a(pp_rec_innerdepth)b(pp_rec_innerdepth)c|Int_pred(l,o)->Fmt.fprintfout"(@[%a@ %a@])"(Linexp_int.pp(pp_rec_innerdepth))lInt_op.ppo|Rat_pred(l,o)->Fmt.fprintfout"(@[%a@ %a@])"(Linexp_rat.pp(pp_rec_innerdepth))lRat_op.ppoandpp_rec_innerdepthoutt=matchviewtwith|App_|Bind_|AppBuiltin(_,_::_)|Arrow_|Ite_->Fmt.fprintfout"(%a)/%d"(pp_recdepth)tt.id|Type|Const_|Var_|AppBuiltin(_,[])|Int_pred_|Rat_pred_->Fmt.fprintfout"%a/%d"(pp_recdepth)tt.idandpp_infix_depthboutl=matchlwith|[]->assertfalse|[t]->pp_rec_innerdepthoutt|t::l'->Format.fprintfout"@[%a@]@ %a %a"(pp_rec_innerdepth)tBuiltin.ppb(pp_infix_depthb)l'letpp=pp_rec0letpp_inner=pp_rec_inner0letsubterms(t:t)(k:t->unit):unit=letrecauxt=kt;CCOpt.iteraux(tyt);beginmatchviewtwith|Type|Const_|Var_->()|App(f,a)->auxf;auxa|Arrow(a,b)->auxa;auxb|Bind{body;_}->auxbody|AppBuiltin(_,l)->List.iterauxl|Ite(a,b,c)->auxa;auxb;auxc|Int_pred(l,_)->Linexp_int.subtermslk|Rat_pred(l,_)->Linexp_rat.subtermslkendinauxtlet[@inline]mk_viewty:t=lett={view;ty;id=-1;}inH_cons.hashconstlett_type=mk_TypeNonelet[@inline]varv=mk_(Varv)(Some(HVar.tyv))let[@inline]const~tyid=mk_(Constid)(Somety)letprop=mk_(AppBuiltin(Builtin.Prop,[]))(Somet_type)let[@inline]is_typet:bool=matchtytwith|Somety->ty==t_type|None->falseletiteabc=beginmatchtyb,tycwith|Somety1,Somety2whenequalty1ty2->mk_(Ite(a,b,c))(tyb)|_->errorf"type error:@ cannot build `@[ite %a %a %a@]`@ incompatible types"ppappbppcendlet[@inline]app_fx~ty=mk_(App(f,x))(Somety)let[@inline]arrow_ab=mk_(Arrow(a,b))(Somet_type)let[@inline]bind_~tybinder~ty_varbody=mk_(Bind{binder;ty_var;body})(Somety)letid_eta_=ID.make"test_eta_"(* privat to {!as_eta_expansion} *)let[@inline]app_builtin~tybl=letmk_bl=mk_(AppBuiltin(b,l))(Somety)inbeginmatchb,lwith|Builtin.Not,[f']->beginmatchviewf'with|AppBuiltin(Builtin.Eq,l)->mk_Builtin.Neql|AppBuiltin(Builtin.Neq,l)->mk_Builtin.Eql|AppBuiltin(Builtin.Not,[t])->t|AppBuiltin(Builtin.True,[])->mk_Builtin.False[]|AppBuiltin(Builtin.False,[])->mk_Builtin.True[]|_->mk_blend|_->mk_blendlet[@inline]builtin~tyb=app_builtin~tyb[]letbool=builtin~ty:t_typeBuiltin.Proplettrue_=builtin~ty:boolBuiltin.Trueletfalse_=builtin~ty:boolBuiltin.Falseletof_boolb=ifbthentrue_elsefalse_letint_predlo=ifLinexp_int.is_constlthen(letmoduleO=Int_opinletn=l.constinbeginmatchowith|O.Leq0->Z.signn<=0|O.Geq0->Z.signn>=0|O.Lt0->Z.signn<0|O.Gt0->Z.signn>0|O.Eq0->Z.signn=0|O.Neq0->Z.signn<>0|O.Divisible_byk->Z.equalZ.zero(Z.remnk)|O.Not_div_byk->not(Z.equalZ.zero(Z.remnk))end|>of_bool)elsemk_(Int_pred(l,o))(Someprop)letrat_predlo=ifLinexp_rat.is_constlthen(letmoduleO=Rat_opinletn=l.constinbeginmatchowith|O.Leq0->Q.signn<=0|O.Geq0->Q.signn>=0|O.Lt0->Q.signn<0|O.Gt0->Q.signn>0|O.Eq0->Q.signn=0|O.Neq0->Q.signn<>0end|>of_bool)elsemk_(Rat_pred(l,o))(Someprop)let[@inline]map~f~bind:f_bindb_acct=matchviewtwith|Type->t_type|Varv->var(HVar.update_tyv~f:(fb_acc))|Constid->const~ty:(fb_acc@@ty_exnt)id|App(hd,a)->app_(fb_acchd)(fb_acca)~ty:(fb_acc(ty_exnt))|Arrow(a,b)->arrow_(fb_acca)(fb_accb)|Bindb->letb_acc'=f_bindb_accinbind_b.binder~ty:(fb_acc@@ty_exnt)~ty_var:(fb_accb.ty_var)(fb_acc'b.body)|AppBuiltin(b,l)->app_builtin~ty:(fb_acc@@ty_exnt)b(List.map(fb_acc)l)|Ite(a,b,c)->ite(fb_acca)(fb_accb)(fb_accc)|Int_pred(l,o)->int_pred(Linexp_int.map(fb_acc)l)o|Rat_pred(l,o)->rat_pred(Linexp_rat.map(fb_acc)l)o(* shift DB indices by [n] *)letdb_shiftn(t:t):t=letrecauxkt=matchviewtwith|Varv->ifHVar.idv>=kthenvar(HVar.make(HVar.idv+n)~ty:(HVar.tyv))elset|_->map~f:aux~bind:succktinaux0t(* replace DB 0 by [sub] in [t] *)letdb_eval~(sub:t)(t:t):t=letrecauxkt=matchviewtwith|Varv->ifHVar.idv=kthen((* shift [sub] by the number of binders added since binding point *)db_shiftksub)elseif(HVar.idv>k)then((* shift down by 1, to account for the vanished binder *)var(HVar.make(HVar.idv-1)~ty:(HVar.tyv)))elset|_->map~f:aux~bind:succktinaux0tletbind~tybinder~ty_varbody=matchbinder,viewbodywith|Binder.Lambda,App(t,{view=Varv;_})whenHVar.idv=0->(* eta reduction for λ:
check if replacing [db0] with a fresh [c] in [t] contains [c] *)letc=constid_eta_~ty:(HVar.tyv)inlett_reduced=db_eval~sub:ctinifsubtermst_reduced|>Iter.exists(equalc)thenbind_binder~ty~ty_varbodyelset_reduced|_->bind_binder~ty~ty_varbodyletapp_fx=matchtyf,tyxwith|Some{view=Arrow(a,b);_},Somea'whenequalaa'->app_fx~ty:b|Some{view=Bind{binder=Binder.ForallTy;ty_var;body};_},Somety_x->(* polymorphic type *)ifnot(equalty_xt_type)then(errorf"cannot apply@ `@[<2>%a@ : %a@]`@ to non-type `@[<2>%a@ : %a@]`"ppf(Fmt.optpp)(tyf)ppx(Fmt.optpp)(tyx));ifnot(equalty_vart_type)then(errorf"ill-formed polymorphic type@ `%a`"pp(ty_exnf););letty=db_eval~sub:xbodyinapp_fx~ty|_->errorf"type error: cannot apply `@[<2>%a@ : %a@]`@ to `@[<2>%a@ : %a@]`"ppf(Fmt.optpp)(tyf)ppx(Fmt.optpp)(tyx)letappfx=matchviewfwith|Bind{binder=Binder.Lambda;ty_var;body}->(* β-reduction *)beginmatchtyxwith|Somety_xwhenequalty_varty_x->db_eval~sub:xbody|Somety_x->errorf"type error: cannot apply `%a`@ to `%a : %a`"ppfppxppty_x|None->errorf"type error: cannot apply `%a`@ to `%a : none`"ppfppxend|_->app_fxletrecapp_lf=function|[]->f|a::tail->app_l(appfa)tailletrecreturns(t:t):ty=matchviewtwith|Arrow(_,ret)->returnsret|_->tletarrowab=matchtya,tybwith|Some{view=Type;_},Some{view=Type;_}->arrow_ab|_whena==t_type&&returnsb==t_type->arrow_ab(* type constructor *)|_->errorf"type error: cannot make arrow between non-types@ :from `%a`@ :to `%a`"ppappbletrecarrow_llret=matchlwith|[]->ret|a::tail->arrowa(arrow_ltailret)letbox_opaquet=app_builtin~ty:(ty_exnt)Builtin.Box_opaque[t]letid_eta_=ID.make"test_eta_"(* privat to {!as_eta_expansion} *)(* check if [body = t db0], with [db0 ∉ t].
returns [Some (t shift -1)] if it's the case *)letas_eta_expansionbody:_option=matchviewbodywith|App(t,{view=Varv;_})whenHVar.idv=0->(* check if replacing [db0] with a fresh [c] in [t] contains [c] *)letc=constid_eta_~ty:(HVar.tyv)inlett_reduced=db_eval~sub:ctinifsubtermst_reduced|>Iter.exists(equalc)thenNoneelseSomet_reduced|_->Nonelet[@inline]lambda~ty_varbody=bindBinder.Lambda~ty:(arrowty_var@@ty_exnbody)~ty_varbodymoduleForm=structtypet=termtypeview=|True|False|Oroftlist|Andoftlist|Notoft|Equivoft*t|Xoroft*t|Implyoft*t|Atomoft|Eqoft*t|Neqoft*t|Int_predofZ.tlinexp*Int_op.t|Rat_predofQ.tlinexp*Rat_op.t|Forallof{ty_var:ty;body:t}|Existsof{ty_var:ty;body:t}letpp=ppletviewt=matchviewtwith|AppBuiltin(Builtin.True,[])->True|AppBuiltin(Builtin.False,[])->False|AppBuiltin(Builtin.And,l)->Andl|AppBuiltin(Builtin.Or,l)->Orl|AppBuiltin(Builtin.Not,[t])->Nott|AppBuiltin(Builtin.Eq,([_;t;u]|[t;u]))->Eq(t,u)|AppBuiltin(Builtin.Neq,([_;t;u]|[t;u]))->Neq(t,u)|AppBuiltin(Builtin.Imply,[t;u])->Imply(t,u)|AppBuiltin(Builtin.Equiv,[t;u])->Equiv(t,u)|AppBuiltin(Builtin.Xor,[t;u])->Xor(t,u)|Bind{binder=Binder.Forall;ty_var;body;_}->Forall{ty_var;body}|Bind{binder=Binder.Exists;ty_var;body;_}->Exists{ty_var;body}|Int_pred(l,o)->Int_pred(l,o)|Rat_pred(l,o)->Rat_pred(l,o)|_->Atomtlettrue_=true_letfalse_=false_leteqab=app_builtin~ty:(ty_exna)Builtin.Eq[a;b]letneqab=app_builtin~ty:boolBuiltin.Neq[a;b]letand_a=app_builtin~ty:boolBuiltin.Andaletor_a=app_builtin~ty:boolBuiltin.Oraletequivab=app_builtin~ty:(ty_exna)Builtin.Equiv[a;b]letimplyab=app_builtin~ty:(ty_exna)Builtin.Imply[a;b]letxorab=app_builtin~ty:(ty_exna)Builtin.Xor[a;b]letint_pred=int_predletrat_pred=rat_predletforall~ty_varbody=bindBinder.Forall~ty:bool~ty_varbodyletexists~ty_varbody=bindBinder.Exists~ty:bool~ty_varbodyletnot_a=matchviewawith|Eq(a,b)->neqab|Neq(a,b)->eqab|Notf->f|Int_pred(l,o)->int_predl(Int_op.noto)|Rat_pred(l,o)->rat_predl(Rat_op.noto)|_->app_builtin~ty:boolBuiltin.Not[a]endmoduleAs_key=structtypet=termletcompare=compareendmoduleSet=CCSet.Make(As_key)moduleConv=structmoduleT=TypedSTermtypectx={depth:int;(* depth *)vars:(T.t,int*ty)Var.Subst.t;(* depth at binding site, + type *)}letcreate():ctx={depth=0;vars=Var.Subst.empty}letpp_ctxout(c:ctx):unit=Fmt.fprintfout"(@[ctx@ :depth %d@ :vars %a@])"c.depth(Var.Subst.pp(Fmt.mapfstFmt.int))c.varsletrecof_term(ctx:ctx)(t:T.t):t=matchT.viewtwith|T.Varv->beginmatchVar.Subst.findctx.varsvwith|None->errorf"cannot find var `%a`@ in %a"Var.ppvpp_ctxctx|Some(i,ty)->assert(ctx.depth>i);letty=db_shift(ctx.depth-i)tyinvar(HVar.make(ctx.depth-i-1)~ty)end|T.AppBuiltin(Builtin.Pseudo_de_bruijni,[])->(* NOTE: magic here. This was a free De Bruijn index, typically coming
from rewriting under lambdas. Now we convert it back into a
normal DB index. *)letty=of_termctx(T.ty_exnt)invar(HVar.makei~ty)|T.Constid->letty=of_termctx(T.ty_exnt)inconstid~ty|T.App(f,l)->letf=of_termctxfinletl=List.map(of_termctx)linapp_lfl|T.Ite(a,b,c)->leta=of_termctxainletb=of_termctxbinletc=of_termctxciniteabc|T.Bind(b,var,body)->letty=of_termctx(T.ty_exnt)inletty_var=of_termctx(Var.tyvar)inletctx={depth=ctx.depth+1;vars=Var.Subst.addctx.varsvar(ctx.depth,ty_var)}inbindb~ty_var~ty(of_termctxbody)|T.AppBuiltin(Builtin.TType,[])->t_type|T.AppBuiltin(Builtin.Arrow,ret::l)->letret=of_termctxretinletl=List.map(of_termctx)linarrow_llret|T.AppBuiltin(b,l)->letty=T.ty_exntinbeginmatchbwith|(Builtin.Greatereq|Builtin.Lesseq|Builtin.Less|Builtin.Greater|Builtin.Eq|Builtin.Neq)whenList.existsis_arithl->ifList.existsis_intlthen(conv_int_predctx~tybl)else(assert(List.existsis_ratl);conv_rat_predctx~tybl)|_->conv_builtinctx~tyblend|T.Let_->assertfalse(* FIXME *)|T.Match_->assertfalse(* FIXME? *)|T.Multiset_->assertfalse(* FIXME? *)|T.Record_->assertfalse(* FIXME? *)|T.Meta_->assertfalseandis_intt=T.Ty.equalT.Ty.int(T.ty_exnt)andis_ratt=T.Ty.equalT.Ty.rat(T.ty_exnt)andis_aritht=is_intt||is_ratt(* default conv for builtins *)andconv_builtinctx~tybl=letty=of_termctxtyinletl=List.map(of_termctx)linapp_builtin~tyblandconv_int_predctx~tybl:term=letmoduleO=Int_opinletop=matchbwith|Builtin.Greatereq->O.Geq0|Builtin.Lesseq->O.Leq0|Builtin.Less->O.Lt0|Builtin.Greater->O.Gt0|Builtin.Eq->O.Eq0|Builtin.Neq->O.Neq0|_->assertfalseinmatchlwith|[_;a;b]|[a;b]->leta=conv_int_linexpctxainletb=conv_int_linexpctxbinint_predLinexp_int.(a-b)op|_->conv_builtinctx~tyblandconv_rat_predctx~tybl:term=letmoduleO=Rat_opinletop=matchbwith|Builtin.Greatereq->O.Geq0|Builtin.Lesseq->O.Leq0|Builtin.Less->O.Lt0|Builtin.Greater->O.Gt0|Builtin.Eq->O.Eq0|Builtin.Neq->O.Neq0|_->assertfalseinmatchlwith|[_;a;b]|[a;b]->leta=conv_rat_linexpctxainletb=conv_rat_linexpctxbinrat_predLinexp_rat.(a-b)op|_->conv_builtinctx~tyblandconv_int_linexpctxt:Linexp_int.t=matchT.viewtwith|T.AppBuiltin(Builtin.Intz,[])->Linexp_int.constz|T.AppBuiltin(Builtin.Sum,[_;a;b])->Linexp_int.(conv_int_linexpctxa+conv_int_linexpctxb)|T.AppBuiltin(Builtin.Difference,[_;a;b])->Linexp_int.(conv_int_linexpctxa-conv_int_linexpctxb)|T.AppBuiltin(Builtin.Product,[_;a;b])->beginmatchT.viewa,T.viewbwith|T.AppBuiltin(Builtin.Intn,[]),_->Linexp_int.(n*conv_int_linexpctxb)|_,T.AppBuiltin(Builtin.Intn,[])->Linexp_int.(n*conv_int_linexpctxa)|_->Linexp_int.monomial1(of_termctxt)end|_->Linexp_int.monomial1(of_termctxt)andconv_rat_linexpctxt:Linexp_rat.t=matchT.viewtwith|T.AppBuiltin(Builtin.Ratz,[])->Linexp_rat.constz|T.AppBuiltin(Builtin.Sum,[_;a;b])->Linexp_rat.(conv_rat_linexpctxa+conv_rat_linexpctxb)|T.AppBuiltin(Builtin.Difference,[_;a;b])->Linexp_rat.(conv_rat_linexpctxa-conv_rat_linexpctxb)|T.AppBuiltin(Builtin.Product,[_;a;b])->beginmatchT.viewa,T.viewbwith|T.AppBuiltin(Builtin.Ratn,[]),_->Linexp_rat.(n*conv_rat_linexpctxb)|_,T.AppBuiltin(Builtin.Ratn,[])->Linexp_rat.(n*conv_rat_linexpctxa)|_->Linexp_rat.monomial1(of_termctxt)end|_->Linexp_rat.monomial1(of_termctxt)end