12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268openElpi_utilopenElpi_parseropenElpi_runtimeopenUtilmoduleF=Ast.FuncmoduleSymbol=Data.SymbolmoduleScopeContext=structtypelanguage=string[@@derivingshow,ord]typectx={vmap:(language*F.t*F.t)list;uvmap:(F.t*F.t)listref}letempty()={vmap=[];uvmap=ref[]}leteq_var{vmap}languagec1c2=List.mem(language,c1,c2)vmapletcmp_varctxlanguagec1c2=ifeq_varctxlanguagec1c2then0elseletr=F.comparec1c2inifr=0then-1elserletpurgelanguagefcl=List.filter(fun(l,x,y)->l=language&¬@@F.equal(f(x,y))c)lletpush_ctxlanguagec1c2ctx={ctxwithvmap=(language,c1,c2)::(purgelanguagefstc1@@purgelanguagesndc2ctx.vmap)}leteq_uvarctxc1c2=ifList.exists(fun(x,_)->F.equalxc1)!(ctx.uvmap)||List.exists(fun(_,y)->F.equalyc2)!(ctx.uvmap)thenList.mem(c1,c2)!(ctx.uvmap)elsebeginctx.uvmap:=(c1,c2)::!(ctx.uvmap);trueendendletelpi_language:ScopeContext.language="lp"letelpi_var:ScopeContext.language="lp_var"moduleMutableOnce:sigtype'at[@@derivingshow,ord]valmake:F.t->'atvalcreate:'a->'atvalset:?loc:Loc.t->'at->'a->unitvalunset:'at->unitvalget:'at->'avalget_name:'at->F.tvalis_set:'at->boolvalpretty:Format.formatter->'at->unitend=structtype'at=F.t*'aoptionref[@@derivingshow,ord]letmakef=f,refNoneletcreatet=F.from_string"_",ref(Somet)letis_set(_,x)=Option.is_some!xletset?loc(_,r)x=match!rwith|None->r:=Somex|Some_->anomaly?loc"MutableOnce"letget(_,x)=match!xwithSomex->x|None->anomaly"get"letget_name(x,_)=xletunset(_,x)=x:=Noneletprettyfmt(f,x)=match!xwith|None->Format.fprintffmt"%a"F.ppf|Some_->anomaly"pp"endmoduleTypeAssignment=structtypetmode=MRefoftmodeMutableOnce.t|MValofMode.t[@@derivingshow]letrecderef_tmode=function|MRefrwhenMutableOnce.is_setr->deref_tmode(MutableOnce.getr)|a->aletcompare_tmodem1m2=matchderef_tmodem1,deref_tmodem2with|MValm1,MValm2->Mode.comparem1m2|_->anomaly"comparing an inferred mode declaration. Maybe some pred/func declaration is missing"letis_tmode_sett=matchderef_tmodetwith|MVal_->true|_->falseletset_tmodemx=matchderef_tmodemwith|MVal_->assertfalse|MRefm->MutableOnce.setm(MValx)letrecpretty_tmodefmt=function|MRefxwhenMutableOnce.is_setx->pretty_tmodefmt(MutableOnce.getx)|MRefx->Format.fprintffmt"?"|MValm->Mode.prettyfmtmletrecis_input=function|MRefxwhenMutableOnce.is_setx->is_input(MutableOnce.getx)|MRefx->false|MValMode.Input->true|MValMode.Output->falsetype'aoverloaded=|Singleof'a|Overloadedof'alist[@@derivingshow,fold,iter]type('uvar,'mode)t__=|PropofAst.Structured.functionality|Any|ConsofF.t|AppofF.t*('uvar,'mode)t__*('uvar,'mode)t__list|Arrof'mode*Ast.Structured.variadic*('uvar,'mode)t__*('uvar,'mode)t__|UVarof'uvar[@@derivingshow,fold,ord]type'at_=('a,tmode)t__[@@derivingshow,fold]exceptionInvalidModeletcmp_auxcmp1k=ifcmp1=0thenk()elsecmp1let(&&&)xy=ifx=0thenyelsexletreccompare_t_~cmp_mode~cmp_funcct1t2=matcht1,t2with|Propd1,Propd2->cmp_funcd1d2|Any,Any->0|Consf1,Consf2->F.comparef1f2|App(f1,hd,tl),App(f2,hd1,tl1)->cmp_aux(F.comparef1f2)(fun()->List.compare(compare_t_~cmp_mode~cmp_funcc)(hd::tl)(hd1::tl1))|Arr(m1,v1,l1,r1),Arr(m2,v2,l2,r2)->(cmp_modem1m2)&&&cmp_aux(Ast.Structured.compare_variadicv1v2)(fun()->cmp_aux(compare_t_~cmp_mode~cmp_funccl1l2)(fun()->compare_t_~cmp_mode~cmp_funccr1r2))|UVarv1,UVarv2->cv1v2|Prop_,_->-1|_,Prop_->1|Any,_->-1|_,Any->1|Cons_,_->-1|_,Cons_->1|App_,_->-1|_,App_->1|Arr_,_->-1|_,Arr_->1typeskema=LamofF.t*skema|TyofF.tt_[@@derivingshow]typetype_abbrevs=(skema*Ast.Loc.t)F.Map.t[@@derivingshow]letcompare_skema~cmp_mode~cmp_funcsk1sk2=letrecauxctxsk1sk2=matchsk1,sk2with|Lam(f1,sk1),Lam(f2,sk2)->aux(ScopeContext.push_ctxelpi_languagef1f2ctx)sk1sk2|Tyt1,Tyt2->compare_t_~cmp_mode~cmp_func(ScopeContext.cmp_varctxelpi_language)t1t2|Lam_,Ty_->-1|Ty_,Lam_->1inaux(ScopeContext.empty())sk1sk2typeoverloaded_symbol=Symbol.toverloaded[@@derivingshow]typet=ValoftMutableOnce.tt_[@@derivingshow]typety=tMutableOnce.tt_[@@derivingshow]letcreatet=MutableOnce.create(Valt)letunval(Valx)=xletrecderefm=matchunval@@MutableOnce.getmwith|UVarmwhenMutableOnce.is_setm->derefm|x->xletderef_optm=ifMutableOnce.is_setmthenSome(derefm)elseNoneopenFormatletpretty(f:formatter->(formatter->'at_->unit)->'a->unit)fmttm=letarrs=0inletapp=1inletrecarrow_tail=function|Propx->Somex|Arr(_,_,_,x)->arrow_tailx|_->Noneinletlvl_of=function|Arr_->arrs|App_->app|_->2inletshow_modefmtm=Format.fprintffmt"%a"pretty_tmodeminletrecis_func_modesinput=function|Arr(m,_,_,t)whenis_inputm&&input->is_func_modesinputt|Arr(m,_,_,t)whennot(is_inputm)&&input->is_func_modesfalset|Arr(m,_,_,t)whennot(is_inputm)&¬input->is_func_modesfalset|Prop_->true|_->falseinletrecprettyfmt=function|PropRelation->fprintffmt"(pred)"|PropFunction->fprintffmt"(func)"|Any->fprintffmt"any"|Consc->F.ppfmtc|App(f,x,xs)->fprintffmt"@[<hov 2>%a@ %a@]"F.ppf(Util.pplist(pretty_parens~lvl:app)" ")(x::xs)|Arr(m,NotVariadic,s,t)asx->beginmatcharrow_tailtwith|None->fprintffmt"@[<hov 2>%a ->@ %a@]"(pretty_parens~lvl:arrs)sprettyt|SomeAst.Structured.Functionwhenis_func_modestruex->fprintffmt"@[<hov 2>(func%a)@]"(pretty_func~fst:truetrue)x|Some_->fprintffmt"@[<hov 2>(pred %a)@]"(pretty_pred_modem)(s,t)end|Arr(m,Variadic,s,t)->fprintffmt"variadic %a %a"(pretty_parens~lvl:arrs)sprettyt|UVarm->ffmtprettym(* | UVar m -> MutableOnce.pretty fmt m *)andpretty_parens~lvlfmt=function|UVarm->ffmt(pretty_parens~lvl)m|twhenlvl>=lvl_oft->fprintffmt"(%a)"prettyt|t->prettyfmttandpretty_pred_modemfmt(s,t)=fprintffmt"@[<hov 2>%a:%a@]"show_modem(pretty_parens~lvl:arrs)s;matchtwith|Prop_->()|Arr(m,v,s',r)->fprintffmt", %s%a"(ifv=Variadicthen"variadic "else"")(pretty_pred_modem)(s',r)|_->assertfalseandpretty_func?(fst=false)inputfmtx=matchxwith|Prop_->()|Arr(m,v,s,r)->letinput=ifnot(is_inputm)&&inputthenbeginfprintffmt"@ ->";falseendelse(ifnotfstthenfprintffmt",";input)infprintffmt"@[<hov 2>@ %a%a@]"(pretty_parens~lvl:arrs)s(pretty_funcinput)r|_->assertfalseinletprettyfmtt=Format.fprintffmt"@[%a@]"prettytinprettyfmttmletpretty_mut_once=pretty(funfmtft->ifMutableOnce.is_settthenffmt(dereft)elseMutableOnce.prettyfmtt)letpretty_ftfmtt=pretty(funfmt_(t:F.t)->F.ppfmtt)fmttletpretty_skemafmtsk=letrecaux=function|Lam(_,t)->auxt|Tyt->pretty_ftfmttinauxskletpretty_skema=pretty_skemaletpretty_skema_w_idfmt(_,sk)=pretty_skemafmtskletpretty_overloaded_skemafmt=function|Singlet->pretty_skema_w_idfmtt|Overloadedl->pplistpretty_skema_w_id","fmtlletsetmv=MutableOnce.setm(Valv)letnew_ty():tMutableOnce.t=MutableOnce.make(F.from_string"Ty")letmkPropf:tMutableOnce.t=letr=MutableOnce.make(F.from_string"Ty")insetr(Propf);rletmkListx:tMutableOnce.t=letr=MutableOnce.make(F.from_string"Ty")insetr(App(F.from_string"list",x,[]));rletnparams(t:skema)=letrecaux=functionTy_->0|Lam(_,t)->1+auxtinauxtletrecsubstmap=function|(Prop_|Any|Cons_)asx->x|App(c,x,xs)->App(c,substmapx,List.map(substmap)xs)|Arr(m,v,s,t)->Arr(m,v,substmaps,substmapt)|UVarc->matchmapcwith|Somex->x|None->anomaly"TypeAssignment.subst"letfresh(sk:skema)=letrecfreshmap=function|Lam(c,t)->fresh(F.Map.addc(UVar(MutableOnce.makec))map)t|Tyt->ifF.Map.is_emptymapthen(Obj.magict),mapelse(subst(funx->F.Map.find_optxmap)t),mapinfreshF.Map.emptyskletmap_overloadedf=function|Singlesk->Single(fsk)|Overloadedl->Overloaded(List.mapfl)letfresh_overloadedo=map_overloaded(funx->fst@@freshx)oletrecapplymskargs=matchsk,argswith|Tyt,[]->ifF.Map.is_emptymthenObj.magictelsesubst(funx->F.Map.find_optxm)t|Lam(c,t),x::xs->apply(F.Map.addcxm)txs|_->assertfalse(* kind checker *)letapply(sk:skema)args=applyF.Map.emptyskargsletrecis_prop~type_abbrevs=function|Propf->Somef|ConsawhenF.Map.mematype_abbrevs->letty=apply(fst@@F.Map.findatype_abbrevs)[]inis_prop~type_abbrevsty|App(a,x,xs)whenF.Map.mematype_abbrevs->letty=apply(fst@@F.Map.findatype_abbrevs)(x::xs)inis_prop~type_abbrevsty|Any|Cons_|App_|UVar_->None|Arr(_,_,_,t)->is_prop~type_abbrevstleteq_skema_w_idn(symb1,x)(symb2,y)=trycompare_skema~cmp_mode:compare_tmode~cmp_func:Ast.Structured.compare_functionalityxy=0withInvalidMode->error~loc:(Symbol.get_locsymb1)(Format.asprintf"@[<v>duplicate mode declaration for %a.@ - %a %a@ - %a %a@]"F.ppnSymbol.ppsymb1pretty_skemaxSymbol.ppsymb2pretty_skemay)letcheck_same_mode~loc1~loc2(s1,x)(s2,y)=ifcompare_skema~cmp_mode:compare_tmode~cmp_func:Ast.Structured.compare_functionalityxy<>0thenerror~loc:loc2(Format.asprintf"@[<v>Two types for the symbol %s cannot only differ on modes or functionality.@\n@[<hov 2>Current declaration:@;<2 0>%a@]@\n@[<v 2>Previous declaration: %a@ (%s)@]@]"(Symbol.prettys1)pretty_skemaxpretty_skemay(Loc.showloc1))letundup_skemassk_of_sosl=letl=osl|>List.map(funx->x,sk_of_sx)inletfiltered=ref[]inleteq_skema((s1,x)asl)((s2,y)asr)=letb=compare_skema~cmp_mode:(fun__->0)~cmp_func:(fun__->0)xy=0inifbthencheck_same_mode~loc1:(Symbol.get_locs1)~loc2:(Symbol.get_locs2)lr;ifbthenfiltered:=(s1,s2)::!filtered;binletl=letrecundup=function|[]->[]|(s,_asx)::xswhenList.exists(eq_skemax)xs->undupxs|x::xs->x::undupxsinunduplinmatchList.mapfstlwith|[]->assertfalse|[x]->!filtered,Singlex|l->!filtered,Overloadedlletmerge_skemask1sk2=ifcompare_skema~cmp_mode:compare_tmode~cmp_func:Ast.Structured.compare_functionalitysk1sk2<>0thenanomaly"merging different skemas";sk1letcompare_t_ab=compare_t_~cmp_mode:compare_tmode~cmp_func:Ast.Structured.compare_functionalityabletcompare_skemaab=compare_skema~cmp_mode:compare_tmode~cmp_func:Ast.Structured.compare_functionalityabexceptionNot_monomorphicletis_monomorphic(Valt)=letrecmap=function|UVarrwhenMutableOnce.is_setr->map(derefr)|UVar_->raiseNot_monomorphic|(Prop_|Any|Cons_)asv->v|App(c,x,xs)->App(c,mapx,List.mapmapxs)|Arr(m,b,s,t)->Arr(m,b,maps,mapt)intrylett=maptinSome(Ty(Obj.magict:F.tt_))(* No UVar nodes *)withNot_monomorphic->Noneletvars_of(Valt)=fold_t__(fun(xs,acc)(x:tMutableOnce.t)->ifMutableOnce.is_setxthenxs,accelsex::xs,acc)(fun(acc,xs)(x:tmode)->matchxwith|MRefxwhenMutableOnce.is_setx->acc,xs|MRefx->acc,x::xs|MVal_->acc,xs)([],[])tletto_func_mode~(type_abbrevs:type_abbrevs)f=letapply_tafcaccl=matchF.Map.find_optctype_abbrevswith|None->None|Some(e,_)->facc(applyel)inletrecauxacc=function|Propf->Some(Somef,List.revacc)|Any|UVar_->None|Consc->apply_taauxcacc[]|App(c,x,xs)->apply_taauxcacc(x::xs)|Arr(mode,_,l,r)->letm=matchderef_tmodemodewith|MValv->v|MRef_->Outputinmatchaux[]lwith|None->aux(Mode.Fom::acc)r|Some(_,e)->aux(Mode.Ho(m,e)::acc)rinmatchaux[]fwithNone->(None,[])|Somee->eletrecskema_to_func_mode~(type_abbrevs:type_abbrevs)=function|Lam(_,x)->skema_to_func_mode~type_abbrevsx|Tyt->to_func_mode~type_abbrevstendmoduleTypingEnv:sigtypeindexing=|IndexofElpi_runtime.Data.pred_info|DontIndex[@@derivingshow]typesymbol_metadata={ty:TypeAssignment.skema;indexing:indexing;availability:Elpi_parser.Ast.Structured.symbol_availability;implemented_in_ocaml:bool;occur_check:bool;}[@@derivingshow]valcompatible_indexing:indexing->indexing->booltypet={symbols:symbol_metadataSymbol.QMap.t;overloading:Symbol.tTypeAssignment.overloadedF.Map.t;}[@@derivingshow]valempty:tvalresolve_name:F.t->t->Symbol.tTypeAssignment.overloadedvalresolve_symbol:Symbol.t->t->symbol_metadatavalresolve_symbol_opt:Symbol.t->t->symbol_metadataoptionvalmerge_envs:t->t->tvaliter_names:(F.t->Symbol.tTypeAssignment.overloaded->unit)->t->unitvaliter_symbols:(Symbol.t->symbol_metadata->unit)->t->unitvalsame_symbol:t->Symbol.t->Symbol.t->boolvalcompare_symbol:t->Symbol.t->Symbol.t->intvalundup:t->Symbol.tlist->Symbol.tlistvalall_symbols:t->(Symbol.t*symbol_metadata)listvalmem_symbol:t->Symbol.t->boolvalcanon:t->Symbol.t->Symbol.tvalset_as_implemented_in_ocaml:t->Symbol.t->tend=structtypeindexing=|IndexofElpi_runtime.Data.pred_info|DontIndex[@@derivingshow]typesymbol_metadata={ty:TypeAssignment.skema;indexing:indexing;availability:Elpi_parser.Ast.Structured.symbol_availability;implemented_in_ocaml:bool;occur_check:bool;}[@@derivingshow]typet={symbols:symbol_metadataSymbol.QMap.t;overloading:Symbol.tTypeAssignment.overloadedF.Map.t;}[@@derivingshow]letset_as_implemented_in_ocamles=matchSymbol.QMap.find_optse.symbolswith|None->assertfalse|Somem->{ewithsymbols=Symbol.QMap.adds{mwithimplemented_in_ocaml=true}e.symbols}letcompatible_indexingi1i2=matchi1,i2with|Index{indexing=i1;mode=m1},Index{indexing=i2;mode=m2}->Elpi_runtime.Data.compare_indexingi1i2==0&&Elpi_util.Util.Mode.compare_hosm1m2==0|DontIndex,_->true|_,DontIndex->trueletempty={symbols=Symbol.QMap.empty;overloading=F.Map.empty}letcanonsymbolss=Symbol.UF.find(Symbol.QMap.get_ufsymbols)sletresolve_namef{overloading;symbols}:Symbol.tTypeAssignment.overloaded=matchF.Map.findfoverloadingwith|Singles->Single(canonsymbolss)|Overloadedl->Overloaded(List.map(canonsymbols)l)letresolve_symbols{symbols}=Symbol.QMap.findssymbolsletresolve_symbol_opts{symbols}=Symbol.QMap.find_optssymbolsletmerge_indexingsidx1idx2=ifnot@@compatible_indexingidx1idx2thenerror~loc:(Symbol.get_locs)("Incompatible indexing options for symbol "^Symbol.get_strs);idx1letmerge_availabilitysa1a2=letopenAst.Structuredinmatcha1,a2with|Elpi,Elpi->Elpi|OCaml(p1),OCaml(p2)whenSymbol.compare_provenancep1p2=0->a1|OCaml((Builtin_|Core)),OCaml((File_))->a1|OCaml((File_)),OCaml((Builtin_|Core))->a2|_->error~loc:(Symbol.get_locs)("Incompatible provenance for symbol "^Symbol.get_strs^": "^show_symbol_availabilitya1^" != "^show_symbol_availabilitya2)letmerge_symbol_metadatas{ty=ty1;indexing=idx1;availability=a1;implemented_in_ocaml=o1;occur_check=oc1}{ty=ty2;indexing=idx2;availability=a2;implemented_in_ocaml=o2;occur_check=oc2}={ty=TypeAssignment.merge_skematy1ty2;indexing=merge_indexingsidx1idx2;availability=merge_availabilitysa1a2;implemented_in_ocaml=o1||o2;occur_check=oc1&&oc2;}leto2l=functionTypeAssignment.Singlex->[x]|Overloadedl->lletmerge_envs{symbols=s1;overloading=o1}{symbols=s2;overloading=o2}=letsymbols=Symbol.QMap.unionmerge_symbol_metadatas1s2inletto_unite=ref[]inletoverloading=F.Map.union(funfl1l2->(* We give precedence to recent type declarations over old ones *)letto_u,l=TypeAssignment.undup_skemas(funx->(Symbol.QMap.findxsymbols).ty)(o2ll1@o2ll2)into_unite:=to_u::!to_unite;Somel)o1o2inletto_unite=List.concat!to_uniteinletsymbols=List.fold_right(fun(x,y)->Symbol.QMap.unifymerge_symbol_metadataxy)to_unitesymbolsin{overloading;symbols}letiter_namesf{overloading}=F.Map.iterfoverloadingletiter_symbolsf{symbols}=Symbol.QMap.iterfsymbolsletsame_symbol{symbols}xy=letuf=Symbol.QMap.get_ufsymbolsinSymbol.equal~ufxyletcompare_symbol{symbols}xy=letuf=Symbol.QMap.get_ufsymbolsinSymbol.compare~ufxyletundup{symbols}l=letuf=Symbol.QMap.get_ufsymbolsinSymbol.undup~uflletall_symbols{symbols}=Symbol.QMap.bindingssymbolsletmem_symbol{symbols}x=Symbol.QMap.memxsymbolsletcanon{symbols}x=canonsymbolsxendmoduleSymbolResolver:sigtyperesolution[@@derivingshow]valcompare:TypingEnv.t->resolution->resolution->intvalclone:resolution->resolutionvalmake:unit->resolutionvalresolve:TypingEnv.t->resolution->Symbol.t->unitvalresolved_to:TypingEnv.t->resolution->Symbol.toptionvalis_resolved_to:TypingEnv.t->resolution->Symbol.t->boolvalis_resolved_to_builtin:TypingEnv.t->resolution->boolend=structtyperesolution=Symbol.toptionref[@@derivingshow]letcloner=match!rwith|None->refNone|Somex->ref(Somex)letcompareenvr1r2=match!r1,!r2with|Somes1,Somes2->TypingEnv.compare_symbolenvs1s2|Some_,None->-1|None,Some_->1|_->0letmake()=refNoneletresolveenvrs=match!rwith|None->r:=Somes|Somes'->ifnot@@TypingEnv.same_symbolenvs'sthenanomaly("SymbolResolver: new "^Symbol.shows^" != old "^Symbol.shows');r:=Somesletresolved_toenvr=match!rwith|None->None|Somex->Some(TypingEnv.canonenvx)letis_resolved_toenvrs=matchresolved_toenvrwith|None->false|Somes1->TypingEnv.same_symbolenvss1letis_resolved_to_builtinenvr=matchresolved_toenvrwith|None->false|Somer->matchTypingEnv.resolve_symbol_optrenvwith|None->false|Somes->s.implemented_in_ocamlendmoduleScope=structtypelanguage=ScopeContext.language[@@derivingshow,ord]typet=|Boundoflanguage(* bound by a lambda, stays bound *)|Globalof{escape_ns:bool;(* when true name space elimination does not touch this constant *)resolved_to:SymbolResolver.resolution;}[@@derivingshow](* The compare function ignores the resolved_to field *)letcompareenvt1t2=matcht1,t2with|Boundb1,Boundb2->String.compareb1b2|Globalg1,Globalg2->letv=SymbolResolver.compareenvg1.resolved_tog2.resolved_toinifv=0thenBool.compareg1.escape_nsg2.escape_nselsev|Bound_,Global_->1|Global_,Bound_->-1letequalenvxy=compareenvxy=0letclone=functionBound_ast->t|Global{escape_ns;resolved_to}->Global{escape_ns;resolved_to=SymbolResolver.cloneresolved_to}moduleMap=Map.Make(structtypet=F.t*language[@@derivingshow,ord]end)moduleSet=Set.Make(structtypet=F.t*language[@@derivingshow,ord]end)letmkGlobal?(escape_ns=false)()=Global{escape_ns;resolved_to=SymbolResolver.make()}letmkResolvedGlobaltypessymb=letresolved_to=SymbolResolver.make()inSymbolResolver.resolvetypesresolved_tosymb;Global{escape_ns=true;resolved_to}endmoduleScopedTypeExpression=structopenScopeContextmoduleSimpleType=structtypet_=|Any|ConofF.t|AppofF.t*t*tlist|Arroft*tandt={it:t_;loc:Loc.t}[@@derivingshow]endtypet_=|Any|PropofAst.Structured.functionality|ConstofScope.t*F.t|AppofScope.t*F.t*e*elist|ArrowofMode.t*Ast.Structured.variadic*e*eande={it:t_;loc:Loc.t}[@@derivingshow]openFormatletarrs=0letapp=1letlvl_of=function|Arrow_->arrs|App_->app|_->2letrecis_prop=function|Propf->Somef|Any|Const_|App_->None|Arrow(_,_,_,t)->is_propt.itletrecpretty_efmt=function|Any->fprintffmt"any"|Const(_,c)->F.ppfmtc|Prop_->fprintffmt"prop"|App(_,f,x,xs)->fprintffmt"@[<hov 2>%a@ %a@]"F.ppf(Util.pplist(pretty_e_parens~lvl:app)" ")(x::xs)|Arrow(m,v,s,t)asp->(matchis_proppwith|None->fprintffmt"@[<hov 2>%a ->@ %a@]"(pretty_e_parens~lvl:arrs)spretty_e_loct|SomeFunction->fprintffmt"@[<hov 2>func%a@]"(pretty_propmvst)()|SomeRelation->fprintffmt"@[<hov 2>pred%a@]"(pretty_propmvst)())andpretty_propmvlrfmt()=letshow_var=functionAst.Structured.Variadic->".."|_->""inmatchr.itwith|Prop_->fprintffmt"."|_->fprintffmt"%a %s->@ %a"(*Mode.pretty m*)pretty_e_locl(show_varv)pretty_e_locrandpretty_e_parens~lvlfmt=function|twhenlvl>=lvl_oft.it->fprintffmt"(%a)"pretty_e_loct|t->pretty_e_locfmttandpretty_e_locfmt{it}=pretty_efmtitletpretty_efmt(t:e)=Format.fprintffmt"@[%a@]"pretty_e_loctletrecof_simple_type=function|SimpleType.Any->Any|Conc->Const(Scope.mkGlobal(),c)|App(c,x,xs)->App(Scope.mkGlobal(),c,of_simple_type_locx,List.mapof_simple_type_locxs)|Arr(s,t)->Arrow(Output,NotVariadic,of_simple_type_locs,of_simple_type_loct)andof_simple_type_loc{it;loc}={it=of_simple_typeit;loc}typev_=|LamofF.t*v_|Tyofe[@@derivingshow]typet={name:F.t;value:v_;nparams:int;loc:Loc.t;index:Ast.Structured.predicate_indexingoption;availability:Ast.Structured.symbol_availability;occur_check:bool;}[@@derivingshow]letprettyfmt{value}=letrecprettyfmt=function|Lam(_,x)->prettyfmtx|Tye->pretty_efmteinFormat.fprintffmt"@[%a@]"prettyvalueletreceqtenvctxt1t2=matcht1.it,t2.itwith|Const(Global_asb1,c1),Const(Global_asb2,c2)->Scope.compareenvb1b2==0&&F.equalc1c2|Const(Boundl1,c1),Const(Boundl2,c2)->Scope.compare_languagel1l2==0&&eq_varctxl1c1c2|App(Global_,c1,x,xs),App(Global_,c2,y,ys)->F.equalc1c2&&eqtenvctxxy&&Util.for_all2(eqtenvctx)xsys|App(Bound_,_,_,_),_->assertfalse|_,App(Bound_,_,_,_)->assertfalse|Arrow(m1,b1,s1,t1),Arrow(m2,b2,s2,t2)->Mode.comparem1m2==0&&b1=b2&&eqtenvctxs1s2&&eqtenvctxt1t2|Any,Any->true|Propf1,Propf2->Ast.Structured.compare_functionalityf1f2==0|_->falseletreceqenvctxt1t2=matcht1,t2with|Lam(c1,b1),Lam(c2,b2)->eqenv(push_ctx"lp"c1c2ctx)b1b2|Tyt1,Tyt2->eqtenvctxt1t2|_->falseletequalenv{name=n1;value=x}{name=n2;value=y}=F.equaln1n2&&eqenv(empty())xyletcompare__=assertfalseletrecsmart_map_scoped_loc_tyf({it;loc}asorig)=letit'=smart_map_scoped_tyfitinifit'==itthenorigelse{it=it';loc}andsmart_map_scoped_tyforig=matchorigwith|Any|Prop_->orig|Const((Scope.Bound_|Scope.Global{escape_ns=true}),_)->orig|Const(Scope.Global_asg,c)->letc'=fcinifc==c'thenorigelseConst(g,c')|App(Bound_,_,_,_)->assertfalse|App(Globalgass,c,x,xs)->letc'=ifg.escape_nsthencelsefcinletx'=smart_map_scoped_loc_tyfxinletxs'=smart_map(smart_map_scoped_loc_tyf)xsinifc'==c&&x'==x&&xs'==xsthenorigelseApp(s,c',x',xs')|Arrow(m,v,x,y)->letx'=smart_map_scoped_loc_tyfxinlety'=smart_map_scoped_loc_tyfyinifx'==x&&y'==ythenorigelseArrow(m,v,x',y')letrecsmart_map_tyef=function|Lam(c,t)asorig->lett'=smart_map_tyeftinift==t'thenorigelseLam(c,t')|Tytasorig->lett'=smart_map_scoped_loc_tyftinift==t'thenorigelseTyt'letsmart_mapf({name;value;nparams;loc;index;availability;occur_check}asorig)=letname'=fnameinletvalue'=smart_map_tyefvalueinifname==name'&&value'==valuethenorigelse{name=name';value=value';nparams;loc;index;availability;occur_check}endmoduleScopedTerm=structopenScopeContextmoduleSimpleTerm=structtypeimpl_kind=L2R|L2RBang|R2L[@@derivingshow]letis_implff=letopenAstinFunc.equalfFunc.implf||Func.equalfFunc.implbangf||Func.equalfFunc.rimplfletfunc_to_impl_kindf=letopenAstinifFunc.equalfFunc.implfthenL2RelseifFunc.equalfFunc.implbangfthenL2RBangelseifFunc.equalfFunc.rimplfthenR2Lelseanomaly("not an implication "^F.showf)(* User Visible *)typet_=|Implofimpl_kind*Loc.t*t*t(* `Impl(true,t1,t2)` ≡ `t1 => t2` and `Impl(false,t1,t2)` ≡ `t1 :- t2` *)|ConstofScope.t*F.t|Discard|VarofF.t*Loc.t*tlist|AppofScope.t*F.t*Loc.t*t*tlist|Lamof(F.t*Loc.t*Scope.language)option*ScopedTypeExpression.SimpleType.toption*t|OpaqueofCData.t|Castoft*ScopedTypeExpression.SimpleType.tandt={it:t_;loc:Loc.t}[@@derivingshow]typeconstant=intletmkGlobal~locc={loc;it=Const(Scope.mkGlobal~escape_ns:true(),Data.Symbol.get_func@@Constants.Map.findcData.Global_symbols.table.c2s)}letmkBound~loc~languagen={loc;it=Const(Boundlanguage,n)}letmkAppGlobal~loc~hdloccxxs={loc;it=App(Scope.mkGlobal~escape_ns:true(),Data.Symbol.get_func@@Constants.Map.findcData.Global_symbols.table.c2s,hdloc,x,xs)}letmkAppBound~loc~hdloc~languagenxxs={loc;it=App(Boundlanguage,n,hdloc,x,xs)}letmkVar~loc~hdlocnl={loc;it=Var(n,hdloc,l)}letmkOpaque~loco={loc;it=Opaqueo}letmkCast~loctty={loc;it=Cast(t,ty)}letmkDiscard~loc={loc;it=Discard}letmkLam~locn?tyt={loc;it=Lam(n,ty,t)}letmkImplication~loc~hdlocst={loc;it=Impl(L2R,hdloc,s,t)}letmkPi~loc~hdlocn~nloc?tyt={loc;it=App(Scope.mkGlobal~escape_ns:true(),F.pif,hdloc,{loc;it=Lam(Some(n,nloc,elpi_language),ty,t)},[])}letmkConj~loc~hdloc=function|[]->{loc;it=Const(Scope.mkGlobal~escape_ns:true(),F.truef)}|[x]->x|x::xs->{loc;it=App(Scope.mkGlobal~escape_ns:true(),F.andf,hdloc,x,xs)}letmkEq~loc~hdlocab={loc;it=App(Scope.mkGlobal~escape_ns:true(),F.eqf,hdloc,a,[b])}letmkNil~loc={it=Const(Scope.mkGlobal~escape_ns:true(),F.nilf);loc}letmkCons?loc~hdlocab=letloc=matchlocwithSomex->x|None->Loc.mergea.locb.locin{loc;it=App(Scope.mkGlobal~escape_ns:true(),F.consf,hdloc,a,[b])}letlist_to_lp_list~locl=letrecaux=function|[]->mkNil~loc|hd::tl->lettl=auxtlinmkCons~hdloc:lochdtlinauxlletne_list_to_lp_listl=matchList.revlwith|[]->anomaly"Ast.list_to_lp_list on empty list"|h::_->list_to_lp_list~loc:h.loclletreclp_list_to_list=function|{it=App(Global{escape_ns=true},c,_,x,[xs])}whenF.equalcF.consf->x::lp_list_to_listxs|{it=Const(Global{escape_ns=true},c)}whenF.equalcF.nilf->[]|{loc;it}->error~loc(Format.asprintf"%a is not a list"pp_t_it)endtype'scopew_ty_loc={scope:'scope;name:F.t;ty:TypeAssignment.tMutableOnce.t;loc:Loc.t}[@@derivingshow]typeconst=Scope.tw_ty_loc[@@derivingshow]typeuvar=unitw_ty_loc[@@derivingshow]typebinder=stringw_ty_loc[@@derivingshow]letmk_w_ty_loc?(ty=MutableOnce.makeF.dummyname)~scopename~loc:'aw_ty_loc={scope;name;ty;loc}letmk_global_const?ty?escape_ns~locname:const=mk_w_ty_loc?ty~scope:(Scope.mkGlobal?escape_ns())name~locletmk_bound_const?ty~langname~loc=mk_w_ty_loc?ty~scope:(Scope.Boundlang)name~locletmk_uvar?tyname~loc=mk_w_ty_loc?ty~scope:()name~locletmk_binder?ty~langname~loc=mk_w_ty_loc?ty~scope:lang~locnameletbind_const(n:binder):const={nwithscope=Scope.Boundn.scope}letconst_of_symb~typessymb~loc:const=mk_w_ty_loc~scope:(Scope.mkResolvedGlobaltypessymb)(Symbol.get_funcsymb)~locletclone_const?(clone_scope=Fun.id){scope;name;loc}=mk_w_ty_loc~scope:(clone_scopescope)name~loctypespill_info=|NoInfo(* before typing *)|Mainofint(* how many arguments it stands for *)|Phantomofint(* phantom term used during type checking *)[@@derivingshow]typet_=|ImplofSimpleTerm.impl_kind*Loc.t*t*t(* `Impl(true,t1,t2)` ≡ `t1 => t2` and `Impl(false,t1,t2)` ≡ `t1 :- t2` *)|Discardof{mutableheapify:bool}(* true if passed to code not doing OC *)|UVarofuvar*tlist|Appofconst*tlist|Lamofbinderoption*ScopedTypeExpression.eoption*t|CDataofCData.t|Spilloft*spill_inforef|Castoft*ScopedTypeExpression.eandt={it:t_;loc:Loc.t;ty:TypeAssignment.tMutableOnce.t}[@@derivingshow]letmkGlobalApp?ty?escape_ns~locfxs=App(mk_global_const?ty?escape_ns~locf,xs)letmkBoundApp?ty~lang~locfxs=App(mk_bound_const?ty~lang~locf,xs)letmkUVar?ty~locfxs=UVar(mk_uvar?ty~locf,xs)lettype_of{ty}:TypeAssignment.ty=assert(MutableOnce.is_setty);TypeAssignment.dereftyopenFormatletlam=0letapp=1letlvl_of=function|App(_,(_::_))->app|UVar(_,(_::_))->app|Lam_->lam|_->2letget_lam_name=functionNone->F.from_string"_"|Some(n,_)->nletmk_empty_lam_type=function|None->None|Some(name,loc,scope)->Some(mk_w_ty_locname~scope~loc)(* The type of the object being constructed is irrelevant since
build_infix_constant is used in the pretty printer of term and the type
of infix constants is not displayed
*)letbuild_infix_constantnameloc:t={loc;ty=MutableOnce.make(F.from_string"dummy");it=App(name,[])}letis_infix_constantf=letinfix=[F.andf;F.orf;F.eqf;F.isf;F.asf;F.consf]@List.mapF.from_string["^";"+";"-";"*";"/"]inList.memfinfixletrecinterspersee:'a->tlist=function|[]|[_]asa->a|x::xs->x::ex.loc::intersperseexsletrecpretty_lamfmtnsteit=(matchnwith|None->Format.fprintffmt"_"|Some{scope;name;ty}->fprintffmt"@[<hov 2>%a"F.ppname;ifMutableOnce.is_settythenfprintffmt": @[%a@] "TypeAssignment.pretty_mut_once(TypeAssignment.derefty)elseOption.iter(fprintffmt": %a "ScopedTypeExpression.pretty_e)ste);fprintffmt"\\@]@ %a"prettyit;andprettyfmt{it}=pretty_fmtitandpretty_fmt=function|Impl(L2R,_,t1,t2)->fprintffmt"@[<hov 2>(%a =>@ (%a))@]"prettyt1prettyt2|Impl(L2RBang,_,t1,t2)->fprintffmt"@[<hov 2>(%a =!=>@ (%a))@]"prettyt1prettyt2|Impl(R2L,_,t1,t2)->fprintffmt"@[<hov 2>(%a :-@ %a)@]"prettyt1prettyt2|App({name=f},[])->fprintffmt"%a"F.ppf|Discard_->fprintffmt"_"|Lam(n,ste,it)->pretty_lamfmtnsteit|App({name=f},[x])whenF.equalF.spillff->fprintffmt"{%a}"prettyx|App({name=f},x::xs)whenF.equalF.piff||F.equalF.sigmaff->fprintffmt"@[<hov 2>%a@ %a@]"F.ppf(Util.pplist~pplastelem:(pretty_parens_lam~lvl:app)(pretty_parens~lvl:app)" ")(x::xs)|App({scope=Global_;name=f}asn,x::xs)whenis_infix_constantf->fprintffmt"%a"(Util.pplist~boxed:true(pretty_parens~lvl:0)" ")(intersperse(build_infix_constantn)(x::xs))|App({name=f},x::xs)->fprintffmt"@[<hov 2>%a@ %a@]"F.ppf(Util.pplist~boxed:true(pretty_parens~lvl:app)" ")(x::xs)|UVar({name=f},[])->fprintffmt"@[%a@]"F.ppf|UVar({name=f},xs)->fprintffmt"@[%a@ %a@]"F.ppf(Util.pplist~boxed:true(pretty_parens~lvl:app)" ")xs|CDatac->fprintffmt"%a"CData.ppc|Spill(t,{contents=NoInfo})->fprintffmt"{%a}"prettyt|Spill(t,{contents=Main_})->fprintffmt"{%a}"prettyt|Spill(t,{contents=Phantomn})->fprintffmt"{%a}/*%d*/"prettytn|Cast(t,ty)->fprintffmt"(%a : %a)"prettytScopedTypeExpression.pretty_ety(* TODO pretty *)andpretty_parens~lvlfmt{it}=iflvl>=lvl_ofitthenfprintffmt"(%a)"pretty_itelsepretty_fmtitandpretty_parens_lam~lvlfmtx=matchx.itwithLam_->fprintffmt"%a"pretty_x.it|_->pretty_parens~lvlfmtxletequalenv?(types=true)t1t2=letreceqctxt1t2=matcht1.it,t2.itwith|Discard_,Discard_->true|UVar(n1,l1),UVar(n2,l2)->eq_uvarctxn1.namen2.name&&Util.for_all2(eqctx)l1l2|App({scope=Global_asb1;name=c1},xs),App({scope=Global_asb2;name=c2},ys)->Scope.equalenvb1b2&&F.equalc1c2&&Util.for_all2(eqctx)xsys|App({scope=Boundl1;name=c1},xs),App({scope=Boundl2;name=c2},ys)->l1=l2&&eq_varctxl1c1c2&&Util.for_all2(eqctx)xsys|Lam(None,ty1,b1),Lam(None,ty2,b2)->eqctxb1b2&&(nottypes||Option.equal(ScopedTypeExpression.eqtenv(empty()))ty1ty2)|Lam(Some{scope=l1;name=c1},ty1,b1),Lam(Some{scope=l2;name=c2},ty2,b2)->l1=l2&&eq(push_ctxl1c1c2ctx)b1b2&&(nottypes||Option.equal(ScopedTypeExpression.eqtenv(empty()))ty1ty2)|Spill(b1,n1),Spill(b2,n2)->n1==n2&&eqctxb1b2|CDatac1,CDatac2->CData.equalc1c2|Cast(t1,ty1),Cast(t2,ty2)->eqctxt1t2&&(nottypes||ScopedTypeExpression.eqtenv(empty())ty1ty2)|Impl(b1,_,s1,t1),Impl(b2,_,s2,t2)->b1=b2&&eqctxt1t2&&eqctxs1s2|_->falseinletb=eq(empty())t1t2inbletcompare__=assertfalseletin_scoped_term,out_scoped_term,is_scoped_term=letopenCDatainlet{cin;cout;isc}=declare{data_name="hidden_scoped_term";data_pp=pretty;data_compare=(fun__->assertfalse);data_hash=Hashtbl.hash;data_hconsed=false;}incin,cout,iscletrecof_simple_term~loc=function|SimpleTerm.Discard->Discard{heapify=false}|Impl(b,loc,t1,t2)->Impl(b,loc,of_simple_term_loct1,of_simple_term_loct2)|Const(scope,c)->App(mk_w_ty_loc~scopec~loc,[])|Opaquec->CDatac|Cast(t,ty)->Cast(of_simple_term_loct,ScopedTypeExpression.of_simple_type_locty)|Lam(c,ty,t)->Lam(mk_empty_lam_typec,Option.mapScopedTypeExpression.of_simple_type_locty,of_simple_term_loct)|App(s,c,cloc,x,xs)whenSimpleTerm.is_implfc->beginmatchxswith|[y]->Impl(SimpleTerm.func_to_impl_kindc,cloc,of_simple_term_locx,of_simple_term_locy)|_->error~loc"Use of App for Impl is allowed, but the length of the list in 3rd position must be 1"end|App(s,c,cloc,x,xs)->App(mk_w_ty_loc~scope:sc~loc,of_simple_term_locx::List.mapof_simple_term_locxs)|Var(c,cloc,xs)->UVar(mk_uvarc~loc:cloc,List.mapof_simple_term_locxs)andof_simple_term_loc{SimpleTerm.it;loc}=matchitwith|Opaquecwhenis_scoped_termc->out_scoped_termc|_->{it=of_simple_term~locit;loc;ty=MutableOnce.make(F.from_string"Ty")}letunlock{it}=it(* naive, but only used by macros *)letfresh=ref0letfresh()=incrfresh;F.from_string(Format.asprintf"%%bound%d"!fresh)letrecrenamelcdt=matchtwith|Impl(b,loc,t1,t2)->Impl(b,loc,rename_loclcdt1,rename_loclcdt2)|App({scope=Boundl';name=c';ty;loc},xs)whenl=l'&&F.equalcc'->(* NOTE: the name in mutable once should be renamed *)App({scope=Boundl;name=d;ty;loc},List.map(rename_loclcd)xs)|App(n,xs)->App(n,List.map(rename_loclcd)xs)|Lam(Some{scope=l';name=c'},_,_)whenl=l'&&F.equalcc'->t|Lam(v,tya,t)->Lam(v,tya,rename_loclcdt)|Spill(t,i)->Spill(rename_loclcdt,i)|Cast(t,ty)->Cast(rename_loclcdt,ty)|UVar(v,xs)->UVar(v,List.map(rename_loclcd)xs)|Discard_|CData_->tandrename_loclcd{it;ty;loc}={it=renamelcdit;ty;loc}letrecclone_loc~loc{it}={it=clone~locit;loc;ty=TypeAssignment.new_ty()}andclone~loc=function|Impl(b,loc,l,r)->Impl(b,loc,clone_loc~locl,clone_loc~locr)|Lam(n,ty,bo)->Lam(Option.mapclone_constn,ty,clone_loc~locbo)|Discard{heapify}->Discard{heapify}|UVar(v,xs)->UVar(clone_constv,List.map(clone_loc~loc)xs)|App(g,xs)->App(clone_constg,List.map(clone_loc~loc)xs)|CData_ast->t|Spill(t,_)->Spill(clone_loc~loct,refNoInfo)|Cast(t,ty)->Cast(clone_loc~loct,ty)letbetatargs=letrecfvacc{it}=matchitwith|Impl(_,_,a,b)->List.fold_leftfvacc[a;b]|UVar(_,args)->List.fold_leftfvaccargs|App({scope=Boundl;name=c},xs)->List.fold_leftfv(Scope.Set.add(c,l)acc)xs|App({scope=Global_},xs)->List.fold_leftfvaccxs|Lam(None,_,t)->fvacct|Lam(Some{scope=c;name=l},_,t)->Scope.Set.unionacc@@Scope.Set.remove(l,c)(fvScope.Set.emptyt)|Spill(t,_)->fvacct|Cast(t,_)->fvacct|Discard_|CData_->accinletrecload_subst~loct(args:tlist)mapfvset=matcht,argswith|Lam(None,_,t),_::xs->load_subst_loctxsmapfvset|Lam(Some{scope=l;name=c},_,t),x::xs->load_subst_loctxs(Scope.Map.add(c,l)xmap)(fvfvsetx)|t,xs->app~loc(substmapfvsett)xsandload_subst_loc{it;loc}argsmapfvset=load_subst~locitargsmapfvsetandsubst(map:tScope.Map.t)fvt=matchtwith|Impl(b,loc,t1,t2)->Impl(b,loc,subst_locmapfvt1,subst_locmapfvt2)|Lam(None,ty,t)->Lam(None,ty,subst_locmapfvt)|Lam(Some{scope=c;name=l}asn,ty,t)whennot@@Scope.Map.mem(l,c)map&¬@@Scope.Set.mem(l,c)fv->Lam(n,ty,subst_locmapfv@@t)|Lam(Some{scope=l;name=c;ty=tya;loc},ty,t)->letd=fresh()inLam(Some{scope=l;name=d;ty=tya;loc},ty,subst_locmapfv@@rename_loclcdt)|App({scope=Boundl;name=c},xs)whenScope.Map.mem(c,l)map->lethd=Scope.Map.find(c,l)mapinunlock@@app_lochd(List.map(subst_locmapfv)xs)|App(n,xs)->App(n,List.map(subst_locmapfv)xs)|UVar(c,xs)->UVar(c,List.map(subst_locmapfv)xs)|Spill(t,i)->Spill(subst_locmapfvt,i)|Cast(t,ty)->Cast(subst_locmapfvt,ty)|Discard_|CData_->tandsubst_locmapfv{it;ty;loc}={loc;it=(substmapfvit);ty}andapp_loc{it;loc;ty}args:t={loc;it=(app~locitargs);ty}andapp~loct(args:tlist)=ifargs=[]thentelsematchtwith|App(n,xs)->App(n,xs@args)|UVar(c,xs)->UVar(c,xs@args)|Impl(_,_,_,_)->error~loc"cannot apply impl"|CData_->error~loc"cannot apply cdata"|Spill_->error~loc"cannot apply spill"|Discard_->error~loc"cannot apply discard"|Cast_->error~loc"cannot apply cast"|Lam_->load_subst~loctargsScope.Map.emptyScope.Set.emptyinifargs=[]thenunlocktelseload_subst_loctargsScope.Map.emptyScope.Set.emptyletbetatargs=(* Format.eprintf "beta %a\n" pretty t; *)lett=betatargsin(* Format.eprintf "beta result %a\n" pretty_ t; *)tmoduleQTerm=structincludeSimpleTermletapply_elpi_var_from_quotation({SimpleTerm.it;loc}aso)l=ifl=[]thenoelseletl=List.mapof_simple_term_loclinmatchitwith|SimpleTerm.Opaqueowhenis_scoped_termo->beginmatchout_scoped_termowith|{it=UVar(f,xs);loc=loc';ty}->{SimpleTerm.loc;it=SimpleTerm.Opaque(in_scoped_term@@{it=UVar(f,xs@l);loc=loc';ty})}|{it=App({scope=Boundg}asn,[]);loc=loc';ty}wheng=elpi_language->{SimpleTerm.loc;it=SimpleTerm.Opaque(in_scoped_term@@{it=App(n,l);loc=loc';ty})}|x->anomaly~loc(Format.asprintf"The term is not an elpi varible coming from a quotation: @[%a@]"prettyx)end|x->anomaly~loc(Format.asprintf"The term is not term coming from a quotation: @[%a@]"pp_t_x)letextend_spill_hyp_from_quotation{SimpleTerm.it;loc}hyps=matchitwith|SimpleTerm.Opaqueowhenis_scoped_termo->beginmatchout_scoped_termowith|{it=Spill(t,i);loc}->letimpl={loc;it=Impl(L2R,loc,list_to_lp_list~lochyps,{loc;it=Opaque(in_scoped_termt)})}in{loc;it=Opaque(in_scoped_term@@{it=Spill(of_simple_term_locimpl,i);loc;ty=MutableOnce.make(F.from_string"Ty")})}|_->anomaly~loc(Format.asprintf"The term is not a spill coming from a quotation: @[%a@]"pp_t_it)end|x->anomaly~loc(Format.asprintf"The term is not coming from a quotation: @[%a@]"pp_t_x)letis_spill_from_quotation{SimpleTerm.it}=matchitwith|SimpleTerm.Opaqueowhenis_scoped_termo->beginmatchout_scoped_termowith|{it=Spill_}->true|_->falseend|_->falseendletis_var=functionUVar_->true|_->falseendmoduleScopeTypeExpressionUniqueList=structtypet=ScopedTypeExpression.tlist[@@derivingshow,ord]letprettyfmtl=pplistScopedTypeExpression.pretty";"fmtlletmaket=[t]letsmart_map=smart_mapletappendenvxt=x::List.filter(funy->not@@ScopedTypeExpression.equalenvxy)tletmergeenvt1t2=List.fold_left(funaccx->appendenvxacc)(List.revt1)t2letfold=List.fold_leftendmoduleState=Data.StatemoduleQuotationHooks=structtypequotation=language:Scope.language->State.t->Ast.Loc.t->string->ScopedTerm.SimpleTerm.ttypedescriptor={named_quotations:quotationStrMap.t;default_quotation:quotationoption;singlequote_compilation:(string*quotation)option;backtick_compilation:(string*quotation)option;}letnew_descriptor()=ref{named_quotations=StrMap.empty;default_quotation=None;singlequote_compilation=None;backtick_compilation=None;}letdeclare_singlequote_compilation~descriptornamef=match!descriptorwith|{singlequote_compilation=None}->descriptor:={!descriptorwithsinglequote_compilation=Some(name,f)};name|{singlequote_compilation=Some(oldname,_)}->error("Only one custom compilation of 'ident' is supported. Current: "^oldname^", new: "^name)letdeclare_backtick_compilation~descriptornamef=match!descriptorwith|{backtick_compilation=None}->descriptor:={!descriptorwithbacktick_compilation=Some(name,f)};name|{backtick_compilation=Some(oldname,_)}->error("Only one custom compilation of `ident` is supported. Current: "^oldname^", new: "^name)letset_default_quotation~descriptorf=descriptor:={!descriptorwithdefault_quotation=Somef}letregister_named_quotation~descriptor~name:nf=descriptor:={!descriptorwithnamed_quotations=StrMap.addnf!descriptor.named_quotations};nendmoduleArity=structtypet=int*Loc.t[@@derivingshow,ord]endexceptionCompileErrorofLoc.toption*stringleterror?locmsg=raise(CompileError(loc,msg))