123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625(* elpi: embedded lambda prolog interpreter *)(* license: GNU Lesser General Public License Version 2.1 or later *)(* ------------------------------------------------------------------------- *)openElpi_utilopenElpi_parseropenElpi_runtimeopenUtilmoduleF=Ast.FuncmoduleR=Runtime_trace_offmoduleD=Dataletelpi_language=Compiler_data.elpi_languagetypeflags={defined_variables:StrSet.t;print_units:bool;time_typechecking:bool;skip_det_checking:bool;}[@@derivingshow]letdefault_flags={defined_variables=StrSet.empty;print_units=false;time_typechecking=false;skip_det_checking=false;}lettime_thisrf=lett0=Unix.gettimeofday()intryletrc=f()inlett1=Unix.gettimeofday()inr:=!r+.(t1-.t0);rcwithe->lett1=Unix.gettimeofday()inr:=!r+.(t1-.t0);raiseeletparser:(moduleParse.Parser)optionD.State.component=D.State.declare~descriptor:D.elpi_state_descriptor~name:"elpi:parser"~pp:(funfmt_->Format.fprintffmt"<parser>")~clause_compilation_is_over:(funx->x)~compilation_is_over:(funx->Somex)~execution_is_over:(fun_->None)~init:(fun()->None)()letfilter1_if{defined_variables}projc=matchprojcwith|None->true|SomeewhenStrSet.memedefined_variables->true|Some_->false(* Symbol table of a compilation unit (part of the compiler state).
The initial value is taken from Data.Global_symbols, then both global
names and local ones are allocated (hashconsed) in this table.
Given a two symbols table (base and second) we can obtain a new one
(updated base) via [build_shift] that contains the union of the symbols
and a relocation to be applied to a program that lives in the second table.
The code applying the shift is also supposed to re-hashcons and recognize
builtins.
*)moduleSymbolMap:sigtypetable[@@derivingshow]valpp_table:Format.formatter->table->unitvalequal_globals:table->table->bool(* val diff : table -> table -> table *)valempty:unit->tablevalallocate_global_symbol:D.State.t->table->D.Symbol.t->table*(constant*D.term)valallocate_bound_symbol:D.State.t->table->constant->table*D.termvalget_global_symbol:table->D.Symbol.t->constantoptionvalget_canonical:D.State.t->table->constant->D.termvalglobal_name:D.State.t->table->constant->F.tvalcompile:table->D.symbol_tablevalcompile_s2c:table->(constant*D.term)D.Symbol.RawMap.tend=structopenCompiler_datatypetable={ast2ct:(constant*D.term)D.Symbol.RawMap.t;c2t:D.termConstants.Map.t;c2s:Symbol.tConstants.Map.t;last_global:int;}[@@derivingshow]letequal_globalsm1m2=m1.last_global=m2.last_global(* let diff big small =
Util.Constants.Map.fold (fun c s m ->
{ m with c2s = Util.Constants.Map.remove c m.c2s; c2t = Util.Constants.Map.remove c m.c2t; ast2ct = .Map.remove (F.from_string s) m.ast2ct}
) small.c2s big *)letcompile{last_global;c2t;c2s;ast2ct}=lett={D.c2s;c2t=Hashtbl.create(Util.Constants.Map.cardinalc2t);frozen_constants=last_global;}in(* We could compile the Map c2t to a Hash table upfront, but there is no need
since it is extended at run time anyway *)(* Symbol.RawMap.iter (fun k (c,v) -> lrt c = c Hashtbl.add t.c2t c v; Hashtbl.add t.c2s c (F.show k)) ast2ct; *)tletcompile_s2c{ast2ct}=ast2ctletallocate_global_symbol_aux(x:D.Symbol.t)({c2t;c2s;ast2ct;last_global}astable)=trytable,D.Symbol.RawMap.findxast2ctwithNot_found->(* Format.eprintf "NEW %a -> %d\n" Symbol.pp x last_global; *)letlast_global=last_global-1inletn=last_globalinletxx=D.Term.Constninletp=n,xxinletc2t=Util.Constants.Map.addnxxc2tinletast2ct=D.Symbol.RawMap.addxpast2ctinletc2s=Util.Constants.Map.addnxc2sin{c2t;c2s;ast2ct;last_global},pletget_global_symbol{ast2ct}s=trySome(fst@@D.Symbol.RawMap.findsast2ct)withNot_found->Noneletempty()=ifnot@@D.Global_symbols.table.lockedthenanomaly"SymbolMap created before Global_symbols.table is locked";lettable={ast2ct=D.Global_symbols.(table.s2ct);last_global=D.Global_symbols.table.last_global;c2s=D.Global_symbols.table.c2s;c2t=Util.Constants.Map.map(funs->let_,t=D.Symbol.RawMap.findsD.Global_symbols.(table.s2ct)int)D.Global_symbols.(table.c2s);}in(*T2.go allocate_global_symbol_aux*)tableletallocate_global_symbolstatetable(x:D.Symbol.t)=ifnot(D.State.getD.while_compilingstate)thenanomaly(Format.asprintf"Cannot allocate a symbol for %a. Global symbols can only be allocated during compilation"D.Symbol.ppx);allocate_global_symbol_auxxtableletallocate_bound_symbol_auxn({c2t;ast2ct}astable)=trytable,Util.Constants.Map.findnc2twithNot_found->letxx=D.Term.Constninletc2t=Util.Constants.Map.addnxxc2tin{tablewithc2t;ast2ct},xxletallocate_bound_symbolstatetablen=ifn<0thenanomaly"bound variables are positive";allocate_bound_symbol_auxntable;;letget_canonicalstatetablec=ifnot(D.State.getD.while_compilingstate)thenD.ConstcelsetryUtil.Constants.Map.findctable.c2twithNot_found->anomaly("unknown symbol "^string_of_intc)letglobal_namestatetablec=ifnot(D.State.getD.while_compilingstate)thenanomaly"get_canonical can only be used during compilation";trySymbol.get_func@@Util.Constants.Map.findctable.c2swithNot_found->anomaly("unknown symbol "^string_of_intc)endmoduleBuiltins:sigtypetvalpp:Format.formatter->t->unitvalregister:t->D.BuiltInPredicate.t->constant->tvalis_declared:t->constant->boolvalfold:(constant->Data.BuiltInPredicate.t->'a->'a)->t->'a->'avalempty:tend=structtypet=Data.BuiltInPredicate.tConstants.Map.t[@@derivingshow]letempty=Constants.Map.emptyletfold=Constants.Map.foldletregistert(D.BuiltInPredicate.Pred(s,_,_)asb)idx=ifs=""thenanomaly"Built-in predicate name must be non empty";ifConstants.Map.memidxtthenanomaly("Duplicate built-in predicate "^s);Constants.Map.addidxbt;;letis_declaredtx=Constants.Map.memxtend(****************************************************************************
Intermediate program representation
****************************************************************************)openDatamoduleC=ConstantsopenCompiler_datamoduleUF=Symbol.UFtypemacro_declaration=(ScopedTerm.t*Loc.t)F.Map.t[@@derivingshow,ord]moduleScoped=structtypeprogram={pbody:pbody;toplevel_macros:macro_declaration;}andpbody={kinds:Arity.tF.Map.t;types:ScopeTypeExpressionUniqueList.tF.Map.t;type_abbrevs:(F.t*ScopedTypeExpression.t)list;body:blocklist;pred_symbols:F.Set.t;ty_symbols:F.Set.t;}andblock=|Clausesof(ScopedTerm.t,Ast.Structured.attribute,bool,bool)Ast.Clause.tlist(* TODO: use a map : predicate -> clause list to speed up insertion *)|Namespaceofstring*pbody|ShortenofF.tAst.Structured.shorthandlist*pbody|Constraintsof(F.t,ScopedTerm.t)Ast.Structured.block_constraint*pbody|Accumulatedofpbody[@@derivingshow]endmoduleFlat=structtypeunchecked_signature={toplevel_macros:macro_declaration;kinds:Arity.tF.Map.t;types:ScopeTypeExpressionUniqueList.tF.Map.t;type_abbrevs:(F.t*ScopedTypeExpression.t)list;}[@@derivingshow]typeprogram={signature:unchecked_signature;clauses:(ScopedTerm.t,Ast.Structured.attribute,bool,bool)Ast.Clause.tlist;chr:(F.t,ScopedTerm.t)Ast.Structured.block_constraintlist;builtins:BuiltInPredicate.tlist;}[@@derivingshow]endmoduleAssembled=structtypesignature={toplevel_macros:macro_declaration;kinds:Arity.tF.Map.t;types:TypingEnv.t;type_abbrevs:Type_checker.type_abbrevs;ty_names:Loc.tF.Map.t;}[@@derivingshow]typeprogram={(* for printing only *)clauses:(Ast.Structured.insertionoption*stringoption*constant*clause)list;signature:signature;total_type_checking_time:float;total_det_checking_time:float;builtins:Builtins.t;prolog_program:index;indexing:pred_infoC.Map.t;chr:CHR.t;symbols:SymbolMap.table;hash:string;}[@@derivingshow]letempty_signature()={kinds=F.Map.empty;types=TypingEnv.empty;type_abbrevs=F.Map.empty;toplevel_macros=F.Map.empty;ty_names=F.Map.empty;}letempty()={clauses=[];prolog_program={idx=Ptmap.empty;time=0;times=StrMap.empty};indexing=C.Map.empty;chr=CHR.empty;symbols=SymbolMap.empty();total_type_checking_time=0.0;total_det_checking_time=0.0;hash="";builtins=Builtins.empty;signature=empty_signature()}endmoduleCheckedFlat=structtypeprogram={signature:Assembled.signature;clauses:(ScopedTerm.t,Ast.Structured.attribute,bool,bool)Ast.Clause.tlist;chr:(Symbol.t,ScopedTerm.t)Ast.Structured.block_constraintlist;builtins:(Symbol.t*BuiltInPredicate.t)list;}[@@derivingshow]endtypescoped_program={version:string;code:Scoped.program;}[@@derivingshow]typeunchecked_compilation_unit={version:string;code:Flat.program;}[@@derivingshow](* TODO: proper hash *)lethash_basex=string_of_int@@Hashtbl.hashxtypechecked_compilation_unit={version:string;checked_code:CheckedFlat.program;base_hash:string;precomputed_signature:Assembled.signature;type_checking_time:float;det_checking_time:float;}[@@derivingshow]typechecked_compilation_unit_signature=Assembled.signature[@@derivingshow]letsignature_of_checked_compilation_unit{checked_code={CheckedFlat.signature}}=signaturetypebuiltins=string*Data.BuiltInPredicate.declarationlisttypeprogram=State.t*Assembled.programtypeheader=programmoduleWithMain=struct(* The entire program + query, but still in "printable" format *)typequery={prolog_program:index;chr:CHR.t;symbols:SymbolMap.table;runtime_types:Type_checker.runtime_types;initial_goal:term;assignments:termStrMap.t;compiler_state:State.t;total_type_checking_time:float;total_det_checking_time:float;builtins:Builtins.t;}[@@derivingshow]endtypequery=WithMain.query(****************************************************************************
Compiler
****************************************************************************)letvalid_functional=function[]->SomeAst.Structured.Relation|[Ast.Functional]->SomeFunction|_->NonemoduleRecoverStructure:sig(* Reconstructs the structure of the AST (i.e. matches { with }) *)valrun:State.t->Ast.Program.t->Ast.Structured.programvalstructure_type_expression:Loc.t->'a->(Ast.raw_attributelist->'aoption)->Ast.raw_attributelistAst.TypeExpression.t->'aAst.TypeExpression.tend=struct(* {{{ *)openAst.StructuredopenAstletcl2b=function|[]->[]|clauses->[Clauses(List.revclauses)]letstructure_clause_attributes({Clause.attributes;loc}asc)=letduplicate_errs=error~loc("duplicate attribute "^s)inletillegal_erra=error~loc("illegal attribute "^show_raw_attributea)inletillegal_replaces=error~loc("replacing rule for "^s^" cannot have a name attribute")inletillegal_remove_ids=error~loc("remove rule for "^s^" cannot have a name attribute")inletrecaux_attrsr=function|[]->r|Names::rest->ifr.id<>Nonethenduplicate_err"name";aux_attrs{rwithid=Somes}rest|Afters::rest->ifr.insertion<>Nonethenduplicate_err"insertion";aux_attrs{rwithinsertion=Some(Insert(Afters))}rest|Befores::rest->ifr.insertion<>Nonethenduplicate_err"insertion";aux_attrs{rwithinsertion=Some(Insert(Befores))}rest|Replaces::rest->ifr.insertion<>Nonethenduplicate_err"insertion";aux_attrs{rwithinsertion=Some(Replaces)}rest|Removes::rest->ifr.insertion<>Nonethenduplicate_err"insertion";aux_attrs{rwithinsertion=Some(Removes)}rest|Ifs::rest->ifr.ifexpr<>Nonethenduplicate_err"if";aux_attrs{rwithifexpr=Somes}rest|Untyped::rest->aux_attrs{rwithtypecheck=false}rest|(NoOC(* is set by the predicate *)|External_|Index_|Functional)asa::_->illegal_errainletattributes=aux_attrs{insertion=None;id=None;ifexpr=None;typecheck=true;occur_check=true}attributesinbeginmatchattributes.insertion,attributes.idwith|Some(Replacex),Some_->illegal_replacex|Some(Removex),Some_->illegal_remove_idx|_->()end;{cwithClause.attributes}letstructure_chr_attributes({Chr.attributes;loc}asc)=letduplicate_errs=error~loc("duplicate attribute "^s)inletillegal_erra=error~loc("illegal attribute "^show_raw_attributea)inletrecaux_chrr=function|[]->r|Names::rest->aux_chr{rwithcid=s}rest|Ifs::rest->ifr.cifexpr<>Nonethenduplicate_err"if";aux_chr{rwithcifexpr=Somes}rest|(Before_|After_|Replace_|Remove_|External_|Index_|Functional|Untyped|NoOC)asa::_->illegal_errainletcid=Loc.showlocin{cwithChr.attributes=aux_chr{cid;cifexpr=None}attributes}letrecstructure_type_expression_aux~locvalidt={twithTypeExpression.tit=matcht.TypeExpression.titwith|TPred(att,p,v)whenvalidatt<>None->TPred(Option.get(validatt),List.map(fun(m,p)->m,structure_type_expression_aux~locvalidp)p,v)|TPred([],_,_)->assertfalse|TPred(a::_,_,_)->error~loc("illegal attribute "^show_raw_attributea)|TArr(s,t)->TArr(structure_type_expression_aux~locvalids,structure_type_expression_aux~locvalidt)|TApp(c,x,xs)->TApp(c,structure_type_expression_aux~locvalidx,List.map(structure_type_expression_aux~locvalid)xs)|TConstc->TConstc}(*
replaces
- TArr (t1,t2) when t2 = Prop -> TPred (o:t1),
- TArr (t1,t2) when t2 = TPred l -> TPred (o:t1, l)
*)letflatten_arrowstoplevel_func=letis_propff=F.equalF.propffinletrecis_pred=function|Ast.TypeExpression.TConsta->is_propfa|TArr(_,r)->is_predr.tit|TApp(_,_,_)|TPred(_,_,_)->falseinletrecflattentloc=function|Ast.TypeExpression.TArr(l,r)->(Ast.Mode.Output,l)::flatten_locr|TConstcwhenis_propfc->[]|tit->[Output,{tit;tloc}]andflatten_loc{tit;tloc}=flattentloctitandmain=function|Ast.TypeExpression.TPred(b,l,v)->Ast.TypeExpression.TPred(b,List.map(fun(a,b)->a,main_locb)l,v)|TConst_ast->t|TApp(n,x,xs)->TApp(n,main_locx,List.mapmain_locxs)|TArr(l,r)whenis_predr.tit->TPred(toplevel_func,(Output,main_locl)::flatten_locr,false)|TArr(l,r)->TArr(main_locl,main_locr)andmain_loc{tit;tloc}={tit=maintit;tloc}inmain_locletstructure_type_expressionloctoplevel_funcvalidt=letres=matcht.TypeExpression.titwith|TPred([],p,v)->{twithtit=TPred(toplevel_func,List.map(fun(m,p)->m,structure_type_expression_aux~locvalidp)p,v)}|x->structure_type_expression_aux~locvalidtinflatten_arrowstoplevel_funcresletstructure_kind_attributes{Type.attributes;loc;name;ty}=letty=structure_type_expressionloc()(function[]->Some()|_->None)tyinmatchattributeswith|[]->{Type.attributes=();loc;name;ty}|x::_->error~loc("illegal attribute "^show_raw_attributex)letstructure_external~loc=function|None->Builtin{variant=0}|Some"core"->Core|Somes->try(Builtin{variant=int_of_strings})withInvalid_argument_->error~loc("illegal external attribute")letstructure_type_attributes{Type.attributes;loc;name;ty}:(symbol_attribute,functionality)Type.t=letduplicate_errs=error~loc("duplicate attribute "^s)inletillegal_erra=error~loc("illegal attribute "^show_raw_attributea)inletrecaux_tatt(r:symbol_attribute)f=function|[]->r,f|Externalo::rest->beginmatchr.availabilitywith|Structured.Elpi->aux_tatt{rwithavailability=Structured.OCaml(structure_external~loco)}frest|Structured.OCaml_->duplicate_err"external"end|Index(i,index_type)::rest->letit=matchindex_typewith|None->None|Some"Map"->SomeMap|Some"Hash"->SomeHashMap|Some"DTree"->SomeDiscriminationTree|Somes->error~loc("unknown indexing directive "^s^". Valid ones are: Map, Hash, DTree.")inbeginmatchr.indexwith|None->aux_tatt{rwithindex=Some(Structured.Index(i,it))}frest|Some_->duplicate_err"index"end|NoOC::rest->aux_tatt{rwithoccur_check_pred=false}frest|Functional::rest->aux_tattrStructured.Functionrest|(Before_|After_|Replace_|Remove_|Name_|If_|Untyped)asa::_->illegal_errainletattributes,toplevel_func=aux_tatt{availability=Elpi;index=None;occur_check_pred=true}Structured.Relationattributesinletis_functional_from_ty()=matchty.titwith|TPred(l,_,_)->List.memFunctionall|_->falseinletattributes=matchattributes.indexwith|None->{attributeswithindex=iftoplevel_func=Function||is_functional_from_ty()thenSomeMaximizeForFunctionalelseNone}|Some_->attributesinletty=structure_type_expressionloctoplevel_funcvalid_functionaltyin{Type.attributes;loc;name;ty}letstructure_type_abbreviation{TypeAbbreviation.name;value;nparams;loc}=letrecaux=function|TypeAbbreviation.Lam(c,loc,t)->TypeAbbreviation.Lam(c,loc,auxt)|TypeAbbreviation.Tyt->TypeAbbreviation.Ty(structure_type_expressionlocRelationvalid_functionalt)in{TypeAbbreviation.name;value=auxvalue;nparams;loc}letrun_dl=letrecaux_runnsblocksclausesmacroskindstypestabbrschraccs=function|Program.Ignored_::rest->aux_runnsblocksclausesmacroskindstypestabbrschraccsrest|(Program.End_::_|[])asrest->{body=List.rev(cl2bclauses@blocks);types=(*List.rev*)types;(* we prefer the last one *)kinds=List.revkinds;type_abbrevs=List.revtabbrs;macros=List.revmacros},List.revchr,rest|Program.Beginloc::rest->letp,chr1,rest=aux_runns[][][][][][][]accsrestinifchr1<>[]thenerror"CHR cannot be declared inside an anonymous block";aux_end_blocklocns(Accumulatedp::cl2bclauses@blocks)[]macroskindstypestabbrschraccsrest|Program.Constraint(loc,ctx_filter,clique)::rest->ifchr<>[]thenerror"Constraint blocks cannot be nested";letp,chr,rest=aux_runns[][][][][][][]accsrestinaux_end_blocklocns(Constraints({loc;ctx_filter;clique;rules=chr},p)::cl2bclauses@blocks)[]macroskindstypestabbrs[]accsrest|Program.Namespace(loc,n)::rest->letp,chr1,rest=aux_run(n::ns)[][][][][][][]StrSet.emptyrestinifchr1<>[]thenerror"CHR cannot be declared inside a namespace block";aux_end_blocklocns(Namespace(n,p)::cl2bclauses@blocks)[]macroskindstypestabbrschraccsrest|Program.Shorten(loc,[])::_->anomaly~loc"parser returns empty list of shorten directives"|Program.Shorten(loc,directives)::rest->letshorthand(full_name,short_name)={iloc=loc;full_name;short_name}inletshorthands=List.mapshorthanddirectivesinletp,chr1,rest=aux_runns[][][][][][][]accsrestinifchr1<>[]thenerror"CHR cannot be declared after a shorthand";aux_runns((Shorten(shorthands,p)::cl2bclauses@blocks))[]macroskindstypestabbrschraccsrest|Program.Accumulated(_,[])::rest->aux_runnsblocksclausesmacroskindstypestabbrschraccsrest|Program.Accumulated(loc,{file_name;digest;ast=a}::more)::rest->letrest=Program.Accumulated(loc,more)::restinletdigest=String.concat"."(digest::List.mapF.showns)inifStrSet.memdigestaccsthenbegin(* Printf.eprintf "skip: %s\n%!" filename; *)aux_runnsblocksclausesmacroskindstypestabbrschraccsrestendelsebegin(* Printf.eprintf "acc: %s -> %d\n%!" filename (List.length a); *)aux_runnsblocksclausesmacroskindstypestabbrschr(StrSet.adddigestaccs)(Program.Beginloc::a@Program.Endloc::rest)end|Program.Clausec::rest->letc=structure_clause_attributescinaux_runnsblocks(c::clauses)macroskindstypestabbrschraccsrest|Program.Macrom::rest->aux_runnsblocksclauses(m::macros)kindstypestabbrschraccsrest|Program.Predt::rest->lett=structure_type_attributestinaux_runnsblocksclausesmacroskinds(t::types)tabbrschraccsrest|Program.Kind[]::rest->aux_runnsblocksclausesmacroskindstypestabbrschraccsrest|Program.Kind(k::ks)::rest->letk=structure_kind_attributeskinaux_runnsblocksclausesmacros(k::kinds)typestabbrschraccs(Program.Kindks::rest)|Program.Type[]::rest->aux_runnsblocksclausesmacroskindstypestabbrschraccsrest|Program.Type(t::ts)::rest->ifList.memFunctionalt.attributesthenerror~loc:t.loc"functional attribute only applies to pred";lett=structure_type_attributestinaux_runnsblocksclausesmacroskinds(t::types)tabbrschraccs(Program.Typets::rest)|Program.TypeAbbreviationabbr::rest->letabbr=structure_type_abbreviationabbrinaux_runnsblocksclausesmacroskindstypes(abbr::tabbrs)chraccsrest|Program.Chrr::rest->letr=structure_chr_attributesrinaux_runnsblocksclausesmacroskindstypestabbrs(r::chr)accsrestandaux_end_blocklocnsblocksclausesmacroskindstypestabbrschraccsrest=matchrestwith|Program.End_::rest->aux_runnsblocksclausesmacroskindstypestabbrschraccsrest|_->error~loc"matching } is missing"inletblocks,chr,rest=aux_run[][][][][][][][]StrSet.emptydlinbeginmatchrestwith|[]->()|Program.Endloc::_->error~loc"extra }"|_->assertfalseend;ifchr<>[]thenerror"CHR cannot be declared outside a Constraint block";blocksend(* }}} *)moduleQuotation=structletnamed_quotations:QuotationHooks.quotationStrMap.tState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:named_quotations"~pp:(fun__->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(funx->Somex)~execution_is_over:(funx->Somex)~init:(fun()->StrMap.empty)()letdefault_quotation:QuotationHooks.quotationoptionState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:default_quotation"~pp:(fun__->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(funx->Somex)~execution_is_over:(funx->Somex)~init:(fun()->None)()endincludeQuotationmoduleCustomFunctorCompilation=structletis_singlequotex=lets=F.showxinletlen=String.lengthsinlen>2&&s.[0]=='\''&&s.[len-1]=='\''letis_backtickx=lets=F.showxinletlen=String.lengthsinlen>2&&s.[0]=='`'&&s.[len-1]=='`'letsinglequote:(string*QuotationHooks.quotation)optionState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:singlequote"~pp:(fun__->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(funx->Somex)~execution_is_over:(funx->Somex)~init:(fun()->None)()letbacktick:(string*QuotationHooks.quotation)optionState.component=State.declare~descriptor:elpi_state_descriptor~name:"elpi:backtick"~pp:(fun__->())~clause_compilation_is_over:(funb->b)~compilation_is_over:(funx->Somex)~execution_is_over:(funx->Somex)~init:(fun()->None)()letscope_singlequote~locstatex=matchState.getsinglequotestatewith|None->ScopedTerm.mkGlobalApp~locx[]|Some(language,f)->ScopedTerm.(unlock@@of_simple_term_loc@@f~languagestateloc(F.showx))letscope_backtick~locstatex=matchState.getbacktickstatewith|None->ScopedTerm.mkGlobalApp~locx[]|Some(language,f)->ScopedTerm.(unlock@@of_simple_term_loc@@f~languagestateloc(F.showx))endletnamespace_separatorc='.'letnamespace_separator=String.make1namespace_separatorcletprefix_constprefixc=F.from_string(String.concatnamespace_separator(prefix@[F.showc]))letprependps=F.Set.map(prefix_constp)slethas_dotf=trylet_=String.index(F.showf)namespace_separatorcintruewithNot_found->falsetypemtm={macros:(ScopedTerm.t*Loc.t)F.Map.t;ctx:F.Set.t;needs_spilling:boolref;}letempty_mtm={macros=F.Map.empty;ctx=F.Set.empty;needs_spilling=reffalse}lettodoppname_fmt_=error("pp not implemented for field: "^name)letget_mtm,set_mtm,_drop_mtm,update_mtm=letmtm=State.declare~name:"elpi:mtm"~pp:(todopp"elpi:mtm")~descriptor:D.elpi_state_descriptor~clause_compilation_is_over:(fun_->empty_mtm)~compilation_is_over:(fun_->None)~execution_is_over:(fun_->None)~init:(fun()->empty_mtm)()inState.(getmtm,setmtm,dropmtm,updatemtm)moduleScope_Quotation_Macro:sigvalrun:State.t->toplevel_macros:macro_declaration->Ast.Structured.program->Scoped.programvalscope_loc_term:state:State.t->Ast.Term.t->ScopedTerm.tend=structletmap_appendenvAst.Type.{name;loc}vm=letk=nameintryletl=F.Map.findkminF.Map.addk(ScopeTypeExpressionUniqueList.mergeenvvl)mwithNot_found->F.Map.addkvmletis_uvar_namef=F.is_uvar_namefletis_globalf=(F.showf).[0]='.'letof_globalf=lets=F.showfinF.from_string@@String.subs1(String.lengths-1)letis_discardf=F.(equalfdummyname)||letc=(F.showf).[0]inc='_'letis_macro_namef=letc=(F.showf).[0]inc='@'letrecpred2arrctx~locfuncvariadic=function|[]->ScopedTypeExpression.Propfunc|[m,x]whenvariadic->Arrow(m,Variadic,scope_loc_tyectxx,{loc;it=ScopedTypeExpression.Propfunc})|(m,x)::xs->Arrow(m,NotVariadic,scope_loc_tyectxx,{loc;it=pred2arrctx~locfuncvariadicxs})andscope_tyectx~loct:ScopedTypeExpression.t_=matchtwith|Ast.TypeExpression.TConstcwhenF.equalF.propfc->PropRelation|TConstcwhenF.showc="any"->Any|TConstcwhenF.Set.memcctx->Const(Boundelpi_language,c)|TConstcwhenis_globalc->Const(Scope.mkGlobal~escape_ns:true(),of_globalc)|TConstc->Const(Scope.mkGlobal(),c)|TApp(c,x,[y])whenF.showc="variadic"->(* Convention all arguments of a variadic function are in input *)Arrow(Input,Variadic,scope_loc_tyectxx,scope_loc_tyectxy)|TApp(c,x,xs)whenis_globalc->App(Scope.mkGlobal~escape_ns:true(),of_globalc,scope_loc_tyectxx,List.map(scope_loc_tyectx)xs)|TApp(c,x,xs)->ifF.Set.memcctx||is_uvar_namecthenerror~loc"type schema parameters cannot be type formers";App(Scope.mkGlobal(),c,scope_loc_tyectxx,List.map(scope_loc_tyectx)xs)|TPred(m,xs,v)->pred2arrctx~locmvxs|TArr(s,t)->Arrow(Output,NotVariadic,scope_loc_tyectxs,scope_loc_tyectxt)andscope_loc_tyectx{tloc;tit}={loc=tloc;it=scope_tyectx~loc:tloctit}letscope_loc_tyectx(t:Ast.Structured.functionalityAst.TypeExpression.t)=scope_loc_tyectxtletcompile_type{Ast.Type.name;loc;attributes={Ast.Structured.index;availability;occur_check_pred};ty}=letopenScopedTypeExpressioninletvalue=scope_loc_tyeF.Set.emptytyinletvars=letrecauxe{it}=matchitwith|App(_,_,x,xs)->List.fold_leftauxe(x::xs)|Const(Bound_,_)->assertfalse(* there are no binders yet *)|Const(Global_,c)whenis_uvar_namec->F.Set.addce|Const(Global_,_)->e|Any|Prop_->e|Arrow(_,_,x,y)->aux(auxex)yinauxF.Set.emptyvalueinletvalue=scope_loc_tyevarstyinletnparams=F.Set.cardinalvarsinletvalue=letrecclosest=ifF.Set.is_emptysthentelseletc=F.Set.choosesinlets=F.Set.removecsincloses(Lam(c,t))inclosevars(Tyvalue)in{ScopedTypeExpression.name;index;availability;occur_check=occur_check_pred;loc;nparams;value}letscope_term_macro~loc~statecargs=let{macros}=get_mtmstateinmatchF.Map.find_optcmacroswith|None->error~loc(Format.asprintf"@[<hv>Unknown macro %a.@ Known macros: %a@]"F.ppc(pplistF.pp", ")(F.Map.bindingsmacros|>List.mapfst))|Some(t,_)->ScopedTerm.(beta(clone_loc~loct)args)(* would be better when symbols are resolved, in particular andf, nil and cons *)letrecscope_term~statectx~loct=letopenAst.Terminmatchtwith|Parens{loc;it}->scope_term~statectx~locit|Constcwhenis_discardc->ScopedTerm.Discard{heapify=false}|Constcwhenis_macro_namec->scope_term_macro~loc~statec[]|ConstcwhenF.Set.memcctx->ScopedTerm.mkBoundApp~lang:elpi_language~locc[]|Constc->ifis_uvar_namecthenScopedTerm.mkUVar~locc[]elseifCustomFunctorCompilation.is_singlequotecthenCustomFunctorCompilation.scope_singlequote~locstatecelseifCustomFunctorCompilation.is_backtickcthenCustomFunctorCompilation.scope_backtick~locstatecelseifis_globalcthenScopedTerm.mkGlobalApp~escape_ns:true~loc(of_globalc)[]elseScopedTerm.mkGlobalApp~locc[]|App({it=App(f,l1)},l2)->scope_term~statectx~loc(App(f,l1@l2))|App({it=Parensf},l)->scope_term~statectx~loc(App(f,l))|App({it=Constc},[x])whenF.equalcF.spillf->let{needs_spilling}=get_mtmstateinneeds_spilling:=true;ScopedTerm.Spill(scope_loc_term~statectxx,refScopedTerm.NoInfo)|App({it=Constc;loc=cloc},l)whenScopedTerm.SimpleTerm.is_implfc->beginmatchlwith|[t1;t2]->(* Printf.eprintf "LHS= %s\n" (Ast.Term.show t1); *)Impl(ScopedTerm.SimpleTerm.func_to_impl_kindc,cloc,scope_loc_term~statectxt1,scope_loc_term~statectxt2)|_->error~loc"implication is a binary operator"end|App({it=Constc;loc=cloc},xs)->ifis_discardcthenerror~loc"Applied discard";letxs=List.map(scope_loc_term~statectx)xsinifis_macro_namecthenscope_term_macro~loc~statecxselseletbound=F.Set.memcctxinifboundthenScopedTerm.mkBoundApp~lang:elpi_language~loc:cloccxselseifis_uvar_namecthenScopedTerm.mkUVar~loc:cloccxselseifis_globalcthenScopedTerm.mkGlobalApp~escape_ns:true~loc:cloc(of_globalc)xselseScopedTerm.mkGlobalApp~loc:cloccxs|Cast(t,ty)->lett=scope_loc_term~statectxtinletty=scope_loc_tyeF.Set.empty(RecoverStructure.structure_type_expressionty.Ast.TypeExpression.tlocAst.Structured.Relationvalid_functionalty)inScopedTerm.Cast(t,ty)|Lam(c,_,ty,b)whenis_discardc->letty=ty|>Option.map(funty->scope_loc_tyeF.Set.empty(RecoverStructure.structure_type_expressionty.Ast.TypeExpression.tlocAst.Structured.Relationvalid_functionalty))inScopedTerm.Lam(None,ty,scope_loc_term~statectxb)|Lam(c,cloc,ty,b)->ifhas_dotcthenerror~loc"Bound variables cannot contain the namespaec separator '.'";letty=ty|>Option.map(funty->scope_loc_tyeF.Set.empty(RecoverStructure.structure_type_expressionty.Ast.TypeExpression.tlocAst.Structured.Relationvalid_functionalty))inletname=Some(ScopedTerm.mk_binder~lang:elpi_languagec~loc:cloc)inScopedTerm.Lam(name,ty,scope_loc_term~state(F.Set.addcctx)b)|CDatac->ScopedTerm.CDatac(* CData.hcons *)|App({it=Lam_},_)->error~loc"Beta-redexes not allowed, use something like (F = x\\x, F a)"|App({it=CData_},_)->error~loc"Applied literal"|App({it=Quoted_},_)->error~loc"Applied quotation"|App({it=Cast_},_)->error~loc"Casted app not supported yet"|Quoted_->assertfalseandscope_loc_term~statectx{Ast.Term.it;loc}=matchitwith|Quoted{Ast.Term.data;kind;qloc}->letunquote=matchkindwith|None->letdefault_quotation=State.getdefault_quotationstateinifOption.is_nonedefault_quotationthenanomaly~loc"No default quotation";option_getdefault_quotation~language:"default"|Somename->letnamed_quotations=State.getnamed_quotationsstateintryStrMap.findnamenamed_quotations~language:namewithNot_found->anomaly~loc("No '"^name^"' quotation")inletstate=update_mtmstate(funx->{xwithctx})inletsimple_t=tryunquotestateqlocdatawithElpi_parser.Parser_config.ParseError(loc,msg)->error~locmsginScopedTerm.of_simple_term_locsimple_t|_->letit=scope_term~statectx~locitin{ScopedTerm.it;loc;ty=TypeAssignment.new_ty()}letscope_loc_term~state=let{ctx}=get_mtmstateinscope_loc_term~statectxletscope_type_abbrev{Ast.TypeAbbreviation.name;value;nparams;loc}=letrecauxctx=function|Ast.TypeAbbreviation.Lam(c,loc,t)whenis_uvar_namec->ifF.Set.memcctxthenerror~loc"duplicate type schema variable";ScopedTypeExpression.Lam(c,aux(F.Set.addcctx)t)|Ast.TypeAbbreviation.Lam(c,loc,_)->error~loc"only variables can be abstracted in type schema"|Ast.TypeAbbreviation.Tyt->ScopedTypeExpression.Ty(scope_loc_tyectxt)in{ScopedTypeExpression.name;value=auxF.Set.emptyvalue;nparams;loc;index=None;occur_check=true;availability=Elpi}letcompile_type_abbrev({Ast.TypeAbbreviation.name;nparams;loc}asab)=letab=scope_type_abbrevabinname,abletdefs_of_mapm=F.Map.bindingsm|>List.fold_left(funx(a,_)->F.Set.addax)F.Set.emptyletdefs_of_assoclistm=m|>List.fold_left(funx(a,_)->F.Set.addax)F.Set.emptyletglobal_hd_symbols_of_clausescl=letopenScopedTerminletadd1~locst=matcht.itwith|App({scope=Global_;name=c},_)->F.Set.addcs|Impl(R2L,_,{it=(App({scope=Global_;name=c},_))},_)->F.Set.addcs|Impl(R2L,_,{it=(UVar_)},_)|UVar_->error~loc"Variables cannot be used as predicate names"|_->error~loc"Cannot determine the predicate for this rule"inList.fold_left(funs{Ast.Clause.body;loc}->matchbody.itwith|App({scope=Global_;name=c},xs)whenF.equalF.andfc->(* since we allow a rule to be of the form (p :- ..., q :- ...) eg
via macro expansion, we could have , in head position *)List.fold_left(add1~loc)sxs|_->add1~locsbody)F.Set.emptyclletcompile_clausestatemacros{Ast.Clause.body;attributes;loc;needs_spilling=()}=letneeds_spilling=reffalseinletstate=set_mtmstate{empty_mtmwithmacros;needs_spilling}inletbody=scope_loc_term~statebodyin{Ast.Clause.body;attributes;loc;needs_spilling=!needs_spilling}letcompile_sequentstatemacros{Ast.Chr.eigen;context;conclusion}=letstate=set_mtmstate{empty_mtmwithmacros}in{Ast.Chr.eigen=scope_loc_term~stateeigen;context=scope_loc_term~statecontext;conclusion=scope_loc_term~stateconclusion}letcompile_chr_rulestatemacros{Ast.Chr.to_match;to_remove;guard;new_goal;attributes;loc}=letto_match=List.map(compile_sequentstatemacros)to_matchinletto_remove=List.map(compile_sequentstatemacros)to_removeinletguard=Option.map(scope_loc_term~state:(set_mtmstate{empty_mtmwithmacros}))guardinletnew_goal=Option.map(compile_sequentstatemacros)new_goalin{Ast.Chr.to_match;to_remove;guard;new_goal;attributes;loc}letcompile_kindkinds{Ast.Type.name;ty;loc}=letopenAst.TypeExpressioninletreccount=function|TArr({tit=TConstc},t)whenF.equalcF.typef->1+countt.tit|TConstcwhenF.equalcF.typef->0|x->error~loc"Syntax error: illformed kind.\nExamples:\nkind bool type.\nkind list type -> type.\n"inF.Map.addname(countty.tit,loc)kindsletcompile_macrostate(am,m){Ast.Macro.loc;name;body}=trylet_,oloc=F.Map.findnameminerror~loc(Format.asprintf"duplicate macro %a, previous declaration %a"F.ppnameLoc.ppoloc)withNot_found->letbody=scope_loc_term~state:(set_mtmstate{empty_mtmwithmacros=m})bodyinF.Map.addname(body,loc)am,F.Map.addname(body,loc)mletrunstate~toplevel_macrosp:Scoped.program=letreccompile_programomacrosstate{Ast.Structured.macros;kinds;types;type_abbrevs;body}=lettoplevel_macros,active_macros=List.fold_left(compile_macrostate)(F.Map.empty,omacros)macrosinlettype_abbrevs=List.mapcompile_type_abbrevtype_abbrevsinletkinds=List.fold_leftcompile_kindF.Map.emptykindsinlettypes=List.fold_left(funmt->map_appendTypingEnv.emptyt(ScopeTypeExpressionUniqueList.make@@compile_typet)m)F.Map.empty(List.revtypes)inletta_t_captures=List.filter_map(fun(k,loc)->ifF.Map.memkkindsthenSome(k,loc,F.Map.findkkinds)elseNone)type_abbrevsinifta_t_captures<>[]thenbeginletta,tsd,(_,oloc)=List.hdta_t_capturesinlettad=List.assoctatype_abbrevsinerror~loc:tad.ScopedTypeExpression.loc("Illegal type abbreviation for "^F.showta^". A type with the same name already exists in "^Loc.showoloc)end;letdefs_k=defs_of_mapkindsinletdefs_t=defs_of_maptypesinletdefs_ta=defs_of_assoclisttype_abbrevsinletkinds,types,type_abbrevs,defs_b,defs_ty,body=compile_bodyactive_macroskindstypestype_abbrevsF.Set.emptyF.Set.emptystatebodyinletty_symbols=F.Set.(uniondefs_k(uniondefs_t(uniondefs_tadefs_ty)))inletpred_symbols=F.Set.(uniondefs_tdefs_b)in(* Format.eprintf "CP: types: %d\n" (F.Map.cardinal types);
Format.eprintf "CP: ty_sym: %a\n" F.Set.pp ty_symbols; *)toplevel_macros,{Scoped.types;kinds;type_abbrevs;body;ty_symbols;pred_symbols}andcompile_bodymacroskindstypestype_abbrevs(defs:F.Set.t)(ty_defs:F.Set.t)state=function|[]->kinds,types,type_abbrevs,defs,ty_defs,[]|Clausescl::rest->letcompiled_cl=List.map(compile_clausestatemacros)clinletdefs=F.Set.uniondefs(global_hd_symbols_of_clausescompiled_cl)inletkinds,types,type_abbrevs,defs,ty_defs,compiled_rest=compile_bodymacroskindstypestype_abbrevsdefsty_defsstaterestinletcompiled_rest=matchcompiled_restwith|Scoped.Clausesl::rest->Scoped.Clauses(compiled_cl@l)::rest|rest->Scoped.Clausescompiled_cl::restinkinds,types,type_abbrevs,defs,ty_defs,compiled_rest|Namespace(prefix,p)::rest->letprefix=F.showprefixinlet_,p=compile_programmacrosstatepinletkinds,types,type_abbrevs,defs,ty_defs,compiled_rest=compile_bodymacroskindstypestype_abbrevsdefsty_defsstaterestinletty_symbols=prepend[prefix]p.Scoped.ty_symbolsin(* Format.eprintf "CB: ty_sym %s: %a\n" prefix F.Set.pp ty_symbols; *)letpred_symbols=prepend[prefix]p.Scoped.pred_symbolsinkinds,types,type_abbrevs,F.Set.uniondefspred_symbols,F.Set.unionty_defsty_symbols,Scoped.Namespace(prefix,p)::compiled_rest|Shorten(shorthands,p)::rest->letshorts=List.fold_left(funs{Ast.Structured.short_name}->F.Set.addshort_names)F.Set.emptyshorthandsinlet_,p=compile_programmacrosstatepinletkinds,types,type_abbrevs,defs,ty_defs,compiled_rest=compile_bodymacroskindstypestype_abbrevsdefsty_defsstaterestinkinds,types,type_abbrevs,F.Set.uniondefs(F.Set.diffp.Scoped.pred_symbolsshorts),(* TODO shorten/ shorten-ty *)F.Set.unionty_defs(F.Set.diffp.Scoped.ty_symbolsshorts),Scoped.Shorten(shorthands,p)::compiled_rest|Constraints({loc;ctx_filter;clique;rules},p)::rest->(* XXX missing check for nested constraints *)letrules=List.map(compile_chr_rulestatemacros)rulesinlet_,p=compile_programmacrosstatepinletkinds,types,type_abbrevs,defs,ty_defs,compiled_rest=compile_bodymacroskindstypestype_abbrevsdefsty_defsstaterestinkinds,types,type_abbrevs,F.Set.uniondefsp.Scoped.pred_symbols,F.Set.unionty_defsp.Scoped.ty_symbols,Scoped.Constraints({loc;ctx_filter;clique;rules},p)::compiled_rest|Accumulatedp::rest->let_,p=compile_programmacrosstatepinletkinds,types,type_abbrevs,defs,ty_defs,compiled_rest=compile_bodymacroskindstypestype_abbrevsdefsty_defsstaterestinkinds,types,type_abbrevs,F.Set.uniondefsp.Scoped.pred_symbols,F.Set.unionty_defsp.Scoped.ty_symbols,Scoped.Accumulatedp::compiled_restinlettoplevel_macros,pbody=compile_programtoplevel_macrosstatepin(* Printf.eprintf "run: %d\n%!" (F.Map.cardinal toplevel_macros); *){Scoped.pbody;toplevel_macros}endmoduleFlatten:sig(* Eliminating the structure (name spaces) *)valrun:State.t->Scoped.program->Flat.programvalmerge_kinds:Arity.tF.Map.t->Arity.tF.Map.t->Arity.tF.Map.tvalmerge_type_assignments:TypingEnv.t->TypingEnv.t->TypingEnv.tvalmerge_checked_type_abbrevs:Type_checker.type_abbrevs->Type_checker.type_abbrevs->Type_checker.type_abbrevsvalmerge_toplevel_macros:TypingEnv.t->(ScopedTerm.t*Loc.t)F.Map.t->(ScopedTerm.t*Loc.t)F.Map.t->(ScopedTerm.t*Loc.t)F.Map.tend=structtypesubst={old_prefix:stringlist;subst:F.tF.Map.t}letempty_subst={old_prefix=[];subst=F.Map.empty}letpush_substextra_prefixsymbols_affected{old_prefix;subst=oldsubst}=letnew_prefix=old_prefix@[extra_prefix]inletnewsubst=F.Set.fold(funcsubst->letc1=prefix_constnew_prefixcinF.Map.addcc1subst)symbols_affectedoldsubstin{old_prefix=new_prefix;subst=newsubst}letpush_subst_shorthandsshorthands{old_prefix;subst=oldsubst}=letpush1m{Ast.Structured.short_name;full_name}=F.Map.addshort_name(tryF.Map.findfull_namemwithNot_found->full_name)min{old_prefix;subst=List.fold_leftpush1oldsubstshorthands}letsmart_map_scoped_termf~tyf:tyft=letopenScopedTerminletrecauxit=matchitwith|Impl(b,lb,t1,t2)->lett1'=aux_loct1inlett2'=aux_loct2inift1==t1'&&t2==t2'thenitelseImpl(b,lb,t1',t2')|Spill(t,n)->lett'=aux_loctinift'==tthenitelseSpill(t',n)|App({scope;name=c;ty;loc},xs)->letc'=matchscopewithGlobal{escape_ns=false}->fc|_->cinletxs'=smart_mapaux_locxsinifc==c'&&xs==xs'thenitelseApp({scope=Scope.mkGlobal();name=c';ty;loc},xs')|Lam(n,ty,b)->letb'=aux_locbinletty'=option_smart_map(ScopedTypeExpression.smart_map_scoped_loc_tytyf)tyinifb==b'&&ty'==tythenitelseLam(n,ty',b')|UVar(c,l)->letl'=smart_mapaux_loclinifl==l'thenitelseUVar(c,l')|Cast(t,ty)->lett'=aux_loctinletty'=ScopedTypeExpression.smart_map_scoped_loc_tytyftyinift'==t&&ty'==tythenitelseCast(t',ty')|Discard_->it|CData_->itandaux_loc({it;loc;ty}asorig)=letit'=auxitinifit==it'thenorigelse{it=it';loc;ty}inaux_loctletsmart_map_clausef({Ast.Clause.body}asx)=letbody'=fbodyinifbody==body'thenxelse{xwithbody=body'}letsubst_global{subst=s}f=tryF.Map.findfswithNot_found->fletapply_subst_clausessty_scl=smart_map(smart_map_clause(smart_map_scoped_term(subst_globals)~tyf:(subst_globalty_s)))clletsmart_map_sequentf~tyf({Ast.Chr.eigen;context;conclusion}asorig)=leteigen'=smart_map_scoped_termf~tyfeigeninletcontext'=smart_map_scoped_termf~tyfcontextinletconclusion'=smart_map_scoped_termf~tyfconclusioninifeigen'==eigen&&context'==context&&conclusion'==conclusionthenorigelse{Ast.Chr.eigen=eigen';context=context';conclusion=conclusion'}letsmart_map_chrf~tyf({Ast.Chr.to_match;to_remove;guard;new_goal;attributes;loc}asorig)=letto_match'=smart_map(smart_map_sequentf~tyf)to_matchinletto_remove'=smart_map(smart_map_sequentf~tyf)to_removeinletguard'=Util.option_map(smart_map_scoped_termf~tyf)guardinletnew_goal'=Util.option_map(smart_map_sequentf~tyf)new_goalinifto_match'==to_match&&to_remove'==to_remove&&guard'==guard&&new_goal'==new_goalthenorigelse{Ast.Chr.to_match=to_match';to_remove=to_remove';guard=guard';new_goal=new_goal';attributes;loc}letsmart_map_chrsf~tyf({Ast.Structured.clique;ctx_filter;rules;loc}asorig)=letclique'=smart_mapfcliqueinletctx_filter'=smart_mapfctx_filterinletrules'=smart_map(smart_map_chrf~tyf)rulesinifclique'==clique&&ctx_filter'==ctx_filter&&rules'==rulesthenorigelse{Ast.Structured.clique=clique';ctx_filter=ctx_filter';rules=rules';loc}letapply_subst_chrsssty=smart_map_chrs(subst_globals)~tyf:(subst_globalsty)letapply_subst_typess=ScopeTypeExpressionUniqueList.smart_map(ScopedTypeExpression.smart_map(subst_globals))letapply_subst_typessl=F.Map.fold(funkvm->F.Map.add(subst_globalsk)(apply_subst_typessv)m)lF.Map.emptyletapply_subst_kindssl=F.Map.fold(funkvm->F.Map.add(subst_globalsk)vm)lF.Map.emptyletapply_subst_type_abbrevssl=List.map(fun(k,v)->subst_globalsk,ScopedTypeExpression.smart_map(subst_globals)v)lletmerge_type_assignments=TypingEnv.merge_envsletmerge_checked_type_abbrevsm1m2=letm=F.Map.union(funk(sk,otherlocasx)(ty,loc)->ifTypeAssignment.compare_skemaskty<>0thenerror~loc("Duplicate type abbreviation for "^F.showk^". Previous declaration: "^Loc.showotherloc)elseSomex)m1m2inmletmerge_typesenvt1t2=F.Map.union(fun_l1l2->Some(ScopeTypeExpressionUniqueList.mergeenvl1l2))t1t2letmerge_kindst1t2=F.Map.union(funf(k,loc1askdecl)(k',loc2)->ifk==k'thenSomekdeclelseerror~loc:loc2("Duplicate kind declaration for "^F.showf^". Previously declared in "^Loc.showloc1);)t1t2letmerge_type_abbrevsm1m2=m1@m2letmerge_toplevel_macrosenvotlmtoplevel_macros=F.Map.union(funk(m1,l1)(m2,l2)->ifScopedTerm.equalenv~types:falsem1m2thenSome(m1,l1)elseerror~loc:l2(Format.asprintf"@[<v>Macro %a declared twice.@;@[<hov 2>%a @[%a@]@]@;@[<hov 2>%a @[%a@]@]@]"F.ppkLoc.ppl1ScopedTerm.prettym1Loc.ppl2ScopedTerm.prettym2))otlmtoplevel_macrosletreccompile_blockkindstypestype_abbrevsclauseschrpred_substty_subst=function|[]->kinds,types,type_abbrevs,clauses,chr|Scoped.Shorten(shorthands,{kinds=k;types=t;type_abbrevs=ta;body;pred_symbols=_;ty_symbols=_})::rest->letinpsubst=push_subst_shorthandsshorthandspred_substinletintysubst=push_subst_shorthandsshorthandsty_substinletkinds=merge_kinds(apply_subst_kindsintysubstk)kindsinlettypes=merge_typesTypingEnv.empty(apply_subst_typesintysubstt)typesinlettype_abbrevs=merge_type_abbrevstype_abbrevs(apply_subst_type_abbrevsintysubstta)inletkinds,types,type_abbrevs,clauses,chr=compile_blockkindstypestype_abbrevsclauseschrinpsubstintysubstbodyincompile_blockkindstypestype_abbrevsclauseschrpred_substty_substrest|Scoped.Namespace(extra,{kinds=k;types=t;type_abbrevs=ta;body;pred_symbols=ps;ty_symbols=ts})::rest->letnew_pred_subst=push_substextrapspred_substinletnew_ty_subst=push_substextratsty_substinletkinds=merge_kinds(apply_subst_kindsnew_ty_substk)kindsin(* Format.eprintf "@[<v>Types before:@ %a@]@," F.Map.(pp ScopeTypeExpressionUniqueList.pretty) t; *)lettypes=merge_typesTypingEnv.empty(apply_subst_typesnew_ty_substt)typesin(* Format.eprintf "@[<v>Types after:@ %a@]@," F.Map.(pp ScopeTypeExpressionUniqueList.pretty) (apply_subst_types new_ty_subst t); *)lettype_abbrevs=merge_type_abbrevstype_abbrevs(apply_subst_type_abbrevsnew_ty_substta)inletta_t_captures=List.filter_map(fun(k,loc)->ifF.Map.memkkindsthenSome(k,loc,F.Map.findkkinds)elseNone)type_abbrevsinifta_t_captures<>[]thenbeginletta,tad,(_,oloc)=List.hdta_t_capturesinerror~loc:tad.ScopedTypeExpression.loc("Illegal type abbreviation for "^F.showta^". A type with the same name already exists in "^Loc.showoloc)end;letkinds,types,type_abbrevs,clauses,chr=compile_blockkindstypestype_abbrevsclauseschrnew_pred_substnew_ty_substbodyincompile_blockkindstypestype_abbrevsclauseschrpred_substty_substrest|Scoped.Clausescl::rest->letcl=apply_subst_clausespred_substty_substclinletclauses=cl::clausesincompile_blockkindstypestype_abbrevsclauseschrpred_substty_substrest|Scoped.Constraints(ch,{kinds=k;types=t;type_abbrevs=ta;body})::rest->letkinds=merge_kinds(apply_subst_kindsty_substk)kindsinlettypes=merge_typesTypingEnv.empty(apply_subst_typesty_substt)typesinlettype_abbrevs=merge_type_abbrevstype_abbrevs(apply_subst_type_abbrevsty_substta)in(* let modes = merge_modes (apply_subst_modes subst m) modes in *)letchr=apply_subst_chrspred_substty_substch::chrinletkinds,types,type_abbrevs,clauses,chr=compile_blockkindstypestype_abbrevsclauseschrpred_substty_substbodyincompile_blockkindstypestype_abbrevsclauseschrpred_substty_substrest|Scoped.Accumulated{kinds=k;types=t;type_abbrevs=ta;body;ty_symbols=_}::rest->letkinds=merge_kinds(apply_subst_kindsty_substk)kindsinlettypes=merge_typesTypingEnv.empty(apply_subst_typesty_substt)typesinlettype_abbrevs=merge_type_abbrevstype_abbrevs(apply_subst_type_abbrevsty_substta)inletkinds,types,type_abbrevs,clauses,chr=compile_blockkindstypestype_abbrevsclauseschrty_substpred_substbodyincompile_blockkindstypestype_abbrevsclauseschrty_substpred_substrestletcompile_body{Scoped.kinds;types;type_abbrevs;ty_symbols=_;pred_symbols=_;body}=compile_blockkindstypestype_abbrevs[][]empty_substempty_substbodyletrunstate{Scoped.pbody;toplevel_macros}=letkinds,types,type_abbrevs,clauses_rev,chr_rev=compile_bodypbodyinletsignature={Flat.kinds;types;type_abbrevs;toplevel_macros}in{Flat.clauses=List.(flatten(revclauses_rev));chr=List.revchr_rev;builtins=[];signature}(* TODO builtins can be in a unit *)end(* This is marshalable *)moduleCheck:sigvalcheck:flags:flags->State.t->base:Assembled.program->unchecked_compilation_unit->checked_compilation_unitend=structletcheck_signature~flags(base_signature:Assembled.signature)(signature:Flat.unchecked_signature):Assembled.signature*Assembled.signature*float*TypingEnv.t=let{Assembled.kinds=ok;types=ot;type_abbrevs=ota;toplevel_macros=otlm;ty_names=ots}=base_signatureinlet{Flat.kinds;types;type_abbrevs;toplevel_macros}=signatureinletall_kinds=Flatten.merge_kindsokkindsinletcheck_k_begin=Unix.gettimeofday()inletall_type_abbrevs,type_abbrevs,all_ty_names,ty_names=List.fold_left(fun(all_type_abbrevs,type_abbrevs,all_ty_names,ty_names)(name,scoped_ty)->(* TODO check disjoint from kinds *)letloc=scoped_ty.ScopedTypeExpression.locinlet_,_,{TypingEnv.ty}=Type_checker.check_type~type_abbrevs:all_type_abbrevs~kinds:all_kindsscoped_tyinifF.Map.memnameall_type_abbrevsthenbeginletsk,otherloc=F.Map.findnameall_type_abbrevsinifTypeAssignment.compare_skemaskty<>0thenerror~loc("Duplicate type abbreviation for "^F.showname^". Previous declaration: "^Loc.showotherloc)end;ifF.Map.memnameots&¬(Loc.equal(F.Map.findnameots)loc)thenbeginerror~loc("Illegal type abbreviation for "^F.showname^". A type with the same name already exists in "^Loc.show(F.Map.findnameots))end;F.Map.addname(ty,loc)all_type_abbrevs,F.Map.addname(ty,loc)type_abbrevs,F.Map.addnamelocall_ty_names,F.Map.addnamelocty_names)(ota,F.Map.empty,ots,F.Map.empty)type_abbrevsinletcheck_k_end=Unix.gettimeofday()in(* Type checking *)letcheck_t_begin=Unix.gettimeofday()in(* Type_checker.check_disjoint ~type_abbrevs ~kinds; *)letmergekab=matcha,bwith|_,Some(_,loc)->Someloc|Some_,b->a|_->anomaly("ty_names collision: "^F.showk)inletty_names=F.Map.mergemergety_nameskindsinletall_ty_names=F.Map.mergemergeall_ty_nameskindsinlettypes=Type_checker.check_types~type_abbrevs:all_type_abbrevs~kinds:all_kindstypesinletall_types=Flatten.merge_type_assignmentsottypesinF.Map.iter(funkm->Type_checker.check_macro~kinds:all_kinds~type_abbrevs:all_type_abbrevs~types:all_typeskm)toplevel_macros;letcheck_t_end=Unix.gettimeofday()inletall_toplevel_macros=Flatten.merge_toplevel_macrosall_typesotlmtoplevel_macrosin{Assembled.kinds;types;type_abbrevs;toplevel_macros;ty_names},{Assembled.kinds=all_kinds;types=all_types;type_abbrevs=all_type_abbrevs;toplevel_macros=all_toplevel_macros;ty_names=all_ty_names},(ifflags.time_typecheckingthencheck_t_end-.check_t_begin+.check_k_end-.check_k_beginelse0.0),typesletcheck_and_spill_pred~time~needs_spilling~unknown~type_abbrevs~kinds~typest=letunknown,occur_check=time_thistime(fun()->Type_checker.check_rule~unknown~type_abbrevs~kinds~typest~exp:(Val(PropRelation)))inlett=ifneeds_spillingthenSpilling.main~types~type_abbrevstelsetinunknown,t,occur_checkletis_global~types{ScopedTerm.scope=symb'}symb=matchsymb'with|Scope.Global{resolved_to=x}->beginmatchSymbolResolver.resolved_totypesxwith|Somesymb'->TypingEnv.same_symboltypessymbsymb'|_->falseend|_->falseletrechas_cut~types=function|{ScopedTerm.it=App(b,[])}->is_global~typesbGlobal_symbols.cut|{ScopedTerm.it=App(_,args)}->List.exists(has_cut~types)args|{ScopedTerm.it=Cast(x,_)}->has_cut~typesx|_->falseletcheck_and_spill_chr~flags~det_check_time~time~unknown~type_abbrevs~kinds~typesr=letunknown=time_thistime(fun()->Type_checker.check_chr_rule~unknown~type_abbrevs~kinds~typesr)inifnotflags.skip_det_checkingthentime_thisdet_check_time(fun()->Option.iter(fun{Ast.Chr.conclusion}->Determinacy_checker.check_chr_guard_and_newgoal~type_abbrevs~types~unknown~guard:r.guard~newgoal:conclusion)r.new_goal);ifOption.fold~none:false~some:(funx->has_cut~typesx.Ast.Chr.conclusion)r.new_goalthenerror~loc:r.loc"CHR new goals cannot contain cut";letguard=Option.map(Spilling.main~type_abbrevs~types)r.guardinletnew_goal=Option.map(fun({Ast.Chr.conclusion}asx)->{xwithconclusion=Spilling.main~types~type_abbrevsconclusion})r.new_goalinunknown,{rwithguard;new_goal}letcheck~flagsst~baseu:checked_compilation_unit=letsignature,precomputed_signature,check_sig,new_types=check_signature~flagsbase.Assembled.signatureu.code.Flat.signatureinlet{version;code={Flat.clauses;chr;builtins}}=uinlet{Assembled.kinds;types;type_abbrevs;toplevel_macros}=precomputed_signatureinletu_types=signature.typesinlettype_check_time=ref0.0inletdet_check_time=ref0.0inletbuiltins=List.map(fun(BuiltInPredicate.Pred(name,_,_)asp)->letsymb=matchTypingEnv.resolve_name(F.from_stringname)new_typeswith|Singles->s|Overloaded(s1::s2::_)->error~loc:(Symbol.get_locs2)(Format.asprintf"Multiple signatures for builtin %s\nOther signature: %a"nameSymbol.pps1);|Overloaded_->assertfalse|exceptionNot_found->error(Format.asprintf"No signature declared for builtin %s"name)inlet{TypingEnv.indexing;availability}=TypingEnv.resolve_symbolsymbnew_typesinbeginmatchavailabilitywith|Ast.Structured.OCaml_->()|_->anomaly~loc:(Symbol.get_locsymb)(Format.asprintf"External predicate with no signature %s"name)end;symb,p)builtinsinlettypes,u_types=List.fold_left(fun(t,ut)(s,_)->TypingEnv.set_as_implemented_in_ocamlts,TypingEnv.set_as_implemented_in_ocamluts)(types,u_types)builtinsinTypingEnv.iter_names(funk->function|TypeAssignment.Single_->()|Overloadedl->letl=List.filter(funx->TypingEnv.(resolve_symbolxu_types).availability<>Elpi)linletl=List.filter(funx->matchSymbol.get_provenancexwith|Core|File_->false|Builtin_->true)linifTypingEnv.undupu_typesl|>List.length<>List.lengthlthenerror("Overloaded external symbol "^F.showk^" must be assigned different ids.\nDid you use the external symbol ... = \"id\". syntax?"))u_types;(* returns unkown types + spilled clauses *)letunknown,clauses=List.fold_left(fun(unknown,clauses)({Ast.Clause.body;loc;needs_spilling;attributes=({Ast.Structured.typecheck;occur_check}asatts)}asclause)->letunknown,body,occur_check_pred=iftypecheckthencheck_and_spill_pred~time:type_check_time~needs_spilling~unknown~type_abbrevs~kinds~typesbodyelseunknown,body,truein(* Format.eprintf "The checked clause is %a@." ScopedTerm.pp body; *)letspilled={clausewithbody;needs_spilling=false;attributes={attswithoccur_check=occur_check&&occur_check_pred}}iniftypecheck&¬flags.skip_det_checkingthentime_thisdet_check_time(fun()->Determinacy_checker.check_clause~types~unknown~type_abbrevsspilled.body);unknown,spilled::clauses)(F.Map.empty,[])clausesinletclauses=List.revclausesinletunknown,chr=List.fold_left(fun(unknown,chr_blocks){Ast.Structured.clique;ctx_filter;rules;loc}->letclique=List.map(Type_checker.check_pred_name~types~loc)cliqueinletctx_filter=List.map(Type_checker.check_pred_name~types~loc)ctx_filterinletunknown,rules=map_acc(fununknown->check_and_spill_chr~flags~det_check_time~time:type_check_time~unknown~type_abbrevs~kinds~types)unknownrulesin(unknown,{Ast.Structured.clique;ctx_filter;rules;loc}::chr_blocks))(unknown,[])chrinletchr=List.revchrinTypingEnv.iter_symbols(funk{TypingEnv.indexing;ty}->matchSymbolMap.get_global_symbolbase.Assembled.symbolskwith|Somec->ifBuiltins.is_declaredbase.Assembled.builtinscthenerror~loc:(Symbol.get_lock)(Format.asprintf"Ascribing a type to an already registered builtin %s"(Symbol.get_strk))|_->())new_types;letmore_types=time_thistype_check_time(fun()->Type_checker.check_undeclared~unknown~type_abbrevs)inletu_types=Flatten.merge_type_assignmentsu_typesmore_typesinlettypes=Flatten.merge_type_assignmentstypesmore_typesinletsignature={signaturewithtypes=u_types}inletprecomputed_signature={precomputed_signaturewithtypes}inletchecked_code={CheckedFlat.signature;clauses;chr;builtins}in{version;checked_code;base_hash=hash_basebase;precomputed_signature;type_checking_time=ifflags.time_typecheckingthen!type_check_time+.check_sigelse0.0;det_checking_time=ifflags.time_typecheckingthen!det_check_timeelse0.0;}endlettodoppname_fmt_=error("pp not implemented for field: "^name)letget_argmap,set_argmap,_update_argmap=letargmap=State.declare~name:"elpi:argmap"~pp:(todopp"elpi:argmap")~descriptor:D.elpi_state_descriptor~clause_compilation_is_over:(fun_->F.Map.empty)~compilation_is_over:(fun_->None)~execution_is_over:(fun_->None)~init:(fun()->F.Map.empty)()inState.(getargmap,setargmap,update_returnargmap)moduleAssemble:sigvalextend:flags->State.t->Assembled.program->checked_compilation_unit->State.t*Assembled.programvalextend_signature:State.t->Assembled.program->checked_compilation_unit_signature->State.t*Assembled.program(* for the query *)valcompile_query:State.t->Assembled.program->bool*ScopedTerm.t->SymbolMap.table*intF.Map.t*D.termvalcompile_query_term:State.t->Assembled.program->?ctx:constantScope.Map.t->?amap:constantF.Map.t->depth:int->ScopedTerm.t->constantF.Map.t*D.termend=structletupdate_indexingstatesymbols({idx}asindex)(preds:(Symbol.t*pred_info)list)old_idx=letcheck_if_some_clauses_already_in2~locpredicatec=ifPtmap.memcidxthenerror~loc@@"Some rules for "^predicate^" are already in the program, changing the indexing a posteriori is not allowed."inletadd_indexing_fornamelocc(index:pred_info)map=(* Format.eprintf "indexing for %s with id %a at pos %a\n%!" name pp_int c Loc.pp loc; *)(* Format.eprintf "its indexing is %a@." pp_indexing index; *)tryletold_tindex=tryC.Map.findcmapwithNot_found->C.Map.findcold_idxinifnot@@same_indexingold_tindexindexthenerror("multiple and inconsistent indexing attributes for "^name)(* ". " ^ show_pred_info old_tindex ^ "<> " ^ show_pred_info index)*)elsemapwithNot_found->check_if_some_clauses_already_in2~locnamec;C.Map.addcindexmapinletmap=preds|>List.fold_left(funacc(symb,(indexing:pred_info))->matchSymbolMap.get_global_symbolsymbolssymbwith|None->acc|Somec->add_indexing_for(Symbol.get_strsymb)(Symbol.get_locsymb)cindexingacc)C.Map.emptyinR.CompileTime.update_indexingmapindex,C.Map.union(fun_ab->assert(a=b);Somea)mapold_idxletlookup_globaltypessymbstates=(* Format.eprintf "LOOKUP %a\n" Symbol.pp s; *)matchSymbolMap.get_global_symbol!symbswith|None->(* Format.eprintf " NEW \n"; *)lets,rc=SymbolMap.allocate_global_symbolstate!symbsinsymb:=s;rc|Somec->(* Format.eprintf " FOUND %b\n" (is_builtin_predicate c); *)c,SymbolMap.get_canonicalstate!symbc;;letallocate_global_symboltypessymbstate~locsc=lookup_globaltypessymbstate@@matchSymbolResolver.resolved_totypesswith|Somes->s|None->matchTypingEnv.resolve_namectypeswith|TypeAssignment.Singles->s|TypeAssignment.Overloaded_->error~loc("untyped and non allocated symbol "^F.showc)|exceptionNot_found->error~loc("untyped and non allocated symbol "^F.showc)letrectry_add_tail_cut~types({ScopedTerm.it;loc}asorig)=letopenScopedTerminletopenGlobal_symbolsinletmkGxloc=const_of_symb~typesx~locinletisGs1=functionScope.Global{resolved_to=s}->SymbolResolver.is_resolved_totypesss1|_->falseinletconj({ScopedTerm.it;loc}asorig)=letmkit={it;loc;ty=TypeAssignment.(mkPropFunction)}inApp(mkGand_loc,[orig;mk@@App(mkGcutloc,[])])inletrecappend_list{ScopedTerm.it;loc}=letmkit={it;loc;ty=TypeAssignment.(mkPropFunction)}inletmklit={it;loc;ty=TypeAssignment.(mkList@@PropFunction)}inmatchitwith|App({scope=s},[])whenisGnils->App(mkGconsloc,[mk@@App(mkGcutloc,[]);mkl@@App(mkGnilloc,[])])|App({scope=s}ashd,[x;xs])whenisGconss->App(hd,[x;mk@@append_listxs])|_->raise(Failure"not a list")inletappend_list_or_conjh=tryappend_listhwithFailure_->conjhinletmkit={it;loc;ty=TypeAssignment.(mkPropFunction)}inmatchitwith|Impl(R2L,lb,hd,hyp)->Some(mk@@Impl(R2L,lb,hd,mk@@append_list_or_conjhyp))|App({scope=Scope.Global{resolved_to=s}},[])whenSymbolResolver.is_resolved_totypessnil->Someorig|App({scope=Scope.Global{resolved_to=s}}ashd,[x;xs])whenSymbolResolver.is_resolved_totypesscons->beginmatchtry_add_tail_cut~typesx,try_add_tail_cut~typesxswith|Somex,Somexs->Some(mk@@App(hd,[x;xs]))|_->Noneend|App({scope=Scope.Global{resolved_to=s}}ashd,xs)whenSymbolResolver.is_resolved_totypessand_->letxs=List.map(try_add_tail_cut~types)xsinifList.for_allOption.is_somexsthenSome(mk@@App(hd,List.mapOption.getxs))elseNone|App({scope=Scope.Global{resolved_to=s}}ashd,[{it=Lam(v,ty,t)}aslam])whenSymbolResolver.is_resolved_totypesspi->beginmatchtry_add_tail_cut~typestwith|Somex->Some(mk@@App(hd,[{lamwithit=Lam(v,ty,x)}]))|_->Noneend|App_->Some(mk@@Impl(R2L,loc,orig,mk@@App(const_of_symb~typescut~loc,[])))|_->Noneletto_dbl?(ctx=Scope.Map.empty)~types~builtinsstatesymb?(depth=0)?(amap=F.Map.empty)t=(* Format.eprintf "todbl: term : %a" ScopedTerm.pretty t; *)letsymb=refsymbinletamap=refamapinletallocate_argc=tryF.Map.findc!amapwithNot_found->letn=F.Map.cardinal!amapinamap:=F.Map.addcn!amap;ninletallocate_fresh_arg()=letn=F.Map.cardinal!amapinletc=F.from_string(Printf.sprintf"%%Underscore%d"n)inallocate_argcinletlookup_boundloc(_,ctx)(c,lasx)=tryScope.Map.findxctxwithNot_found->anomaly~loc("Unbound variable "^F.showc^ifl<>elpi_languagethen" (language: "^l^")"else""^" in context "^Scope.Map.(showFormat.pp_print_int)ctx)inletallocate_bound_symbollocctxf=letc=lookup_boundlocctxfinlets,rc=SymbolMap.allocate_bound_symbolstate!symbcinsymb:=s;rcinletallocate_global_symbol=allocate_global_symboltypessymbstateinletpush_bound(n,ctx)c=(n+1,Scope.Map.addcnctx)inletpush_unnamed_bound(n,ctx)=(n+1,ctx)inletpushctx:ScopedTerm.binderoption->'a=function|None->push_unnamed_boundctx|Some{scope=l;name=x}->push_boundctx(x,l)inletopenScopedTerminletrectodbl(ctx:int*_Scope.Map.t)t=matcht.itwith|Impl(b,_,t1,t2)->lett1,(b:builtin_predicate)=matchbwith|L2R->t1,Impl|R2L->t1,RImpl|L2RBang->matchtry_add_tail_cut~typest1with|Somet1->t1,Impl|None->t1,ImplBanginD.mkBuiltinb[todblctxt1;todblctxt2]|CDatac->D.mkCData(CData.hconsc)|Spill(t,_)->error~loc:t.loc(Format.asprintf"todbl: term contains spill: %a"ScopedTerm.prettyt)|Cast(t,_)->todblctxt(* lists *)|App({scope=Global_;name=c},[])whenF.(equalcnilf)->D.mkNil|App({scope=Global_;name=c},[x;y])whenF.(equalcconsf)->letx=todblctxxinlety=todblctxyinD.mkConsxy(* globals and builtins *)|App({scope=Global{resolved_to};name=c},[])->letc,t=allocate_global_symbol~loc:t.locresolved_tocinifis_builtin_predicatecthenD.mkBuiltin(builtin_predicate_of_constc)[]elseifBuiltins.is_declaredbuiltinscthenD.mkBuiltin(Hostc)[]elset|App({scope=Global{resolved_to};name=c},x::xs)->letc,_=allocate_global_symbol~loc:t.locresolved_tocinletx=todblctxxinletxs=List.map(todblctx)xsinifis_builtin_predicatecthenD.mkBuiltin(builtin_predicate_of_constc)(x::xs)elseifBuiltins.is_declaredbuiltinscthenD.mkBuiltin(Hostc)(x::xs)elseD.mkAppcxxs(* lambda terms *)|App({scope=Boundl;name=c},[])->allocate_bound_symbolt.locctx(c,l)|Lam(c,_,t)->D.mkLam@@todbl(pushctxc)t|App({scope=Boundl;name=c},x::xs)->letc=lookup_boundt.locctx(c,l)inletx=todblctxxinletxs=List.map(todblctx)xsinD.mkAppcxxs(* holes *)|UVar({name=c},xs)->letxs=List.map(todblctx)xsinR.mkAppArg(allocate_argc)0xs|Discard{heapify=false}->D.mkDiscard|Discard{heapify=true}->letxs=Scope.Map.bindings(sndctx)|>List.map(fun(k,_)->allocate_bound_symbolt.locctxk)inR.mkAppArg(allocate_fresh_arg())0xsinlett=todbl(depth,ctx)tin(!symb,!amap),tletcheck_mut_exclstatesymbols~locpred_infoclcl_st(oc:overlap_clauseoption)pamap:pred_infoC.Map.t=letpp_global_predicatefmtp=letf=SymbolMap.global_namestatesymbolspinFormat.fprintffmt"predicate %a"F.ppfinletpreds_w_eigen_var_no_cut=refC.Map.emptyinletadd_pred_w_eigen_var_no_cutpredloc=preds_w_eigen_var_no_cut:=C.Map.addpredloc!preds_w_eigen_var_no_cutinletget_fresh_loc=letn=ref0infunloc->incrn;Loc.extend!nlocinletruntime_tick=lettick=ref0infun()->decrtick;!tickinletget_optx=Constants.Map.find_optxpred_infoinletcan_overlapx=matchget_optxwith|Some{overlap=Allowed}->true|Some{overlap=Forbidden_}->false|_->trueinletget_infox=matchget_optxwith|Some{mode;overlap}->letindexed_args=matchoverlapwith|Forbiddend->Discrimination_tree.user_upper_bound_depthd|Allowed->[]inmode,indexed_args|None->[],[]inletget_overlapping(_,pred_info)cquery=matchpred_infowith|{overlap=Allowed}->[]|{overlap=Forbiddendt}->(* Format.eprintf "@[<hov 2>Getting clause for@ %a with query@ %a@]@." pp_global_predicate c pp_term query; *)R.CompileTime.get_clauses~depth:0querydt|>Bl.to_listinletrecto_heap~deptht=matchtwith|Builtin(x,xs)->Builtin(x,List.map(to_heap~depth)xs)|App(h,x,xs)->App(h,(to_heap~depth)x,List.map(to_heap~depth)xs)|Constx->t|Lamt->Lam((to_heap~depth)t)|(Nil|CData_|Discard|AppUVar_|UVar_)->t|Arg_->UVar(R.CompileTime.fresh_uvar~depth,0)|AppArg(_,args)->AppUVar(R.CompileTime.fresh_uvar~depth,List.map(to_heap~depth)args)|Cons(a,b)->Cons((to_heap~depth)a,(to_heap~depth)b)inletpretty_term~depth=letpp_ctx=({uv_names=ref(IntMap.empty,0);table=SymbolMap.compilesymbols})inR.Pp.uppterm~pp_ctxdepth[]~argsdepth:0[||]inleterror_overlapping~loc~is_localpredoverlaps(cl_st,depth:term*int)=letlocal=ifis_localthen"local "else""inletto_strfmtx=matchx.overlap_locwith|None->Format.fprintffmt"- anonymous rule"|Someloc2whenLoc.equallocloc2->Format.fprintffmt"- @[<v 0>itself at %a@,did you accumulate %s twice?@]"Loc.pploc2(Filename.basenameloc2.Loc.source_name)|Someloc2->Format.fprintffmt"- rule at %a"Loc.pploc2inerror~loc(Format.asprintf"@[<v 0>Mutual exclusion violated for rules of %a.@,@[Offending rule is:@ @[<hov 2>%a@]@]@,This %srule overlaps with:@ %a@]@ @[This may break the determinacy of the predicate. To solve the problem, add a cut in its body.@]@ @]"pp_global_predicatepred(pretty_term~depth)cl_stlocal(pplistto_str" ")overlaps)inleterror_overlapping_eigen_variables~locpred(cl_st,depth:term*int)=error~loc(Format.asprintf"@[<v 0>Mutual exclusion violated for rules of %a.@,This rule (displayed below) does not respects the principles of mutual exclution@]@ @[Principles: there is a cut in the body of the local rule and/or all indexed input arguments are eigenvariables@] @[To solve the problem, add a cut in its body.@]@ @[Offending rule:@ @[<hov 2>%a@]@] @]"pp_global_predicatepred(pretty_term~depth)cl_st)in(* check if the term has a rigid occurence of a bound variable *)(*
(* We prefere to use a simpler version of has_rigid_occurrence which is
there is the function is_eigen_variable below: that is, the term is
exactly a name. This is to simplify the check when a catchall is loaded *)
let has_rigid_occurence ~depth (t:term) =
(* Format.eprintf "Computing has rigid of %a from depth %d@." pp_term t depth; *)
let rec aux = function
| Const b -> 0 <= b && b < depth
| Builtin (Impl, [l; r]) -> aux l || aux r
| Builtin (ImplBang, [l; r]) -> aux l || aux r
| Builtin (Cut, _) -> false
| Builtin ((Pi|Sigma), l)
| Builtin ((And|RImpl|Eq|Match|Findall), l)
| Builtin ((Delay|Host _), l) -> List.exists aux l
| Cons (l, r) -> aux l || aux r
| Nil | UVar (_, _, _) | AppUVar (_, _, _) | Arg (_, _) | AppArg (_, _) -> false
| Builtin (Impl, _) -> assert false
| Builtin (ImplBang, _) -> assert false
| App (b, hd, tl) -> b < 0 || aux hd || List.exists aux tl
| Lam b -> aux b
| Discard | CData _ -> false in
let b = aux t in
(* Format.eprintf "Bool is %b@." b; *)
b
in *)letis_eigen_variable~min_depth~depth=function|Constb->min_depth<=b&&b<depth|_->falseinletrecis_unif_var=function|AppUVar_|UVar(_,_)|Discard|Arg(_,_)|AppArg(_,_)->true|App(h,x,xs)whenh==Global_symbols.asc->is_unif_varx&&List.for_allis_unif_varxs|Nil|Const_|Lam_|App(_,_,_)|Cons(_,_)|Builtin(_,_)|CData_->falsein(* Builds a query for the predicate p with args args *)(* returns
- if all the input terms are eigen_variables (or if the predicate has no inputs)
- if all the input terms are unification variables
- the query
*)lethd_query~loc~depth~min_depthpargs=letmode,indexed_args=get_infopin(* all inputs are exactely an eigen_variable *)letrig_occ=reftrueinlethas_input=reffalseinletis_catchall=reftrueinletupdate_boolsmt=has_input:=!has_input||m;rig_occ:=!rig_occ&&(is_eigen_variable~min_depth~deptht);is_catchall:=!is_catchall&&is_unif_vartinletremove_as=function|App(c,a,_)whenc==Global_symbols.asc->a|x->xinletrecmkpatsindexed_argsargsmode=matchindexed_args,args,modewith|_,[],[]->[]|i::is,a::args,(Mode.FoInput|Ho(Input,_))::modewheni>0->update_boolstruea;remove_asa::mkpatsisargsmode|(([]asis)|(_::is)),_::args,_::mode->mkDiscard::mkpatsisargsmode|(([]asis)|(_::is)),_::args,[]->mkDiscard::mkpatsisargsmode|_->assertfalsein(not!has_input||!rig_occ),(not!has_input||!is_catchall),R.mkAppLp@@mkpatsindexed_argsargsmodein(* Returns if the clause has a bang *)letcheck_overlaps~is_local~loc~min_depth~depth(cl:clause)h(cl_overlap:overlap_clauseoption)pargs(index:int*pred_info)=matchcl_overlapwith|None->()|Somecl_overlap->letrecfilter_overlaps(arg_nb:int)has_cut:overlap_clauselist->'alist=function|[]->[]|x::xswhenx.timestamp=cl.timestamp->ifx.has_cutthen[]elsefilter_overlapsarg_nbhas_cutxs|x::xs->ifnotx.has_cut&&arg_nb=x.arg_nbthen(x::filter_overlapsarg_nbhas_cutxs)elsefilter_overlapsarg_nbhas_cutxsinletall_input_eigen_vars,all_input_catchall,hd=hd_query~loc~min_depth~depthpargsin(* Format.eprintf "Is_local:%b -- Has bang? %b -- rig_occ:%b -- is_chatchall:%b@." is_local cl_overlap.has_cut has_input_w_eigen_var is_catchall; *)ifis_local&¬cl_overlap.has_cut&¬all_input_eigen_varsthen(error_overlapping_eigen_variables~locph);ifnotis_local&&all_input_catchallthen(* We check if there is a local clause for p loading a local clause without cut, if this is the case,
we throw an error, the catchall make $p$ non functional *)(matchget_optpwith|None|Some{has_local_without_cut=None}->()|Some{has_local_without_cut=(Some_)asloc1}->error_overlapping~is_local~locp[{overlap_loc=loc1;timestamp=[];has_cut=false;arg_nb=0}]h);ifis_local&¬cl_overlap.has_cut&&all_input_eigen_varsthen(* Here we have a local clause with all input vars being eigenvars + the has no cut in the body, we add the info to the pred *)add_pred_w_eigen_var_no_cutploc;ifnotis_local||(is_local&¬cl_overlap.has_cut)thenletall_overlapping=get_overlappingindexphdinletoverlapping=filter_overlapscl_overlap.arg_nbcl_overlap.has_cutall_overlappinginifoverlapping<>[]thenerror_overlapping~loc~is_localpoverlappinghin(* Inspect the a local premise. If a local clause is found
it is added to the index and it check_clause is launched on it
*)letreccheck_local~min_depth~depth~loc~lcsindexamap(t:term):unit=lett=to_heap~depthtin(* let t = R.hmove ~from:depth ~to_:(depth+lcs) t in *)letrecaux~min_depth~depth(index:pred_infoC.Map.t)t=matchtwith|Builtin(Cut,[])->()|Builtin(Pi,[Lamb])->aux~min_depth~depth:(depth+1)indexb|Builtin(Sigma,[Lamb])->letuvar=UVar(R.CompileTime.fresh_uvar~depth,0)inletb=Runtime.subst~depth[uvar]binaux~min_depth~depth:(depth+1)indexb|Builtin((Impl|ImplBang),[Nil;l])|Builtin((Impl|ImplBang),[Builtin(And,[]);l])->aux~min_depth~depthindexl|Builtin((Impl|ImplBangasik),[Cons(h,hl);l])->aux~min_depth~depthindex(Builtin(ik,[h;Builtin(ik,[hl;l])]))|Builtin((Impl|ImplBangasik),[Builtin(And,h::hl);l])->aux~min_depth~depthindex(Builtin(ik,[h;Builtin(ik,[Builtin(And,hl);l])]))|Builtin((Impl|ImplBangasik),[h;l])->(* Format.eprintf "Adding local clause %a@." pp_term h; *)begintryletfresh_loc=get_fresh_loclocinlet(p,cl),_,morelcs=tryR.CompileTime.clausify1~tail_cut:(ik=ImplBang)~loc:fresh_loc~modes:(funx->fst(get_infox))~nargs:(F.Map.cardinalamap)~depthhwithD.CannotDeclareClauseForBuiltin(loc,c)->error?loc("Declaring a rule for built predicate:"^show_builtin_predicate(fun?tablex->F.show@@SymbolMap.global_namestatesymbolsx)c)inletcl_overlap,index=R.Indexing.add1clause_overlap_runtime~depth~time:(runtime_tick())indexpclincheck_clause~min_depth~is_local:true~depth~loc:fresh_loc~lcs:morelcsindexclhcl_overlappamap;aux~min_depth~depthindexlwith|CompileError_ase->raisee|Flex_head->aux~min_depth~depthindexlend|Builtin(And,l)->List.iter(aux~min_depth~depthindex)l|_->()(* TODO: missing cases *)inaux~min_depth~depthindextandcheck_clause~min_depth~is_local~depth~loc~lcsindexclhcl_overlappamap=ifnot@@can_overlappthencheck_overlaps~is_local~loc~min_depth~depthcl(h,depth)cl_overlappcl.args(0,C.Map.findpindex);List.iter(check_local~min_depth:depth~loc~depth~lcsindexamap)cl.hypsin(* state symbols ~loc pred_info cl body overlap_clause p amap *)check_clause~min_depth:0~loc~is_local:false~lcs:0~depth:0pred_infoclcl_stocpamap;letpred_info=C.Map.fold(funkv->C.Map.addk{(C.Map.findkpred_info)withhas_local_without_cut=Somev})!preds_w_eigen_var_no_cutpred_infoinpred_info(* Format.eprintf "The predicates with local clauses bla is :@ @[%a@]@." (C.Map.pp (Loc.pp)) !preds_w_eigen_var_no_cut *)letspill_todbl?(ctx=Scope.Map.empty)~builtins~needs_spilling~type_abbrevs~typesstatesymb?(depth=0)?(amap=F.Map.empty)t=lett=ifneeds_spillingthenSpilling.main~types~type_abbrevstelsetinto_dbl~ctx~builtinsstatesymb~types~depth~amaptletextend1_clause~timeflagsstate~builtins~types(clauses,symbols,index,pred_info){Ast.Clause.body=body_st;loc;needs_spilling;attributes={Ast.Structured.insertion=graft;id;ifexpr;occur_check}}=assert(notneeds_spilling);ifnot@@filter1_ifflags(funx->x)ifexprthen(clauses,symbols,index,pred_info)elselet(symbols,amap),body=to_dbl~builtins~typesstatesymbolsbody_stinletmodesx=(Constants.Map.find_optxpred_info)|>Option.fold~some:(fun(x:pred_info)->x.mode)~none:[]inlet(p,cl),_,morelcs=tryR.CompileTime.clausify1~tail_cut:false~loc~modes~nargs:(F.Map.cardinalamap)~depth:0bodywithD.CannotDeclareClauseForBuiltin(loc,_c)->error?loc("Declaring a rule for built in predicate")inifmorelcs<>0thenerror~loc"sigma in a toplevel rule is not supported";letcl=ifoccur_checkthenclelse{clwithoc=false}inletp_info=tryC.Map.findppred_infowithNot_found->anomaly("No signature declaration for "^F.show(SymbolMap.global_namestatesymbolsp)^". Did you forget to accumulate a file?")inletindex,(overlap_clause,p_info)=R.CompileTime.add_to_index~det_check:(ifflags.skip_det_checkingthenNoneelseSometime)~depth:0~predicate:p~graftclidindexp_infoinletpred_info=C.Map.addpp_infopred_infoin(* Format.eprintf "Validating clause for predicate %a at %a@." F.pp (SymbolMap.global_name state symbols p) Loc.pp loc; *)letpred_info=refpred_infoinifnotflags.skip_det_checkingthentime_thistime(fun()->pred_info:=check_mut_exclstatesymbols~loc!pred_infoclbodyoverlap_clausepamap);(graft,id,p,cl)::clauses,symbols,index,!pred_infoletcheck_rule_pattern_in_cliquestatesymbolsclique{D.CHR.pattern;rule_name;rule_loc}=tryletoutside=List.find(funx->not(D.CHR.in_cliquecliquex))patterninerror~loc:rule_loc("CHR rule "^rule_name^": matches "^(F.show@@SymbolMap.global_namestatesymbolsoutside)^" which is not a constraint on which it is applied. Check the list of predicates after the \"constraint\" keyword.");withNot_found->()letextend1_chrflagsstateclique~builtins~types(symbols,chr){Ast.Chr.to_match;to_remove;guard;new_goal;attributes;loc}=ifnot@@filter1_ifflags(funx->x.Ast.Structured.cifexpr)attributesthen(symbols,chr)elselettodblstate(symbols,amap)t=to_dbl~types~builtinsstatesymbols~amaptinletsequent_todblstatest{Ast.Chr.eigen;context;conclusion}=letst,eigen=todblstatesteigeninletst,context=todblstatestcontextinletst,conclusion=todblstatestconclusioninst,{CHR.eigen;context;conclusion}inletst=symbols,F.Map.emptyinletst,to_match=map_acc(sequent_todblstate)stto_matchinletst,to_remove=map_acc(sequent_todblstate)stto_removeinletst,guard=option_mapacc(todblstate)stguardinletst,new_goal=option_mapacc(sequent_todblstate)stnew_goalinletsymbols,amap=stinletkey_of_sequent{CHR.conclusion}=matchconclusionwith|Constx->x|App(x,_,_)->x|_->error~loc"CHR: rule without head symbol"inletall_sequents=to_match@to_removeinletpattern=List.mapkey_of_sequentall_sequentsinletrule_name=attributes.Ast.Structured.cidinletpatsno=List.(lengthto_match+lengthto_remove)inletnargs=F.Map.cardinalamapinletrule={CHR.to_match;nargs;to_remove;guard;new_goal;patsno;pattern;rule_name;rule_loc=loc}incheck_rule_pattern_in_cliquestatesymbolscliquerule;symbols,CHR.add_rulecliquerulechrletextend1_chr_blockflagsstate~builtins~types(symbols,chr){Ast.Structured.clique;ctx_filter;rules;loc}=letallocate_global_symbolstatesymbolsf=letsymbols=refsymbolsinletresolved_to=letr=SymbolResolver.make()inSymbolResolver.resolvetypesrf;rinlet(c,_)=allocate_global_symboltypessymbolsstate~locresolved_to(Symbol.get_funcf)in!symbols,cinletsymbols,clique=map_acc(allocate_global_symbolstate)symbolscliqueinletsymbols,ctx_filter=map_acc(allocate_global_symbolstate)symbolsctx_filterinletchr,clique=CHR.new_clique(SymbolMap.global_namestatesymbols)ctx_filtercliquechrinList.fold_left(extend1_chr~builtins~typesflagsstateclique)(symbols,chr)rulesletextend1_signaturebase_signature(signature:checked_compilation_unit_signature)=let{Assembled.kinds=ok;types=ot;type_abbrevs=ota;toplevel_macros=otlm;ty_names=ots}=base_signatureinlet{Assembled.toplevel_macros;kinds;types;type_abbrevs;ty_names}=signatureinletkinds=Flatten.merge_kindsokkindsinF.Map.iter(funk(_,loc)->ifF.Map.memkots&¬(Loc.equalloc(F.Map.findkots))thenerror~loc("Illegal type abbreviation for "^F.showk^". A type with the same name already exists in "^Loc.show(F.Map.findkots)))type_abbrevs;lettype_abbrevs=Flatten.merge_checked_type_abbrevsotatype_abbrevsinlettypes=Flatten.merge_type_assignmentsottypesinlettoplevel_macros=Flatten.merge_toplevel_macrostypesotlmtoplevel_macrosinletmergekab=ifLoc.equalabthenSomeaelseanomaly("ty_names collision: "^F.showk^"\n"^Loc.showa^"\n"^Loc.showb)inletty_names=F.Map.unionmergeotsty_namesin{Assembled.kinds;types;type_abbrevs;toplevel_macros;ty_names}letnew_symbols_of_types~(base_sig:checked_compilation_unit_signature)new_types=letsymbs=TypingEnv.all_symbolsnew_typesinsymbs|>List.filter_map(fun(symb,m)->ifTypingEnv.mem_symbolbase_sig.typessymbthenNoneelseSomesymb),symbs|>List.filter_map(fun(symb,{TypingEnv.indexing})->matchindexingwithIndexm->Some(symb,m)|_->None)letallocate_new_symbolsstate~symbols~new_defined_symbols=(* THE MISTERY: allocating symbols following their declaration order makes the grundlagen job 30% faster (600M less memory):
time typchk wall mem
with: 14.75 0.53 16.69 2348.4M
wout: 19.61 0.56 21.72 2789.1M
*)letnew_defined_symbols=ifList.lengthnew_defined_symbols>2000thennew_defined_symbols|>List.sort(funs1s2->compare(Symbol.get_locs1).line(Symbol.get_locs2).line)elsenew_defined_symbolsinList.fold_left(funsymbolss->SymbolMap.allocate_global_symbolstatesymbolss|>fst)symbolsnew_defined_symbolsletextend1flags(state,base)unit=letsignature=ifhash_basebase=unit.base_hashthenunit.precomputed_signatureelseextend1_signaturebase.Assembled.signatureunit.checked_code.CheckedFlat.signatureinlet{Assembled.hash;clauses=cl;symbols;prolog_program;indexing;signature=bsig;chr=ochr;builtins=ob;total_type_checking_time;total_det_checking_time}=baseinlet{version;base_hash;checked_code={CheckedFlat.clauses;chr;builtins;signature={types=new_types}};type_checking_time;det_checking_time}=unitin(* Format.eprintf "extend %a\n%!" (F.Map.pp (fun _ _ -> ())) types_indexing; *)letnew_defined_symbols,new_indexable=new_symbols_of_types~base_sig:bsignew_typesinletsymbols=allocate_new_symbolsstate~symbols~new_defined_symbolsinletprolog_program,indexing=update_indexingstatesymbolsprolog_programnew_indexableindexingin(* Format.eprintf "extended\n%!"; *)letsymbols,builtins=List.fold_left(fun(symbols,builtins)(symb,p)->letsymbols,(c,_)=SymbolMap.allocate_global_symbolstatesymbolssymbinletbuiltins=Builtins.registerbuiltinspcinsymbols,builtins)(symbols,ob)builtinsinletsymbols,chr=List.fold_left(extend1_chr_block~builtins~types:signature.typesflagsstate)(symbols,ochr)chrinletmutexcl_time=ref0.0inletclauses,symbols,prolog_program,indexing=(* TODO: pass also typeabbrevs *)List.fold_left(extend1_clause~time:mutexcl_time~builtins~types:signature.typesflagsstate)(cl,symbols,prolog_program,indexing)clausesin(* Printf.eprintf "kinds: %d\n%!" (F.Map.cardinal kinds); *)letmutexcl_time=ifflags.time_typecheckingthen!mutexcl_timeelse0.0inlettotal_type_checking_time=total_type_checking_time+.type_checking_timeinlettotal_det_checking_time=total_det_checking_time+.det_checking_time+.mutexcl_timeinletbase={Assembled.builtins;hash;symbols;chr;clauses;prolog_program;signature;indexing;total_type_checking_time;total_det_checking_time}inlethash=hash_basebaseinstate,{basewithhash}letextendflagsstateassembledu=extend1flags(state,assembled)uletextend_signaturestateassembledu=letsignature=extend1_signatureassembled.Assembled.signatureuinletbase_sig=assembled.Assembled.signatureinletnew_defined_symbols,new_indexable=new_symbols_of_types~base_sigsignature.typesinletsymbols=allocate_new_symbolsstate~symbols:assembled.symbols~new_defined_symbolsinletprolog_program,indexing=update_indexingstatesymbolsassembled.prolog_programnew_indexableassembled.indexinginletbase={assembledwithsymbols;prolog_program;indexing;signature}instate,{basewithhash=hash_basebase}letcompile_querystate{Assembled.symbols;builtins;signature={types;type_abbrevs}}(needs_spilling,t)=let(symbols,amap),t=spill_todbl~builtins~needs_spilling~types~type_abbrevsstatesymbolstinsymbols,amap,tletcompile_query_termstate{Assembled.symbols;builtins;signature={types;type_abbrevs}}?ctx?(amap=F.Map.empty)~deptht=let(symbols',amap),rt=spill_todbl~builtins?ctx~needs_spilling:falsestatesymbols~types~type_abbrevs~depth~amaptinifSymbolMap.equal_globalssymbols'symbolsthenamap,rtelseerror~loc:t.ScopedTerm.loc"cannot allocate new symbols in the query"end(****************************************************************************
API
****************************************************************************)letscopes~toplevel_macrosp:scoped_program=letp=RecoverStructure.runspinletp=Scope_Quotation_Macro.run~toplevel_macrosspin{version="3.4.5";code=p;}(* Compiler passes *)letunit_or_header_of_scopeds~builtins(p:scoped_program):unchecked_compilation_unit=assert("3.4.5"=p.version);letp=Flatten.runsp.codein{version="3.4.5";code={pwithbuiltins};};;letprint_unit{print_units}x=ifprint_unitsthenletb1=Marshal.to_bytesx.code[]inPrintf.eprintf"== UNIT =================\ncode: %dk (%d clauses)\n\n%!"(Bytes.lengthb1/1024)(List.lengthx.code.Flat.clauses);;letassemble_unit~flags~header:(s,base)units:program=lets,p=Assemble.extendflagssbaseunitsins,p;;letheader_of_ast~flags~parser:pstate_descriptorquotation_descriptorhoas_descriptorcalc_descriptorbuiltinsast:header=letstate=D.State.(init(merge_descriptorsD.elpi_state_descriptorstate_descriptor))inletstate=matchhoas_descriptor.D.HoasHooks.extra_goals_postprocessingwith|Somex->D.State.setD.Conversion.extra_goals_postprocessingstatex|None->stateinlet{Compiler_data.QuotationHooks.default_quotation;named_quotations;singlequote_compilation;backtick_compilation}=quotation_descriptorinletstate=D.State.setCustomFunctorCompilation.backtickstatebacktick_compilationinletstate=D.State.setCustomFunctorCompilation.singlequotestatesinglequote_compilationinletstate=D.State.setQuotation.default_quotationstatedefault_quotationinletstate=D.State.setQuotation.named_quotationsstatenamed_quotationsinletstate=leteval_map=List.fold_left(funm(c,{CalcHooks.code})->Constants.Map.addccodem)Constants.Map.empty(List.revcalc_descriptor)inD.State.setCalcHooks.evalstateeval_mapinletstate=D.State.setparserstate(Somep)inletstate=D.State.setD.while_compilingstatetruein(* let state = State.set Symbols.table state (Symbols.global_table ()) in *)letbuiltins=List.flatten@@List.map(fun(_,decl)->decl|>List.filter_map(function|Data.BuiltInPredicate.MLCode(p,_)->Somep|_->None))builtinsinletscoped_ast=scope~toplevel_macros:F.Map.emptystateastinletu=unit_or_header_of_scopedstate~builtinsscoped_astinprint_unitflagsu;letbase=Assembled.empty()inletu=Check.check~flagsstate~baseuin(* with toplevel_macros = u.checked_code.signature.toplevel_macros } in *)(* Printf.eprintf "header_of_ast: types u %d\n%!" (F.Map.cardinal u.checked_code.CheckedFlat.signature.types); *)leth=assemble_unit~flags~header:(state,base)uin(* Printf.eprintf "header_of_ast: types h %d\n%!" (F.Map.cardinal (snd h).Assembled.signature.types); *)hletcheck_unit~flags~base:(st,base)u=Check.check~flagsst~baseuletempty_base~header:b=bletscoped_of_ast~flags:_~header:(s,u)p=scope~toplevel_macros:u.Assembled.signature.toplevel_macrosspletunit_of_scoped~flags~header:(s,u)?(builtins=[])p:unchecked_compilation_unit=letbuiltins=List.flatten@@List.map(fun(_,decl)->decl|>List.filter_map(function|Data.BuiltInPredicate.MLCode(p,_)->Somep|_->error"Only BuiltInPredicate.MLCode allowed in units"))builtinsinletu=unit_or_header_of_scopeds~builtinspinprint_unitflagsu;uletappend_unit~flags~base:(s,p)unit:program=Assemble.extendflagsspunitletappend_unit_signature~flags~base:(s,p)unit:program=Assemble.extend_signaturespunitletprogram_of_ast~flags~header:((st,base)asheader:State.t*Assembled.program)p:program=letp=scoped_of_ast~flags~headerpinletu=unit_of_scoped~flags~headerpinletu=Check.check~flagsst~baseuinassemble_unit~flags~headerulettotal_type_checking_time{WithMain.total_type_checking_time=x}=xlettotal_det_checking_time{WithMain.total_det_checking_time=x}=xletpp_uvar_bodyfmtub=R.Pp.uppterm0[]~argsdepth:0[||]fmt(D.mkUVarub0)letpp_uvar_body_rawfmtub=R.Pp.ppterm0[]~argsdepth:0[||]fmt(D.mkUVarub0)letuvk=D.State.declare~descriptor:D.elpi_state_descriptor~name:"elpi:uvk"~pp:(Util.StrMap.pppp_uvar_body)~clause_compilation_is_over:(funx->Util.StrMap.empty)~compilation_is_over:(funx->Somex)~execution_is_over:(fun_->None)~init:(fun()->Util.StrMap.empty)()letcompile_builtinsb=letbuiltins=Hashtbl.create17inlet()=Builtins.fold(funcp()->Hashtbl.addbuiltinscp)b()inbuiltinsletquery_of_ast(compiler_state,assembled_program)tstate_update=letcompiler_state=State.begin_goal_compilationcompiler_stateinlet{Assembled.signature={kinds;types;type_abbrevs;toplevel_macros;};chr;prolog_program;total_type_checking_time}=assembled_programinlettotal_type_checking_time=assembled_program.Assembled.total_type_checking_timeinlettotal_det_checking_time=assembled_program.Assembled.total_det_checking_timeinletneeds_spilling=reffalseinlett=Scope_Quotation_Macro.scope_loc_term~state:(set_mtmcompiler_state{empty_mtmwithmacros=toplevel_macros;needs_spilling})tinletunknown=Type_checker.check_query~unknown:F.Map.empty~type_abbrevs~kinds~typest~exp:TypeAssignment.(Val(PropRelation))inlet_:TypingEnv.t=Type_checker.check_undeclared~unknown~type_abbrevsinletsymbols,amap,query=Assemble.compile_querycompiler_stateassembled_program(!needs_spilling,t)inletquery_env=Array.make(F.Map.cardinalamap)D.dummyinletinitial_goal=R.move~argsdepth:0~from:0~to_:0query_envqueryinletassignments=F.Map.fold(funkim->StrMap.add(F.showk)query_env.(i)m)amapStrMap.emptyinletassignments=StrMap.fold(funkim->StrMap.addk(UVar(i,0))m)(State.getuvkcompiler_state)assignmentsinletbuiltins=assembled_program.Assembled.builtinsin{WithMain.prolog_program;chr;symbols;initial_goal;assignments;compiler_state=compiler_state|>state_update;total_type_checking_time;total_det_checking_time;builtins;runtime_types=Type_checker.compile_for_runtimetypes;}letcompile_term_to_raw_term?(check=true)state(_,assembled_program)?ctx~deptht=ifnot@@State.getData.while_compilingstatethenanomaly"compile_term_to_raw_term called at run time";let{Assembled.signature={kinds;types;type_abbrevs};chr;prolog_program;total_type_checking_time}=assembled_programinifcheck&&Option.fold~none:true~some:Scope.Map.is_emptyctxthenbeginletunknown=Type_checker.check_query~unknown:F.Map.empty~type_abbrevs~kinds~typest~exp:(Type_checker.unknown_type_assignment"Ty")inlet_:TypingEnv.t=Type_checker.check_undeclared~unknown~type_abbrevsin()end;letamap=get_argmapstateinletamap,t=Assemble.compile_query_term?ctx~amapstateassembled_program~depthtinset_argmapstateamap,tletruntime_hack_term_to_raw_termstate(_,assembled_program)?ctx~deptht=ifState.getData.while_compilingstatethenanomaly"runtime_hack_term_to_raw_term called at compile time";letamap,t=Assemble.compile_query_term?ctxstateassembled_program~depthtinifF.Map.is_emptyamapthentelseletquery_env=Array.make(F.Map.cardinalamap)D.dummyinR.move~argsdepth:depth~from:depth~to_:depthquery_envtletquery_of_scoped_term(compiler_state,assembled_program)f=letcompiler_state=State.begin_goal_compilationcompiler_stateinlet{Assembled.signature={kinds;types;type_abbrevs};chr;prolog_program;total_type_checking_time}=assembled_programinlettotal_type_checking_time=assembled_program.Assembled.total_type_checking_timeinlettotal_det_checking_time=assembled_program.Assembled.total_det_checking_timeinletcompiler_state,t=fcompiler_stateinletunknown=Type_checker.check_query~unknown:F.Map.empty~type_abbrevs~kinds~typest~exp:TypeAssignment.(Val(PropRelation))inlet_:TypingEnv.t=Type_checker.check_undeclared~unknown~type_abbrevsinletsymbols,amap,query=Assemble.compile_querycompiler_stateassembled_program(false,t)inletquery_env=Array.make(F.Map.cardinalamap)D.dummyinletinitial_goal=R.move~argsdepth:0~from:0~to_:0query_envqueryinletassignments=F.Map.fold(funkim->StrMap.add(F.showk)query_env.(i)m)amapStrMap.emptyinletassignments=StrMap.fold(funkim->StrMap.addk(UVar(i,0))m)(State.getuvkcompiler_state)assignmentsinletbuiltins=assembled_program.Assembled.builtinsin{WithMain.prolog_program;chr;symbols;initial_goal;assignments;compiler_state;total_type_checking_time;total_det_checking_time;builtins;runtime_types=Type_checker.compile_for_runtimetypes;}letquery_of_raw_term(compiler_state,assembled_program)f=letcompiler_state=State.begin_goal_compilationcompiler_stateinlet{Assembled.signature={kinds;types;type_abbrevs};chr;prolog_program;total_type_checking_time}=assembled_programinlettotal_type_checking_time=assembled_program.Assembled.total_type_checking_timeinlettotal_det_checking_time=assembled_program.Assembled.total_det_checking_timeinletcompiler_state,query,gls=fcompiler_stateinletcompiler_state,gls=Data.State.getData.Conversion.extra_goals_postprocessingcompiler_stateglscompiler_stateinletgls=List.mapData.Conversion.term_of_extra_goalglsinletquery=matchgls@[query]with|[]->assertfalse|[g]->g|x::xs->mkBuiltinAnd(x::xs)inletamap=get_argmapcompiler_stateinletquery_env=Array.make(F.Map.cardinalamap)D.dummyinletinitial_goal=R.move~argsdepth:0~from:0~to_:0query_envqueryinletassignments=F.Map.fold(funkim->StrMap.add(F.showk)query_env.(i)m)amapStrMap.emptyinletassignments=StrMap.fold(funkim->StrMap.addk(UVar(i,0))m)(State.getuvkcompiler_state)assignmentsinletbuiltins=assembled_program.Assembled.builtinsin{WithMain.prolog_program;chr;symbols=assembled_program.Assembled.symbols;initial_goal;assignments;compiler_state;total_type_checking_time;total_det_checking_time;builtins;runtime_types=Type_checker.compile_for_runtimetypes;}letsymtab:((constant*D.term)Symbol.RawMap.t*Type_checker.runtime_types)D.State.component=D.State.declare~descriptor:D.elpi_state_descriptor~name:"elpi:symbol_table"~pp:(funfmt_->Format.fprintffmt"<symbol_table>")~clause_compilation_is_over:(funx->x)~compilation_is_over:(funx->Somex)~execution_is_over:(fun_->None)~init:(fun()->Symbol.RawMap.empty,Type_checker.empty_runtime_types)()letglobal_name_to_constantstates=letsymbols2c,str2symbol=State.getsymtabstateinmatchType_checker.runtime_resolvestr2symbol(F.from_strings)with|s->fst@@Symbol.RawMap.findssymbols2c|exceptionNot_found->error(Format.asprintf"cannot resolve overloaded symbol (%s) at runtime"s)moduleCompiler:sigvalrun:query->executableend=struct(* {{{ *)letrun{WithMain.prolog_program;chr;symbols;initial_goal;assignments;builtins;runtime_types;compiler_state=state;}=letsymbol_table=SymbolMap.compilesymbolsinletstate=State.setsymtabstate(SymbolMap.compile_s2csymbols,runtime_types)in{D.compiled_program={index=close_indexprolog_program;src=[]};chr;initial_depth=0;initial_goal;initial_runtime_state=State.end_compilationstate;assignments;symbol_table;builtins=compile_builtinsbuiltins;}end(* }}} *)letoptimize_query=Compiler.runletremovalsl=List.filter_map(function|(Some(Ast.Structured.Removex),_,_,_)->Somex|(Some(Ast.Structured.Replacex),_,_,_)->Somex|_->None)llethandle_clause_graftin(clauses:(Ast.Structured.insertionoption*stringoption*constant*clause)list):(stringoption*constant*clause)list=letclauses=clauses|>List.sort(fun(_,_,_,c1)(_,_,_,c2)->R.lex_insertionc1.timestampc2.timestamp)inletremovals=removalsclausesinletclauses=clauses|>List.filter(fun(_,id,_,_)->id=None||not(List.exists(funx->id=Somex)removals))inletclauses=clauses|>List.filter(fun(c,_,_,_)->matchcwithSome(Ast.Structured.Remove_)->false|_->true)inList.map(fun(_,a,b,c)->a,b,c)clausesletpp_program(pp:pp_ctx:pp_ctx->depth:int->_)fmt(compiler_state,{Assembled.clauses;signature;symbols})=letclauses=handle_clause_graftinclausesinletpp_ctx={uv_names=ref(IntMap.empty,0);table=SymbolMap.compilesymbols;}inFormat.fprintffmt"@[<v>";F.Map.iter(funname(ty,_)->letreca2k=function|0->"type"|n->"type -> "^a2k(n-1)inFormat.fprintffmt"@[<h>kind %s %s.@]@,"(F.showname)(a2kty))signature.kinds;TypingEnv.iter_names(funnamesl->letfs=TypeAssignment.fresh(TypingEnv.resolve_symbolssignature.types).ty|>fstinlettys=matchslwith|TypeAssignment.Singlet->[ft]|TypeAssignment.Overloadedl->List.mapflinletname=matchElpi_parser.Parser_config.precedence_of(F.showname)with|(Some_,_)->"("^F.showname^")"|_->F.shownameinList.iter(funty->Format.fprintffmt"@[<h>type %s %a.@]@,"nameTypeAssignment.pretty_mut_oncety)tys;)signature.types;F.Map.iter(funname(ty,_)->Format.fprintffmt"@[<h>typeabbrv %a (%a).@]@,"F.ppnameTypeAssignment.pretty_mut_once(fst@@TypeAssignment.freshty))signature.type_abbrevs;List.iter(fun(name,predicate,{depth;args;hyps;loc;timestamp})->Format.fprintffmt"@[<h>%% %a [%a] %a@]@;"Format.(pp_print_optionLoc.pp)locFormat.(pp_print_list~pp_sep:(funfmt()->pp_print_stringfmt"; ")pp_print_int)timestampFormat.(pp_print_optionpp_print_string)name;Fmt.fprintffmt"@[<hov 1>%a :- %a.@]@;"(pp~depth~pp_ctx)(ifargs=[]thenD.ConstpredicateelseD.mkApppredicate(List.hdargs)(List.tlargs))(pplist(pp~depth~pp_ctx)", ")hyps)clauses;Format.fprintffmt"@]";;letpp_goalppfmt{WithMain.compiler_state;initial_goal;symbols}=letpp_ctx={uv_names=ref(IntMap.empty,0);table=SymbolMap.compilesymbols;}inFormat.fprintffmt"@[<v>";Format.fprintffmt"%a.@;"(pp~pp_ctx~depth:0)initial_goal;Format.fprintffmt"@]";;letelpi~language:_statelocs=letmoduleP=(valoption_get~err:"No parser"(State.getparserstate))inletast=P.goal~loc~text:sinletterm=Scope_Quotation_Macro.scope_loc_term~stateastin{ScopedTerm.SimpleTerm.it=Opaque(ScopedTerm.in_scoped_termterm);loc=term.loc}exceptionRelocationErrorofstringletrelocate_closed_term~from:symbol_table~to_:(_,{Assembled.symbols;signature})(t:term):term=letrelocatec=lets=Util.Constants.Map.findcsymbol_table.c2sinletf=s|>Symbol.get_funcinletget_variants=matchSymbol.get_provenanceswith|Builtin{variant}->Somevariant|_->Noneinletc=matchTypingEnv.resolve_namefsignature.typeswith|(Singles)->SymbolMap.get_global_symbolsymbolss|(Overloadedl)->beginmatchList.filter(funx->get_variants=get_variantx)lwith|[]->None|[x]->SymbolMap.get_global_symbolsymbolsx|x1::x2::_->anomaly("Cannot relocate overloaded symbol "^F.showf^"\nDeclarations:\n - "^Loc.show(Symbol.get_locx1)^"\n - "^Loc.show(Symbol.get_locx2))end|exceptionNot_found->Noneinmatchcwith|Somex->x|None->raise(RelocationError(Format.asprintf"Relocation: unknown global %a: %a"F.ppfSymbolMap.pp_tablesymbols))inletrecrel=function|Constcwhenc<0->Const(relocatec)|Const_asx->x|App(c,x,xs)whenc<0->App(relocatec,relx,List.maprelxs)|App(c,x,xs)->App(c,relx,List.maprelxs)|Cons(x,y)->Cons(relx,rely)|Lamt->Lam(relt)|CData_asx->x|Builtin(c,l)->Builtin(map_builtin_predicaterelocatec,List.maprell)|(Nil|Discard)asx->x|Arg_|AppArg_|UVar_|AppUVar_->assertfalseinreltletrelocate_closed_term~from~to_t=tryResult.Ok(relocate_closed_term~from~to_t)withRelocationErrors->Result.ErrorsmoduleIntervalTree=structtype'at=(Ast.Loc.t*'a)list[@@derivingshow]letoverlap{Ast.Loc.source_name;source_start;source_stop}(l,_)=l.Ast.Loc.source_name=source_name&¬(l.Ast.Loc.source_start>source_stop||l.Ast.Loc.source_stop<source_start)letsmaller({Ast.Loc.source_start=b1;source_stop=e1},_)({Ast.Loc.source_start=b2;source_stop=e2},_)=letd1=e1-b1inletd2=e2-b2ind1-d2letfindlocl=List.filter(overlaploc)l|>List.sortsmallerendtypetype_=Compiler_data.TypeAssignment.tyletpp_type_=Compiler_data.TypeAssignment.pretty_mut_oncetypeinfo={defined:Ast.Loc.toption;type_:type_option}letpp_infofmt{defined;type_}=Format.fprintffmt"@[<hov 2>{ defined = %a,@ ty = %a }@]"(pp_optionAst.Loc.pp)defined(pp_optionpp_type_)type_letinfo_of_scoped_term~typest=leti=ref[]inletlog_tyloctype_=matchtype_with|None->()|Some_->i:=(loc,{defined=None;type_})::!iinletlog_symblocstype_=matchswith|Scope.Global{resolved_to}->letorigin=SymbolResolver.resolved_totypesresolved_toinletdefined=Option.mapSymbol.get_locoriginini:=(loc,{defined;type_})::!i|Scope.Bound_->i:=(loc,{defined=None;type_})::!iinletlog_bsymblocs=letdefined=Some(Symbol.get_locs)ini:=(loc,{defined;type_=None})::!iinletopenScopedTerminletrecauxlocty=function|Impl(_,locs,l,r)->log_bsymblocsGlobal_symbols.impl;log_tylocty;aux_locl;aux_locr|Discard_->log_tylocty|UVar({scope=s;ty=tys;loc=locs},args)->ifargs<>[]thenlog_tylocty;log_symblocs(Scope.Boundelpi_var)(TypeAssignment.deref_opttys);List.iteraux_locargs|App({scope=s;ty=tys;loc=locs},args)->ifargs<>[]thenlog_tylocty;log_symblocss(TypeAssignment.deref_opttys);List.iteraux_locargs|CData_->log_tylocty|Spill(t,_)->log_tylocty;aux_loct|Cast(t,_)->log_tylocty;aux_loct|Lam(Some{loc=sloc;ty=sty},_,_t)->log_tysloc(TypeAssignment.deref_optsty);log_tylocty;aux_loct|Lam(None,_,_t)->log_tylocty;aux_loctandaux_locx=auxx.loc(TypeAssignment.deref_optx.ty)x.itinaux_loct;!iletinfo_of_clause~types{Ast.Clause.body}=info_of_scoped_term~typesbodylethover(u:checked_compilation_unit)=let{CheckedFlat.clauses}=u.checked_codeinList.map(info_of_clause~types:u.precomputed_signature.Assembled.types)clauses|>List.flatten