1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756(* elpi: embedded lambda prolog interpreter *)(* license: GNU Lesser General Public License Version 2.1 or later *)(* ------------------------------------------------------------------------- *)(* Internal term representation *)openElpi_utilopenElpi_parsermoduleFmt=FormatmoduleF=Ast.FuncopenUtil(**
Used to index the parameters of a predicate P
- [MapOn N] -> N-th argument at depth 1 (head symbol only)
- [Hash L] -> L is the list of depths given by the urer for the parameters of
P. Indexing is done by hashing all the parameters with a non
zero depth and comparing it with the hashing of the parameters
of the query
- [DiscriminationTree L] ->
we use the same logic of Hash, except we use DiscriminationTree to discriminate
clauses
*)typeindexing=|MapOnofint|Hashofintlist|DiscriminationTreeofintlist[@@derivingshow,ord](*
Used in the lightweight discrimination tree to
statically verify whether two rules overlap.
- has_cut:
Instead of storing the full body of the clause in the
lightweight discrimination tree, we simply record
whether the rule contains a cut.
- arg_nb:
In the discrimination tree, variadic arguments are not included in the path.
However, the number of arguments is used as a discriminator between two rules.
arg_nb tells the number of arguments in the clause when it was added to the trie.
*)typeoverlap_clause={overlap_loc:Loc.toption;has_cut:bool;mutabletimestamp:intlist;arg_nb:int}[@@derivingshow]typeoverlap=|Allowed|Forbiddenofoverlap_clauseDiscrimination_tree.t[@@derivingshow]letmk_Forbiddenindexing=Forbidden(matchindexingwith|MapOni->Discrimination_tree.empty_dt(List.init(i+1)(funj->ifj=ithen1else0))|Hashl->Discrimination_tree.empty_dtl|DiscriminationTreel->Discrimination_tree.empty_dtl)typepred_info={indexing:indexing;mode:Mode.hos;overlap:overlap;has_local_without_cut:Loc.toption;(* retroactive check: has a catch all and loads a rule without cut *)occur_check:bool;}[@@derivingshow]letsame_indexing{indexing=i1}{indexing=i2}=compare_indexingi1i2==0(******************************************************************************
Terms: data type definition and printing
******************************************************************************)(* Heap and Stack
*
* We use the same data type (term) the following beasts:
* preterm = Pure term <= Heap term <= Stack term
*
* - only Stack terms can contain Arg nodes
* - Heap terms can contain UVar nodes
* - Pure terms contain no Arg and no UVar nodes
* - a preterm is a Pure term that may contain "%Arg3" constants. These
* constants morally represent Arg nodes
*
* Preterms are only used during compilation. Beta-reduction, needed for
* macro expansion for example, is only defined on Heap terms. We hence
* separate the compilation of clauses into:
* AST -> preterm -> term -> clause
*
* Heap and Stack terms are used during execution. The query if the
* root of Heap terms, clauses are Stack terms and are eventually copied
* to the Heap.
* Invariant: a Heap term never points to a Stack term.
*
*)moduleTerm=struct(* To be instantiated after the dummy term is defined *)letpp_oref=mk_spaghetti_printer()letid_term=UUID.make()(* This data type is open since runtime (traced or not) adds to it
its own representation of constraints, projectable to the type
suspended_goal below *)type'unification_defstuck_goal_kind=..letpp_stuck_goal_kindp1fmtx=()letshow_stuck_goal_kindp1_=""letequal_stuck_goal_kind_xy=x==ytype'unification_defstuck_goal_kind+=|Unificationof'unification_deftypettype=|TConstofconstant|TAppofconstant*ttype*ttypelist|TPredofbool*((Mode.t*ttype)list)(* The bool is for functionality *)|TArrofttype*ttype|TCDataofCData.t|TLamofttype(* this is for parametrized typeabbrevs *)[@@derivingshow,ord]typebuiltin_predicate=|Cut|And|Impl|ImplBang|RImpl|Pi|Sigma|Eq|Match|Findall|Delay|Hostofconstant[@@derivingord,show]letbuiltin_predicates=[Cut;And;Impl;ImplBang;RImpl;Pi;Sigma;Eq;Match;Findall;Delay]letbuiltin_predicate_max=List.lengthbuiltin_predicatesletfunc_of_builtin_predicatef=function|Cut->F.cutf|And->F.andf|Impl->F.implf|ImplBang->F.implbangf|RImpl->F.rimplf|Pi->F.pif|Sigma->F.sigmaf|Eq->F.eqf|Match->F.pmf|Findall->F.from_string"findall_solutions"|Delay->F.from_string"declare_constraint"|Hostc->fcletshow_builtin_predicate?tablef=function|Hostc->f?tablec|x->F.show(func_of_builtin_predicate(fun_->assertfalse)x)letconst_of_builtin_predicate=function|Cut->-1|And->-2|Impl->-3|RImpl->-4|Pi->-5|Sigma->-6|Eq->-7|Match->-8|Findall->-9|Delay->-10|ImplBang->-11|Hostc->cletis_builtin_predicatec=-builtin_predicate_max<=c&&c<=-1letbuiltin_predicate_of_const=function|-1->Cut|-2->And|-3->Impl|-4->RImpl|-5->Pi|-6->Sigma|-7->Eq|-8->Match|-9->Findall|-10->Delay|-11->ImplBang|_->assertfalselet()=assert(List.for_all(funp->is_builtin_predicate@@const_of_builtin_predicatep)builtin_predicates)let()=assert(List.for_all(funp->p=builtin_predicate_of_const@@const_of_builtin_predicatep)builtin_predicates)letmap_builtin_predicatef=function|Hostx->Host(fx)|x->xtypeterm=(* Pure terms *)|Constofconstant|Lamofterm|Appofconstant*term*termlist(* Optimizations *)|Consofterm*term|Nil|Discard(* FFI *)|Builtinofbuiltin_predicate*termlist|CDataofCData.t(* Heap terms: unif variables in the query *)|UVarofuvar*int(* number of arguments *)|AppUVarofuvar*termlist(* arguments *)(* Stack terms: unif variables in the rules *)|Argofint*int(* number of arguments *)|AppArgofint*termlist(* arguments *)anduvar={vardepth:int;(* depth at creation time *)mutablecontents:term[@printer(pp_spaghetti_any~id:id_termpp_oref)];mutableuid_private:int;(* negative if it blocks a constraint *)}[@@derivingshow,ord]letcons2tcons?(loc=Loc.initial"")=functionConstt->TConstt|_->anomaly~loc"Unreachable branch"(* we use this projection to be sure we ignore the sign *)letuvar_id{uid_private}=absuid_private[@@inline];;letuvar_is_a_blocker{uid_private}=uid_private<0[@@inline];;letuvar_isnt_a_blocker{uid_private}=uid_private>0[@@inline];;letuvar_set_blockerr=r.uid_private<--(uvar_idr)[@@inline];;letuvar_unset_blockerr=r.uid_private<-(uvar_idr)[@@inline];;typeclause={depth:int;args:termlist;hyps:termlist;vars:int;oc:bool;(* occur_check *)mode:Mode.hos;(* CACHE to avoid allocation in get_clauses *)loc:Loc.toption;(* debug *)mutabletimestamp:intlist;(* for grafting *)}[@@derivingshow,ord]typegrafting_time=intlist[@@derivingshow,ord]letcompare_constant=Util.compare_constanttypetimes=(grafting_time*constant)StrMap.t[@@derivingshow,ord]typestuck_goal={mutableblockers:blockers;kind:unification_defstuck_goal_kind;}andblockers=uvarlistandunification_def={adepth:int;env:termarray;bdepth:int;a:term;b:term;matching:bool;oc:bool;}andclause_src={hdepth:int;hsrc:term}andprolog_prog={src:clause_srclist;(* hypothetical context in original form, for CHR *)index:index;}(* These two are the same, but the latter should not be mutated *)andclause_list=clauseBl.tandindex=first_lvl_idxandfirst_lvl_idx={idx:second_lvl_idxPtmap.t;time:int;(* ticking clock, to timestamp clauses so to recover total order after retrieval if necessary. positive at compile time, negative at run time *)times:times;(* timestamp of named clauses, for grafting at compile time *)}andsecond_lvl_idx=|TwoLevelIndexof{mode:Mode.hos;argno:int;all_clauses:clause_list;(* when the query is flexible *)flex_arg_clauses:clause_list;(* when the query is rigid but arg_id has nothing *)arg_idx:clause_listPtmap.t;(* when the query is rigid (includes in each binding flex_arg_clauses) *)}|BitHashof{mode:Mode.hos;args:intlist;args_idx:clause_listPtmap.t;(* clause, insertion time *)}|IndexWithDiscriminationTreeof{mode:Mode.hos;arg_depths:intlist;(* the list of args on which the trie is built *)args_idx:clauseDiscrimination_tree.t;}[@@derivingshow]typeoccur_check=|Skip|No|Checkofuvarletstop=reffalseletclose_index({idx;time;times}:index):index={idx=idx;time=0;times=StrMap.empty}typeconstraints=stuck_goallisttypehyps=clause_srclisttypesuspended_goal={context:hyps;goal:int*term;blockers:blockers;}letmkLamx=Lamx[@@inline]letmkAppcxxs=App(c,x,xs)[@@inline]letmkConshdtl=Cons(hd,tl)[@@inline]letmkNil=NilletmkDiscard=DiscardletmkBuiltincargs=Builtin(c,args)[@@inline]letmkCDatac=CDatac[@@inline]letmkUVarrano=UVar(r,ano)[@@inline]letmkAppUVarrargs=AppUVar(r,args)[@@inline]letmkArgiano=Arg(i,ano)[@@inline]letmkAppArgiargs=AppArg(i,args)[@@inline]moduleC=structlet{CData.cin=in_int;isc=is_int;cout=out_int}asint=Ast.cintletis_int=is_intletto_int=out_intletof_intx=CData(in_intx)let{CData.cin=in_float;isc=is_float;cout=out_float}asfloat=Ast.cfloatletis_float=is_floatletto_float=out_floatletof_floatx=CData(in_floatx)let{CData.cin=in_string;isc=is_string;cout=out_string}asstring=Ast.cstringletis_string=is_stringletto_stringx=out_stringxletof_stringx=CData(in_stringx)letloc=Ast.clocletis_loc=loc.CData.iscletto_loc=loc.CData.coutletof_locx=CData(loc.CData.cinx)endletdestConst=functionConstx->x|_->assertfalse(* Our ref data type: creation and dereference. Assignment is defined
After the constraint store, since assigning may wake up some constraints *)letoref=letuid=ref0infun~depth:vardepthx->incruid;assert(!uid>0);{vardepth;contents=x;uid_private=!uid}let(!!){contents=x}=x(* Arg/AppArg point to environments, here the empty one *)typeenv=termarrayletempty_env=[||]endincludeTerm(* Object oriented State.t: borns at compilation time and survives as run time *)moduleState:sigtypedescriptorvalnew_descriptor:unit->descriptorvalmerge_descriptors:descriptor->descriptor->descriptor(* filled in with components *)type'acomponentvaldeclare:descriptor:descriptor->name:string->pp:(Format.formatter->'a->unit)->init:(unit->'a)->clause_compilation_is_over:('a->'a)->?goal_compilation_begins:('a->'a)->compilation_is_over:('a->'aoption)->execution_is_over:('a->'aoption)->unit->'acomponent(* an instance of the State.t type *)typet(* Lifetime:
- init (called once)
- end_clause_compilation (called after every clause)
- end_compilation (just once before running)
- end_execution (just once after running)
*)valinit:descriptor->tvalend_clause_compilation:t->tvalbegin_goal_compilation:t->tvalend_compilation:t->tvalend_execution:t->tvalget:'acomponent->t->'avalset:'acomponent->t->'a->tvaldrop:'acomponent->t->tvalupdate:'acomponent->t->('a->'a)->tvalupdate_return:'acomponent->t->('a->'a*'b)->t*'bvalpp:Format.formatter->t->unitvaldummy:tend=structtypestage=|Dummy|Compile_prog|Compile_goal|Run|Halttype'acomponent=stringtypeextension={init:unit->Obj.t;end_clause:Obj.t->Obj.t;begin_goal:Obj.t->Obj.t;end_comp:Obj.t->Obj.toption;end_exec:Obj.t->Obj.toption;pp:Format.formatter->Obj.t->unit;}typedescriptor=extensionStrMap.treftypet={data:Obj.tStrMap.t;stage:stage;extensions:descriptor}letdummy:t={data=StrMap.empty;stage=Dummy;extensions=refStrMap.empty}letnew_descriptor():descriptor=refStrMap.emptyletmerge_descriptorsm1m2=ref(StrMap.merge(funne1e2->matche1,e2with|None,None->None|Somex,None->Somex|None,Somex->Somex|Some_,Some_->error("The state cannot contain two components named "^n))!m1!m2)letgetname{data=t}=tryObj.obj(StrMap.findnamet)withNot_found->anomaly("State.get: component "^name^" not found")letsetname({data}asx)v={xwithdata=StrMap.addname(Obj.reprv)data}letdropname({data}asx)={xwithdata=StrMap.removenamedata}letupdatename({data}asx)f={xwithdata=StrMap.addname(Obj.repr(f(Obj.obj(StrMap.findnamedata))))data}letupdate_returnnametf=letx=getnametinletx,res=fxinlett=setnametxint,resletdeclare~descriptor:extensions~name~pp~init~clause_compilation_is_over?(goal_compilation_begins=funx->x)~compilation_is_over~execution_is_over()=ifStrMap.memname!extensionsthenanomaly("Extension "^name^" already declared");extensions:=StrMap.addname{init=(funx->Obj.repr(initx));pp=(funfmtx->ppfmt(Obj.objx));end_clause=(funx->Obj.repr(clause_compilation_is_over(Obj.objx)));begin_goal=(funx->Obj.repr(goal_compilation_begins(Obj.objx)));end_comp=(funx->option_mapObj.repr(compilation_is_over(Obj.objx)));end_exec=(funx->option_mapObj.repr(execution_is_over(Obj.objx)));}!extensions;nameletinitextensions:t=letdata=StrMap.fold(funname{init}acc->leto=init()inStrMap.addnameoacc)!extensionsStrMap.emptyin{data;stage=Compile_prog;extensions;}letend_clause_compilation{data=m;stage=s;extensions}:t=assert(s=Compile_prog);{data=StrMap.fold(funnameobjacc->leto=(StrMap.findname!extensions).end_clauseobjinStrMap.addnameoacc)mStrMap.empty;stage=s;extensions}letbegin_goal_compilation{data=m;stage=s;extensions}:t=assert(s=Compile_prog);{data=StrMap.fold(funnameobjacc->leto=(StrMap.findname!extensions).begin_goalobjinStrMap.addnameoacc)mStrMap.empty;stage=Compile_goal;extensions}letend_compilation{data=m;stage=s;extensions}:t=assert(s=Compile_goal);{data=StrMap.fold(funnameobjacc->match(StrMap.findname!extensions).end_compobjwith|None->acc|Someo->StrMap.addnameoacc)mStrMap.empty;stage=Run;extensions}letend_execution{data=m;stage=s;extensions}:t=assert(s=Run);{data=StrMap.fold(funnameobjacc->match(StrMap.findname!extensions).end_execobjwith|None->acc|Someo->StrMap.addnameoacc)mStrMap.empty;stage=Halt;extensions}letppfmt{data=t;stage=s;extensions}:unit=StrMap.iter(funname{pp}->tryppfmt(StrMap.findnamet)withNot_found->())!extensionsendletelpi_state_descriptor=State.new_descriptor()typecore_symbol=As|Uv|ECons|ENil[@@derivingenum,ord,show]letfunc_of_core_symbol=function|As->F.asf|Uv->F.from_string"uvar"|ECons->F.consf|ENil->F.nilfletis_core_symbolf=letrecauxi=ifi<max_core_symbolthenF.equalf(func_of_core_symbol(Option.get(core_symbol_of_enumi)))||aux(i+1)elsefalseinaux0(* Globally unique identifier for symbols with a quotient *)moduleSymbol:sigtypesymbol[@@derivingshow]moduleUF:Union_find.Swithtypekey=symboltype'amerge=(symbol->'a->'a->'a)moduleRawMap:Map.Swithtypekey=symbolmoduleQMap:sigtype'at[@@derivingshow]valempty:'atvaladd:symbol->'a->'at->'atvalfind:symbol->'at->'avalfind_opt:symbol->'at->'aoptionvalunion:'amerge->'at->'at->'atvalgive_uf:'at->UF.tvalunify:'amerge->symbol->symbol->'at->'atvalmapi:(symbol->symbol)->('a->'a)->'at->'atvalmap:('a->'b)->'at->'btvalfold:(symbol->'a->'b->'b)->'at->'b->'bvaliter:(symbol->'a->unit)->'at->unitvalmem:symbol->'at->boolvalbindings:'at->(symbol*'a)listvalget_uf:'at->UF.tendtypet=symbol[@@derivingshow]typeprovenance=Elpi_parser.Ast.Structured.provenance[@@derivingshow,ord]valequal:uf:UF.t->t->t->boolvalcompare:uf:UF.t->t->t->intvalmake:provenance->F.t->tvalmake_builtin:?variant:int->F.t->tvalmake_variant_builtin:F.t->t*int(* variant *)valget_loc:t->Loc.tvalget_provenance:t->provenancevalget_str:t->stringvalget_func:t->F.tvalis_builtin:t->F.t->boolvalundup:uf:UF.t->tlist->tlistvalpretty:t->string(* val map_func : (F.t -> F.t) -> t -> t *)end=structtypeprovenance=Elpi_parser.Ast.Structured.provenance[@@derivingshow,ord]typesymbol=provenance*F.t[@@derivingshow,ord]letcompare_symbol(p1,f1)(p2,f2)=letx=F.comparef1f2inifx=0thencompare_provenancep1p2elsextype'amerge=(symbol->'a->'a->'a)moduleO=structtypet=symbol[@@derivingshow,ord]endmoduleRawMap=Map.Make(O)moduleUF=Elpi_util.Union_find.Make(O)typet=symbol[@@derivingshow]openElpi_parser.Ast.Structuredletpretty(prov,f)=F.showf^matchprovwith|Core->" (core symbol)"|File_->""|Builtin{variant}->ifvariant<>0then" (variant "^string_of_intvariant^")"else""moduleQMap=structtype'at=UF.t*'aRawMap.t[@@derivingshow]letempty=UF.empty,RawMap.emptyletget_uf(u,_)=uletunifyfs1s2(uf,m)=letx,uf=matchfsts1,fsts2with|Builtin_,Builtin_->anomaly"Builtins cannot be declared twice"|Core,Core->anomaly"Core symbols cannot be declared twice"(* we use the (possibly) pre-allocated builtin as the canonical *)|File_,Builtin_->UF.unionufs1~canon:s2|File_,Core->UF.unionufs1~canon:s2|_->UF.unionuf~canon:s1s2inmatchxwith|None->uf,m|Somex->letcanonic_x=UF.findufxinmatchRawMap.find_optcanonic_xm,RawMap.find_optxmwith|None,None->uf,m|Somecanonic_value,None->uf,m|None,Somevalue->uf,RawMap.addcanonic_xvaluem|>RawMap.removex|Somecanonic_value,Somevalue->uf,RawMap.addcanonic_x(fcanonic_xvaluecanonic_value)mletaddsa(uf,m)=lets'=UF.findufsinuf,RawMap.adds'amletfinds(uf,m)=lets'=UF.findufsintryRawMap.finds'mwithNot_found->anomaly("Missing entry from QMap: "^show_symbols)letfind_opts(uf,m)=RawMap.find_opt(UF.findufs)mletunionf(uf1,m1)(uf2,m2)=letuf=UF.mergeuf1uf2inuf,RawMap.union(funsab->Some(f(UF.findufs)ab))m1m2letmapmv(uf,m)=uf,RawMap.mapmvmletmapimkmv(uf,m)=letuf=UF.mapimkufinletm=RawMap.fold(funkvacc->RawMap.add(mkk)(mvv)acc)RawMap.emptyminuf,mletgive_uf(a,_)=aletfoldf(_,m)a=RawMap.foldfmaletmems(uf,m)=lets'=UF.findufsinRawMap.mems'mletiterf(_,m)=RawMap.iterfmletbindings(_,m)=RawMap.bindingsmendletequal~ufxy=compare(UF.findufx)(UF.findufy)=0letcompare~ufxy=compare(UF.findufx)(UF.findufy)letrecundup~uf=function|[]->[]|x::xs->letx=UF.findufxinifList.exists(funy->compare~ufxy=0)xsthenundup~ufxselsex::undup~ufxsletis_builtin(p,f)s=F.equalfs&&matchpwithBuiltin{variant}->variant=0|_->falseletget_provenance(l,_)=lletget_loc(l,f)=matchlwith|Filel->l|Core->Loc.initial("("^__FILE__^":"^F.showf^")")|Builtin{variant}->Loc.initial("(ocaml:"^F.showf^":"^string_of_intvariant^")")letget_str(_,f)=F.showfletget_func(_,f)=fletmakeprovname=prov,nameletmake_builtin?(variant=0)name=Builtin{variant},nameletmake_variant_builtin=letstate=refF.Map.emptyinletincrname=letn=tryF.Map.findname!statewithNot_found->0inletn=n+1instate:=F.Map.addnamen!state;ninfunname->letvariant=incrnamein(Builtin{variant},name),variantend(* This module contains the symbols reserved by Elpi and the ones
declared by the API client via declare_global_symbol statically
(eg the API must be called in a OCaml toplevel value).
These symbols are part of any Elpi program.
The runtime only uses the symbols listed in the module signature,
the declared ones are read by the compiler and propagated to the runtime.
*)moduleGlobal_symbols:sig(* Table used at link time *)typet={(* Ast (functor name) -> negative int n (constant) * hashconsed (Const n) *)mutables2ct:(constant*term)Symbol.RawMap.t;mutablec2s:Symbol.symbolConstants.Map.t;(* negative *)mutablelast_global:int;(* Once the system is initialized this shall change no more *)mutablelocked:bool;}valtable:t(* Static initialization, eg link time *)valdeclare_global_symbol:?variant:int->string->constant(* Used by auto-generated code, eg ADT *)valdeclare_overloaded_global_symbol:string->constant*intvallock:unit->unitopenSymbol(* builtin predicates *)valcut:symbolvaland_:symbolvalimpl:symbolvalrImpl:symbolvalpi:symbolvalsigma:symbolvaleq:symbolvalmatch_:symbolvalfindall:symbolvaldelay:symbol(* core symbols *)valas_:symbolvaluvar:symbolvalnil:symbolvalcons:symbol(* internal *)valuvarc:constant(* needed by runtime/unif *)valasc:constant(* needed by runtime/unif *)valorc:constant(* needed by coq-elpi *)valnilc:constant(* needed by indexing *)valconsc:constant(* needed by indexing *)end=structtypet={mutables2ct:(constant*term)Symbol.RawMap.t;mutablec2s:Symbol.tConstants.Map.t;mutablelast_global:int;mutablelocked:bool;}[@@derivingshow]lettable={last_global=-builtin_predicate_max;s2ct=Symbol.RawMap.empty;c2s=Constants.Map.empty;locked=false;}let()=builtin_predicates|>List.iter(funp->letc=const_of_builtin_predicatepinlets=Symbol.make_builtin(func_of_builtin_predicate(fun_->assertfalse)p)inlett=Constcintable.c2s<-Constants.Map.addcstable.c2s;table.s2ct<-Symbol.RawMap.adds(c,t)table.s2ct)letdeclare_global_symbolsymb=tryfst@@Symbol.RawMap.findsymbtable.s2ctwithNot_found->iftable.lockedthenUtil.anomaly"declare_global_symbol called after initialization";table.last_global<-table.last_global-1;letn=table.last_globalinlett=Constnintable.s2ct<-Symbol.RawMap.addsymb(n,t)table.s2ct;table.c2s<-Constants.Map.addnsymbtable.c2s;nletdeclare_core_symbolx=letsymb=Symbol.(makeCore(func_of_core_symbolx))indeclare_global_symbolsymb,symbletuvarc,uvar=declare_core_symbolUvletasc,as_=declare_core_symbolAsletnilc,nil=declare_core_symbolENilletconsc,cons=declare_core_symbolEConsletdeclare_overloaded_global_symbolstr=letsymb,variant=Symbol.make_variant_builtin(Ast.Func.from_stringstr)indeclare_global_symbolsymb,variantletdeclare_global_symbol?variantstr=letsymb=Symbol.make_builtin?variant(Ast.Func.from_stringstr)indeclare_global_symbolsymbletlock()=table.locked<-trueletorc=declare_global_symbolF.(showorf)letpublish_builtinb=Constants.Map.find(const_of_builtin_predicateb)table.c2sletcut=publish_builtinCutletand_=publish_builtinAndletimpl=publish_builtinImplletrImpl=publish_builtinRImplletpi=publish_builtinPiletsigma=publish_builtinSigmaleteq=publish_builtinEqletmatch_=publish_builtinMatchletfindall=publish_builtinFindallletdelay=publish_builtinDelayend(* This term is hashconsed here *)letdummy=App(-1,Const(-1),[])(* This is the one uvar used for _ in CHR rules blockers *)letdummy_uvar_body={vardepth=0;contents=dummy;uid_private=0}moduleCHR:sig(* a set of rules *)typet(* a set of predicates contributing to represent a constraint *)typecliquetypesequent={eigen:term;context:term;conclusion:term}andrule={to_match:sequentlist;to_remove:sequentlist;patsno:int;guard:termoption;new_goal:sequentoption;nargs:int[@default0];pattern:constantlist;rule_name:string;rule_loc:Loc.t;}valpp_sequent:Fmt.formatter->sequent->unitvalshow_sequent:sequent->stringvalpp_rule:Fmt.formatter->rule->unitvalshow_rule:rule->stringvalempty:tvalnew_clique:(constant->Ast.Func.t)->constantlist->constantlist->t->t*cliquevalclique_of:constant->t->(Constants.Set.t*Constants.Set.t)optionvaladd_rule:clique->rule->t->tvalin_clique:clique->constant->boolvalrules_for:constant->t->rulelistvalpp:Fmt.formatter->t->unitvalpp_clique:Fmt.formatter->clique->unitvalshow:t->stringend=struct(* {{{ *)typeclique={ctx_filter:Constants.Set.t;clique:Constants.Set.t}[@@derivingshow]typesequent={eigen:term;context:term;conclusion:term}andrule={to_match:sequentlist;to_remove:sequentlist;patsno:int;guard:termoption;new_goal:sequentoption;nargs:int[@default0];pattern:constantlist;rule_name:string;rule_loc:Loc.t;}[@@derivingshow]typet={cliques:cliqueConstants.Map.t;rules:rulelistConstants.Map.t}[@@derivingshow]letempty={cliques=Constants.Map.empty;rules=Constants.Map.empty}letin_clique{clique;ctx_filter}c=Constants.Set.memccliqueletnew_cliqueshow_constanthypscl({cliques}aschr)=letopenConstantsinifcl=[]thenerror"empty clique";letc=Set.of_listclinletctx_filter=Set.of_listhypsin(* Check new inserted clique is valid *)letbuild_clique_strc=Printf.sprintf"{ %s }"@@String.concat","(List.map(funx->Ast.Func.show@@show_constantx)(Set.elementsc))inletold_ctx_filter=refNoneinletexceptionStopin(tryMap.iter(fun_({clique=c';ctx_filter=ctx_filter'})->ifSet.equalcc'then(old_ctx_filter:=Somectx_filter';raiseStop)elseifnot(Set.disjointcc')then(* different, not disjoint clique *)error("overlapping constraint cliques:"^build_clique_strc^"and"^build_clique_strc'))cliques;withStop->());letclique={ctx_filter=Set.unionctx_filter(Option.value~default:Set.empty!old_ctx_filter);clique=c}inlet(cliques:cliqueConstants.Map.t)=List.fold_left(funcliquesx->Constants.Map.addxcliquecliques)cliquesclin{chrwithcliques},cliqueletclique_ofc{cliques}=trySome(letres=Constants.Map.findccliquesinres.clique,res.ctx_filter)withNot_found->Noneletadd_rule({clique}:clique)r({rules}aschr)=letrules=Constants.Set.fold(funcrules->tryletrs=Constants.Map.findcrulesinConstants.Map.addc(rs@[r])ruleswithNot_found->Constants.Map.addc[r]rules)cliquerulesin{chrwithrules}letrules_forc{rules}=tryConstants.Map.findcruleswithNot_found->[]end(* }}} *)(* An elpi program, as parsed. But for idx and query_depth that are threaded
around in the main loop, chr and modes are globally stored in Constraints
and Clausify. *)typeclause_w_info={clloc:CData.t;clargsname:stringlist;clbody:clause;}[@@derivingshow]exceptionNo_clauseexceptionNo_more_stepsexceptionFlex_headmoduleConversion=structtypeextra_goal=..typeextra_goal+=|Unifyofterm*term|RawGoaloftermtypeextra_goals=extra_goallisttypeextra_goals_postprocessing=extra_goals->State.t->State.t*extra_goalsletextra_goals_postprocessing:extra_goals_postprocessingState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:extra_goals_postprocessing"~pp:(fun__->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(funx->Somex)~execution_is_over:(funx->Somex)~init:(fun()->();funxs->s,x)()typety_ast=TyNameofstring|TyAppofstring*ty_ast*ty_astlist[@@derivingshow]type'aembedding=depth:int->State.t->'a->State.t*term*extra_goalstype'areadback=depth:int->State.t->term->State.t*'a*extra_goalstype'at={ty:ty_ast;pp_doc:Format.formatter->unit->unit[@opaque];pp:Format.formatter->'a->unit[@opaque];embed:'aembedding[@opaque];(* 'a -> term *)readback:'areadback[@opaque];(* term -> 'a *)}[@@derivingshow]exceptionTypeErrofty_ast*int*term(* a type error at data conversion time *)typeprec_level=|Arrow|AppArgletneed_parxy=matchx,ywith|SomeAppArg,Arrow->true|SomeAppArg,AppArg->true|SomeArrow,Arrow->true|SomeArrow,AppArg->false|None,_->falseletwith_parp1p2s=ifneed_parp1p2then"("^s^")"elsesletrecshow_ty_ast?prec=function|TyNames->s|TyApp("->",src,[tgt])->letsrc=show_ty_ast~prec:Arrowsrcinlettgt=show_ty_asttgtinwith_parprecArrow(src^" -> "^tgt)|TyApp(s,x,xs)->lett=String.concat" "(s::List.map(show_ty_ast~prec:AppArg)(x::xs))inwith_parprecAppArgtletterm_of_extra_goal=function|Unify(a,b)->Builtin(Eq,[a;b])|RawGoalx->x|x->Util.anomaly(Printf.sprintf"Unprocessed extra_goal: %s.\nOnly %s and %s can be left unprocessed,\nplease call API.RawData.set_extra_goals_postprocessing.\n"(Obj.Extension_constructor.(name(of_valx)))(Obj.Extension_constructor.(name(of_val(Unify(dummy,dummy)))))(Obj.Extension_constructor.(name(of_val(RawGoaldummy)))))endmoduleContextualConversion=structtypety_ast=Conversion.ty_ast=TyNameofstring|TyAppofstring*ty_ast*ty_astlist[@@derivingshow]type('a,'hyps,'constraints)embedding=depth:int->'hyps->'constraints->State.t->'a->State.t*term*Conversion.extra_goalstype('a,'hyps,'constraints)readback=depth:int->'hyps->'constraints->State.t->term->State.t*'a*Conversion.extra_goalstype('a,'hyps,'constraints)t={ty:ty_ast;pp_doc:Format.formatter->unit->unit[@opaque];pp:Format.formatter->'a->unit[@opaque];embed:('a,'hyps,'constraints)embedding[@opaque];(* 'a -> term *)readback:('a,'hyps,'constraints)readback[@opaque];(* term -> 'a *)}[@@derivingshow]type('hyps,'constraints)ctx_readback=depth:int->hyps->constraints->State.t->State.t*'hyps*'constraints*Conversion.extra_goalsletunit_ctx:(unit,unit)ctx_readback=fun~depth:___s->s,(),(),[]letraw_ctx:(hyps,constraints)ctx_readback=fun~depth:_hcs->s,h,c,[]let(!<){ty;pp_doc;pp;embed;readback;}={Conversion.ty;pp;pp_doc;embed=(fun~depthst->embed~depth()()st);readback=(fun~depthst->readback~depth()()st);}let(!>){Conversion.ty;pp_doc;pp;embed;readback;}={ty;pp;pp_doc;embed=(fun~depth__st->embed~depthst);readback=(fun~depth__st->readback~depthst);}let(!<<)fx=(!<)(f((!>)x))let(!>>)(f:'aConversion.t->'bConversion.t)cc=letmkhc{ty;pp_doc;pp;embed;readback;}={Conversion.ty;pp;pp_doc;embed=(fun~depthst->embed~depthhcst);readback=(fun~depthst->readback~depthhcst);}inletmk_pp{ty;pp_doc;pp;}={Conversion.ty;pp;pp_doc;embed=(fun~depthst->assertfalse);readback=(fun~depthst->assertfalse);}inlet{Conversion.ty;pp;pp_doc}=f(mk_ppcc)in{ty;pp;pp_doc;embed=(fun~depthhcst->(f(mkhccc)).embed~depthst);readback=(fun~depthhcst->(f(mkhccc)).readback~depthst);}let(!>>>)(f:'aConversion.t->'bConversion.t->'cConversion.t)ccdd=letmkhc{ty;pp_doc;pp;embed;readback;}={Conversion.ty;pp;pp_doc;embed=(fun~depthst->embed~depthhcst);readback=(fun~depthst->readback~depthhcst);}inletmk_pp{ty;pp_doc;pp;}={Conversion.ty;pp;pp_doc;embed=(fun~depthst->assertfalse);readback=(fun~depthst->assertfalse);}inlet{Conversion.ty;pp;pp_doc}=f(mk_ppcc)(mk_ppdd)in{ty;pp;pp_doc;embed=(fun~depthhcst->(f(mkhccc)(mkhcdd)).embed~depthst);readback=(fun~depthhcst->(f(mkhccc)(mkhcdd)).readback~depthst);}endletwhile_compiling:boolState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:compiling"~pp:(funfmt_->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(fun_->Somefalse)~execution_is_over:(fun_->Somefalse)(* we keep it, since API.FlexibleData.Elpi.make needs it *)~init:(fun()->false)()moduleHoasHooks=structtypedescriptor={extra_goals_postprocessing:Conversion.extra_goals_postprocessingoption;}letnew_descriptor()=ref{extra_goals_postprocessing=None;}letset_extra_goals_postprocessing~descriptorf=match!descriptorwith|{extra_goals_postprocessing=None}->descriptor:={extra_goals_postprocessing=Somef}|{extra_goals_postprocessing=Some_}->error"set_extra_goals_postprocessing called twice"endmoduleCalcHooks=structtyperun=termlist->termtypeeval={code:run;ty_decl:string;}typedescriptor=(constant*eval)listletnew_descriptor():descriptorref=ref[]leteval:runConstants.Map.tState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:eval"~clause_compilation_is_over:(funx->x)~compilation_is_over:(funx->Somex)~execution_is_over:(fun_->None)~init:(fun()->Constants.Map.empty)~pp:(funfmtt->Constants.Map.pp(fun__->())fmtt)()endmoduleBuiltInPredicate=structtypename=stringtypedoc=stringtype'aoarg=Keep|Discardtype'aioarg=Dataof'a|NoDatatype('function_type,'inernal_outtype_in,'internal_hyps,'internal_constraints)ffi=|In:'tConversion.t*doc*('i,'o,'h,'c)ffi->('t->'i,'o,'h,'c)ffi|Out:'tConversion.t*doc*('i,'o*'toption,'h,'c)ffi->('toarg->'i,'o,'h,'c)ffi|InOut:'tioargConversion.t*doc*('i,'o*'toption,'h,'c)ffi->('tioarg->'i,'o,'h,'c)ffi|CIn:('t,'h,'c)ContextualConversion.t*doc*('i,'o,'h,'c)ffi->('t->'i,'o,'h,'c)ffi|COut:('t,'h,'c)ContextualConversion.t*doc*('i,'o*'toption,'h,'c)ffi->('toarg->'i,'o,'h,'c)ffi|CInOut:('tioarg,'h,'c)ContextualConversion.t*doc*('i,'o*'toption,'h,'c)ffi->('tioarg->'i,'o,'h,'c)ffi|Easy:doc->(depth:int->'o,'o,unit,unit)ffi|Read:('h,'c)ContextualConversion.ctx_readback*doc->(depth:int->'h->'c->State.t->'o,'o,'h,'c)ffi|Full:('h,'c)ContextualConversion.ctx_readback*doc->(depth:int->'h->'c->State.t->State.t*'o*Conversion.extra_goals,'o,'h,'c)ffi|FullHO:('h,'c)ContextualConversion.ctx_readback*doc->(once:(depth:int->term->State.t->State.t)->depth:int->'h->'c->State.t->State.t*'o*Conversion.extra_goals,'o,'h,'c)ffi|VariadicIn:('h,'c)ContextualConversion.ctx_readback*('t,'h,'c)ContextualConversion.t*doc->('tlist->depth:int->'h->'c->State.t->State.t*'o,'o,'h,'c)ffi|VariadicOut:('h,'c)ContextualConversion.ctx_readback*('t,'h,'c)ContextualConversion.t*doc->('toarglist->depth:int->'h->'c->State.t->State.t*('o*'toptionlistoption),'o,'h,'c)ffi|VariadicInOut:('h,'c)ContextualConversion.ctx_readback*('tioarg,'h,'c)ContextualConversion.t*doc->('tioarglist->depth:int->'h->'c->State.t->State.t*('o*'toptionlistoption),'o,'h,'c)ffitypet=Pred:name*('a,unit,'h,'c)ffi*'a->tletppfmt(Pred(name,_,_))=Format.fprintffmt"%s"nameletcompare(Pred(name1,_,_))(Pred(name2,_,_))=String.comparename1name2typedoc_spec=DocAbove|DocNextletpp_commentfmtdoc=Fmt.fprintffmt"@?";letorig_out=Fmt.pp_get_formatter_out_functionsfmt()inFmt.pp_set_formatter_out_functionsfmt{orig_outwithFmt.out_newline=fun()->orig_out.Fmt.out_string"\n% "03};Fmt.fprintffmt"@[<hov>";Fmt.pp_print_textfmtdoc;Fmt.fprintffmt"@]@?";Fmt.pp_set_formatter_out_functionsfmtorig_out;;letpp_tysepfmt(_,s,_)=Fmt.fprintffmt" %s%s"ssepletpp_ty_args=pplist(pp_ty"")" ->"~pplastelem:(pp_ty"")moduleADT=structtype('match_stateful_t,'match_t,'t)match_t=|Mof((* continuation to call passing subterms *)ok:'match_t->(* continuation to call to signal pattern matching failure *)ko:(unit->term)->(* match 't and pass its subterms to ~ok or just call ~ko *)'t->term)|MSof((* continuation to call passing subterms *)ok:'match_stateful_t->(* continuation to call to signal pattern matching failure *)ko:(State.t->State.t*term*Conversion.extra_goals)->(* match 't and pass its subterms to ~ok or just call ~ko *)'t->State.t->State.t*term*Conversion.extra_goals)type('build_stateful_t,'build_t)build_t=|Bof'build_t|BSof'build_stateful_ttype('stateful_builder,'builder,'stateful_matcher,'matcher,'self,'hyps,'constraints)constructor_arguments=(* No arguments *)|N:(State.t->State.t*'self,'self,State.t->State.t*term*Conversion.extra_goals,term,'self,'hyps,'constraints)constructor_arguments(* An argument of type 'a *)|A:'aConversion.t*('bs,'b,'ms,'m,'self,'hyps,'constraints)constructor_arguments->('a->'bs,'a->'b,'a->'ms,'a->'m,'self,'hyps,'constraints)constructor_arguments(* An argument of type 'a in context 'hyps,'constraints *)|CA:('a,'hyps,'constraints)ContextualConversion.t*('bs,'b,'ms,'m,'self,'hyps,'constraints)constructor_arguments->('a->'bs,'a->'b,'a->'ms,'a->'m,'self,'hyps,'constraints)constructor_arguments(* An argument of type 'self *)|S:('bs,'b,'ms,'m,'self,'hyps,'constraints)constructor_arguments->('self->'bs,'self->'b,'self->'ms,'self->'m,'self,'hyps,'constraints)constructor_arguments(* An argument of type `T 'self` for a constainer `T`, like a `list 'self`.
`S args` above is a shortcut for `C(fun x -> x, args)` *)|C:(('self,'hyps,'constraints)ContextualConversion.t->('a,'hyps,'constraints)ContextualConversion.t)*('bs,'b,'ms,'m,'self,'hyps,'constraints)constructor_arguments->('a->'bs,'a->'b,'a->'ms,'a->'m,'self,'hyps,'constraints)constructor_argumentstype('t,'h,'c)constructor=K:name*doc*('build_stateful_t,'build_t,'match_stateful_t,'match_t,'t,'h,'c)constructor_arguments*(* args ty *)('build_stateful_t,'build_t)build_t*('match_stateful_t,'match_t,'t)match_t->('t,'h,'c)constructortype('t,'h,'c)base_declaration={ty:Conversion.ty_ast;doc:doc;pp:Format.formatter->'t->unit;constructors:('t,'h,'c)constructorlist;}type('t,'h,'c)declaration=|Decl:('t,'h,'c)base_declaration->('t,'h,'c)declaration|Param:('tConversion.t->('t1,'h,'c)declaration)->('t1,'h,'c)declaration|ParamC:(('t,'h,'c)ContextualConversion.t->('t1,'h,'c)declaration)->('t1,'h,'c)declarationtypeallocation=(constant*int)StrMap.ttype('b,'m,'t,'h,'c)compiled_constructor_arguments=|XN:(State.t->State.t*'t,State.t->State.t*term*Conversion.extra_goals,'t,'h,'c)compiled_constructor_arguments|XA:('a,'h,'c)ContextualConversion.t*('b,'m,'t,'h,'c)compiled_constructor_arguments->('a->'b,'a->'m,'t,'h,'c)compiled_constructor_argumentstype('match_t,'t)compiled_match_t=(* continuation to call passing subterms *)ok:'match_t->(* continuation to call to signal pattern matching failure *)ko:(State.t->State.t*term*Conversion.extra_goals)->(* match 't and pass its subterms to ~ok or just call ~ko *)'t->State.t->State.t*term*Conversion.extra_goalstype('t,'h,'c)compiled_constructor=XK:('build_t,'matched_t,'t,'h,'c)compiled_constructor_arguments*'build_t*('matched_t,'t)compiled_match_t->('t,'h,'c)compiled_constructortype('t,'h,'c)compiled_adt=(('t,'h,'c)compiled_constructor)Constants.Map.tletbuildk~mkConstkname=function|[]->mkConstkname|x::xs->mkAppknamexxsletrecreadback_args:typeamthc.look:(depth:int->term->term)->Conversion.ty_ast->depth:int->h->c->State.t->Conversion.extra_goalslist->term->(a,m,t,h,c)compiled_constructor_arguments->a->termlist->State.t*t*Conversion.extra_goals=fun~lookty~depthhypsconstraintsstateextraoriginargsconvertl->matchargs,lwith|XN,[]->letstate,x=convertstateinstate,x,List.(concat(revextra))|XN,_->raise(Conversion.TypeErr(ty,depth,origin))|XA_,[]->assertfalse|XA(d,rest),x::xs->letstate,x,gls=d.readback~depthhypsconstraintsstatexinreadback_args~lookty~depthhypsconstraintsstate(gls::extra)originrest(convertx)xsandreadback:typethc.mkinterval:(int->int->int->termlist)->look:(depth:int->term->term)->alloc:(?name:string->State.t->State.t*'uk)->mkUnifVar:('uk->args:termlist->State.t->term)->Conversion.ty_ast->(t,h,c)compiled_adt->depth:int->h->c->State.t->term->State.t*t*Conversion.extra_goals=fun~mkinterval~look~alloc~mkUnifVartyadt~depthhypsconstraintsstatet->trymatchlook~depthtwith|Constc->letXK(args,read,_)=Constants.Map.findcadtinreadback_args~lookty~depthhypsconstraintsstate[]targsread[]|App(c,x,xs)->letXK(args,read,_)=Constants.Map.findcadtinreadback_args~lookty~depthhypsconstraintsstate[]targsread(x::xs)|(UVar_|AppUVar_)->letXK(args,read,_)=Constants.Map.findGlobal_symbols.uvarcadtinreadback_args~lookty~depthhypsconstraintsstate[]targsread[t]|Discard->letXK(args,read,_)=Constants.Map.findGlobal_symbols.uvarcadtinletstate,k=allocstateinreadback_args~lookty~depthhypsconstraintsstate[]targsread[mkUnifVark~args:(mkinterval0depth0)state]|_->raise(Conversion.TypeErr(ty,depth,t))withNot_found->raise(Conversion.TypeErr(ty,depth,t))andadt_embed_args:typemathc.mkConst:(int->term)->Conversion.ty_ast->(t,h,c)compiled_adt->constant->depth:int->h->c->(a,m,t,h,c)compiled_constructor_arguments->(State.t->State.t*term*Conversion.extra_goals)list->m=fun~mkConsttyadtkname~depthhypsconstraintsargsacc->matchargswith|XN->funstate->letstate,ts,gls=List.fold_left(fun(state,acc,gls)f->letstate,t,goals=fstateinstate,t::acc,goals::gls)(state,[],[])accinstate,buildk~mkConstknamets,List.(flattengls)|XA(d,args)->funx->adt_embed_args~mkConsttyadtkname~depthhypsconstraintsargs((funstate->d.embed~depthhypsconstraintsstatex)::acc)andembed:typeahc.mkConst:(int->term)->Conversion.ty_ast->(Format.formatter->a->unit)->(a,h,c)compiled_adt->depth:int->h->c->State.t->a->State.t*term*Conversion.extra_goals=fun~mkConsttyppadt->letbindings=Constants.Map.bindingsadtinfun~depthhypsconstraintsstatet->letrecauxlstate=matchlwith|[]->type_error("Pattern matching failure embedding: "^Conversion.show_ty_astty^Format.asprintf": %a"ppt)|(kname,XK(args,_,matcher))::rest->letok=adt_embed_args~mkConsttyadtkname~depthhypsconstraintsargs[]inmatcher~ok~ko:(auxrest)tstateinauxbindingsstateletreccompile_arguments:typebbsmmsthc.(bs,b,ms,m,t,h,c)constructor_arguments->(t,h,c)ContextualConversion.t->(bs,ms,t,h,c)compiled_constructor_arguments=funargself->matchargwith|N->XN|A(d,rest)->XA(ContextualConversion.(!>)d,compile_argumentsrestself)|CA(d,rest)->XA(d,compile_argumentsrestself)|Srest->XA(self,compile_argumentsrestself)|C(fs,rest)->XA(fsself,compile_argumentsrestself)letreccompile_builder_aux:typebsbmmsthc.(bs,b,ms,m,t,h,c)constructor_arguments->b->bs=funargsf->matchargswith|N->funstate->state,f|A(_,rest)->funa->compile_builder_auxrest(fa)|CA(_,rest)->funa->compile_builder_auxrest(fa)|Srest->funa->compile_builder_auxrest(fa)|C(_,rest)->funa->compile_builder_auxrest(fa)letcompile_builder:typebsbmmsthc.(bs,b,ms,m,t,h,c)constructor_arguments->(bs,b)build_t->bs=funa->function|Bf->compile_builder_auxaf|BSf->fletreccompile_matcher_ok:typebsbmmsthc.(bs,b,ms,m,t,h,c)constructor_arguments->ms->Conversion.extra_goalsref->State.tref->m=funargsfglsstate->matchargswith|N->letstate',t,gls'=f!stateinstate:=state';gls:=gls';t|A(_,rest)->funa->compile_matcher_okrest(fa)glsstate|CA(_,rest)->funa->compile_matcher_okrest(fa)glsstate|Srest->funa->compile_matcher_okrest(fa)glsstate|C(_,rest)->funa->compile_matcher_okrest(fa)glsstateletcompile_matcher_kofglsstate()=letstate',t,gls'=f!stateinstate:=state';gls:=gls';tletcompile_matcher:typebsbmmsthc.(bs,b,ms,m,t,h,c)constructor_arguments->(ms,m,t)match_t->(ms,t)compiled_match_t=funa->function|Mf->fun~ok~kotstate->letstate=refstateinletgls=ref[]in!state,f~ok:(compile_matcher_okaokglsstate)~ko:(compile_matcher_kokoglsstate)t,!gls|MSf->fletrectyargs_of_args:typeabcde.string->(a,b,c,d,e)compiled_constructor_arguments->(bool*string*string)list=funself->function|XN->[false,self,""]|XA({ty},rest)->(false,Conversion.show_ty_astty,"")::tyargs_of_argsselfrestletdo_allocate_constructorstyl=letnames=List.fold_right(fun(K(name,_,_,_,_))->StrSet.addname)lStrSet.emptyinifStrSet.cardinalnames<>List.lengthlthenanomaly("Duplicate constructors name in ADT: "^Conversion.show_ty_astty);List.fold_left(funvacc(K(name,_,a,b,m))->ifname="uvar"thenvaccelseletc_variant=Global_symbols.declare_overloaded_global_symbolnameinStrMap.addnamec_variantvacc)StrMap.emptylletcompile_constructorsallocatedtyselfself_namel=List.fold_left(fun(acc,sacc)(K(name,_,a,b,m))->ifname="uvar"thenletargs=compile_argumentsaselfinletacc=Constants.Map.addGlobal_symbols.uvarc(XK(args,compile_builderab,compile_matcheram))accin(acc,sacc)elseletc=tryStrMap.findnameallocated|>fstwithNot_found->anomaly"constructor arguments should be preallocated"inletargs=compile_argumentsaselfinConstants.Map.addc(XK(args,compile_builderab,compile_matcheram))acc,StrMap.addname(tyargs_of_argsself_nameargs)sacc)(Constants.Map.empty,StrMap.empty)lletdocument_constructorfmtnamevariantdocargsdoc=Fmt.fprintffmt"@[<hov2>external symbol %s :@[<hov>%a@] = \"%d\". %s@]@\n"namepp_ty_argsargsdocvariant(ifdoc=""then""else" % "^doc)letdocument_kindfmt=function|Conversion.TyApp(s,_,l)->letn=List.lengthl+2inletl=Array.initn(fun_->"type")inFmt.fprintffmt"@[<hov 2>kind %s %s.@]@\n"s(String.concat" -> "(Array.to_listl))|Conversion.TyNames->Fmt.fprintffmt"@[<hov 2>kind %s type.@]@\n"sletdocument_adtdoctykscksvksfmt()=ifdoc<>""thenbeginpp_commentfmt("% "^doc);Fmt.fprintffmt"@\n"end;document_kindfmtty;List.iter(fun(K(name,doc,_,_,_))->ifname<>"uvar"thenletargsdoc=StrMap.findnamecksindocument_constructorfmtname(StrMap.findnamevks|>snd)docargsdoc)ksletrecallocate_constructors:typethc.mkinterval:(int->int->int->termlist)->look:(depth:int->term->term)->mkConst:(int->term)->alloc:(?name:doc->State.t->State.t*'a)->mkUnifVar:('a->args:termlist->State.t->term)->(t,h,c)declaration->allocation=fun~mkinterval~look~mkConst~alloc~mkUnifVar->function|Decl{ty;constructors;doc;pp}->do_allocate_constructorstyconstructors|Paramf->leta={ContextualConversion.ty=Conversion.TyName"A";pp=(funfmt_->());pp_doc=(funfmt()->());readback=(fun~depthhypsconstraintsstateterm->assertfalse);embed=(fun~depthhypsconstraintsstateterm->assertfalse);}|>ContextualConversion.(!<)inallocate_constructors~mkinterval~look~mkConst~alloc~mkUnifVar(fa)|ParamCf->leta={ContextualConversion.ty=Conversion.TyName"A";pp=(funfmt_->());pp_doc=(funfmt()->());readback=(fun~depthhypsconstraintsstateterm->assertfalse);embed=(fun~depthhypsconstraintsstateterm->assertfalse);}inallocate_constructors~mkinterval~look~mkConst~alloc~mkUnifVar(fa)letdeclare_allocated:typethc.mkinterval:(int->int->int->termlist)->look:(depth:int->term->term)->mkConst:(int->term)->alloc:(?name:doc->State.t->State.t*'a)->mkUnifVar:('a->args:termlist->State.t->term)->allocation->(t,h,c)declaration->(t,h,c)ContextualConversion.t=fun~mkinterval~look~mkConst~alloc~mkUnifVarallocated->functionDecl{ty;constructors;doc;pp}->letreadback_ref=ref(fun~depth____->assertfalse)inletembed_ref=ref(fun~depth____->assertfalse)inletsconstructors_ref=refStrMap.emptyinletself={ContextualConversion.ty;pp;pp_doc=(funfmt()->document_adtdoctyconstructors!sconstructors_refallocatedfmt());readback=(fun~depthhypsconstraintsstateterm->!readback_ref~depthhypsconstraintsstateterm);embed=(fun~depthhypsconstraintsstateterm->!embed_ref~depthhypsconstraintsstateterm);}inletcconstructors,sconstructors=compile_constructorsallocatedtyself(Conversion.show_ty_astty)constructorsinsconstructors_ref:=sconstructors;readback_ref:=readback~mkinterval~look~alloc~mkUnifVartycconstructors;embed_ref:=embed~mkConsttyppcconstructors;self|_->anomaly"declare_allocated can only be called on Decl"endtypedeclaration=|MLCodeoft*doc_spec|MLData:'aConversion.t->declaration|MLDataC:('a,'h,'c)ContextualConversion.t->declaration|LPDocofstring|LPCodeofstring(* doc *)letparens?(sep=" ")str=ifRe.Str.(string_match(regexp(".*"^sep^".*"))str0)then"("^str^")"elsestrletparens_arr=parens~sep:("->")letws_to_maxfmtmaxn=ifn<maxthenFormat.fprintffmt"%s"(String.make(max-n)' ')else()letpp_tab_argimaxpresepfmt(_,ty,doc)=ifi=0thenFmt.pp_set_tabfmt()else();Fmt.fprintffmt"%s%s%s"pre(parens_arrty)sep;ifi=0then(ws_to_maxfmtmax(String.lengthty);Fmt.pp_set_tabfmt())elseFmt.pp_print_tabfmt();ifdoc<>""thenbeginFmt.fprintffmt" %% %s"docend;Fmt.pp_print_tabfmt();;letpp_tab_argsfmtl=letmax=List.fold_left(funm(_,s,_)->max(String.lengths)m)0linFmt.pp_open_tboxfmt();letrecauxm_of_lasti=function|[]->()|x::xs->let(m_of_x,_,_)=xinletpre=ifm_of_last<>m_of_xthen"-> "else""inletsep=ifxs=[]then"."elsematchxswith|(b,_,_)::_whenb=m_of_x->", "|_->""inpp_tab_argimaxpresepfmtx;auxm_of_x(i+1)xsinifl=[]thenFormat.fprintffmt"."elseauxtrue0l;Fmt.pp_close_tboxfmt();;letpp_argsfmtl=letl1,l2=List.partition(fun(x,_,_)->x)linletpp_argfmt(_,ty,_)=Format.fprintffmt"%s"(parens_arrty)inletpp_args=pplistpp_arg", "~pplastelem:pp_arginifl1<>[]thenFormat.fprintffmt" ";Format.fprintffmt"%a"pp_argsl1;ifl2=[]then()elseifl1=[]thenFormat.fprintffmt" -> %a"pp_argsl2elseFormat.fprintffmt" -> %a"pp_argsl2letrecis_std_moded=function|[]->true|(true,_,_)::rest->is_std_modedrest|(false,_,_)::[]->true|(false,_,_)::((false,_,_)::_asrest)->is_std_modedrest|_->false(* External predicate are functional *)letpp_predfmtdocspecnamedoc_predargs=letargs=List.revargsinifis_std_modedargsthenmatchdocspecwith|DocNext->Fmt.fprintffmt"@[<v 2>external func %s %% %s@;%a@]@."namedoc_predpp_tab_argsargs|DocAbove->letdoc="["^String.concat" "(name::List.map(fun(_,_,x)->x)args)^"] "^doc_predinFmt.fprintffmt"@[<v>%% %a@.external func %s@[<hov>%a.@]@]@.@."pp_commentdocnamepp_argsargselseletpp_tab_argimaxsepfmt(dir,ty,doc)=letdir=ifdirthen"i"else"o"inifi=0thenFmt.pp_set_tabfmt()else();Fmt.fprintffmt"%s:%s%s"dirtysep;ifi=0then(ws_to_maxfmtmax(String.lengthty);Fmt.pp_set_tabfmt())elseFmt.pp_print_tabfmt();ifdoc<>""thenbeginFmt.fprintffmt" %% %s"docend;Fmt.pp_print_tabfmt()inletpp_tab_argsfmtl=letn=List.lengthl-1inletmax=List.fold_left(funm(_,s,_)->max(String.lengths)m)0linFmt.pp_open_tboxfmt();ifl=[]thenFmt.fprintffmt".";List.iteri(funix->letsep=ifi=nthen"."else","inpp_tab_argimaxsepfmtx)l;Fmt.pp_close_tboxfmt()inletpp_argsepfmt(dir,ty,doc)=letdir=ifdirthen"i"else"o"inFmt.fprintffmt"%s:%s%s"dirtysepinletpp_args=pplist(pp_arg"")", "~pplastelem:(pp_arg"")inmatchdocspecwith|DocNext->Fmt.fprintffmt"@\n@[<v 2>:functional :external pred %s %% %s@;%a@]@."namedoc_predpp_tab_argsargs|DocAbove->letdoc="["^String.concat" "(name::List.map(fun(_,_,x)->x)args)^"] "^doc_predinFmt.fprintffmt"@\n@[<v>%% %a@.:functional :external pred %s @[<hov>%a.@]@]@.@."pp_commentdocnamepp_argsargs;;letpp_variadictypefmtnamedoc_predtyargs=letargs=List.rev((false,"variadic "^parensty^" (func)","")::args)inletdoc="["^String.concat" "(name::List.map(fun(_,_,x)->x)args)^"...] "^doc_predinFmt.fprintffmt"@[<v>%% %a@.external type %s@[<hov>%a.@]@]@.@."pp_commentdocnamepp_ty_argsargs;;letpp_variadicpredfmtdocspecnamedoc_predtyargs=letrargs=List.rev((false,ty^".. ","...")::args)inifis_std_modedrargsthenmatchdocspecwith|DocNext->Fmt.fprintffmt"@[<v 2>external func %s %% %s@;%a@]@."namedoc_predpp_tab_argsrargs|DocAbove->letdoc="["^String.concat" "(name::List.map(fun(_,_,x)->x)rargs)^"] "^doc_predinFmt.fprintffmt"@[<v>%% %a@.external func %s@[<hov>%a.@]@]@.@."pp_commentdocnamepp_argsrargselsepp_variadictypefmtnamedoc_predtyargs;;letdocument_predfmtdocspecnameffi=letrecdoc:typeiohc.(bool*string*string)list->(i,o,h,c)ffi->unit=funargs->function|In({Conversion.ty},s,ffi)->doc((true,Conversion.show_ty_astty,s)::args)ffi|Out({Conversion.ty},s,ffi)->doc((false,Conversion.show_ty_astty,s)::args)ffi|InOut({Conversion.ty},s,ffi)->doc((false,Conversion.show_ty_astty,s)::args)ffi|CIn({ContextualConversion.ty},s,ffi)->doc((true,Conversion.show_ty_astty,s)::args)ffi|COut({ContextualConversion.ty},s,ffi)->doc((false,Conversion.show_ty_astty,s)::args)ffi|CInOut({ContextualConversion.ty},s,ffi)->doc((false,Conversion.show_ty_astty,s)::args)ffi|Read(_,s)->pp_predfmtdocspecnamesargs|Easys->pp_predfmtdocspecnamesargs|Full(_,s)->pp_predfmtdocspecnamesargs|FullHO(_,s)->pp_predfmtdocspecnamesargs|VariadicIn(_,{ContextualConversion.ty},s)->pp_variadictypefmtnames(Conversion.show_ty_astty)args|VariadicOut(_,{ContextualConversion.ty},s)->pp_variadicpredfmtdocspecnames(Conversion.show_ty_astty)args|VariadicInOut(_,{ContextualConversion.ty},s)->pp_variadicpredfmtdocspecnames(Conversion.show_ty_astty)argsindoc[]ffi;;letdocumentfmtlcalc_list=letomargin=Fmt.pp_get_marginfmt()inFmt.pp_set_marginfmt75;Fmt.fprintffmt"@[<v>";Fmt.fprintffmt"@\n@\n";List.iter(function|MLCode(Pred(name,ffi,_),docspec)->document_predfmtdocspecnameffi;ifname="calc"thenbeginFormat.fprintffmt"%s@\n@\n""% --- Operators ---";List.iter(fun(_,x)->Format.fprintffmt"%s@\n@\n"x.CalcHooks.ty_decl)calc_listend;|MLData{pp_doc}->Fmt.fprintffmt"%a@\n"pp_doc()|MLDataC{pp_doc}->Fmt.fprintffmt"%a@\n"pp_doc()|LPCodes->Fmt.fprintffmt"%s"s;Fmt.fprintffmt"@\n@\n"|LPDocs->pp_commentfmt("% "^s);Fmt.fprintffmt"@\n@\n")l;Fmt.fprintffmt"@\n@\n";Fmt.fprintffmt"@]@.";Fmt.pp_set_marginfmtomargin;;typebuiltin_table=(int,t)Hashtbl.t[@@derivingshow]endtypesymbol_table={mutablec2s:Symbol.tConstants.Map.t;c2t:(constant,term)Hashtbl.t;mutablefrozen_constants:int;}[@@derivingshow]typeexecutable={(* the lambda-Prolog program: an indexed list of clauses *)compiled_program:prolog_prog;(* chr rules *)chr:CHR.t;(* query *)initial_depth:int;(* used by findall and CHR *)initial_goal:term;(* constraints coming from compilation *)initial_runtime_state:State.t;(* Hashconsed symbols + their string equivalent *)symbol_table:symbol_table;(* Indexed FFI entry points *)builtins:BuiltInPredicate.builtin_table;(* solution *)assignments:termUtil.StrMap.t;}typepp_ctx={uv_names:(stringUtil.IntMap.t*int)ref;table:symbol_table;}typesolution={assignments:termStrMap.t;constraints:constraints;state:State.t;pp_ctx:pp_ctx;state_for_relocation:int*symbol_table;}type'aoutcome=Successofsolution|Failure|NoMoreStepsexceptionCannotDeclareClauseForBuiltinofLoc.toption*builtin_predicate