123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386(******************************************************************************)(* *)(* Inferno *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the MIT License, as described in the file LICENSE. *)(* *)(******************************************************************************)openUnifierSigopenSolverSigmoduleMake(X:TEVAR)(S:STRUCTURE)(O:OUTPUTwithtype'astructure='aS.structure)=struct(* -------------------------------------------------------------------------- *)(* The type [tevar] of term variables is provided by [X]. *)typetevar=X.tevarmoduleXMap=Map.Make(structincludeXtypet=tevarend)(* The generalization engines is parametrized over inference structures [S],
it instantiates the generalization module [G] but also its underlying
unified [U]. *)moduleG=Generalization.Make(S)moduleU=G.U(* The type [variable] of type variables is provided by the unifier [U]. *)typevariable=intletfresh=letcounter=ref(-1)infun()->incrcounter;!counter(* The type [ischeme] is provided by the generalization engine [G]. *)(* -------------------------------------------------------------------------- *)(* Decoding types. *)(* A variable is decoded to its unique integer identifier, which (via the
function [O.variable]) is turned into an output type. *)letdecode_variable(x:U.variable):O.tyvar=(* The following assertion ensures that the decoder is invoked only
after the solver has been run. It would not really make sense to
invoke the decoder before running the solver. That said, at the
time of writing this comment, the API does not expose the decoder,
so the client should have no way of violating this assertion. *)assert(G.registeredx);O.solver_tyvar(U.idx)letdecode_variable_as_type(x:U.variable):O.ty=O.variable(decode_variablex)(* A type decoder is a function that transforms a unifier variable into an
output type. We choose to decode types in an eager manner; that is, we take
care of invoking the decoder, so that the client never needs to perform this
task. As a result, we do not even need to expose the decoder to the client
(although we could, if desired). *)type'vdecoder='v->O.ty(* The state of the cyclic decoder cannot persist. We must create a new
cyclic decoder at every invocation, otherwise the [mu] binders could
be incorrectly placed in the output. *)letdecode_cyclic:U.variabledecoder=funx->U.new_cyclic_decoderdecode_variable_as_typeO.structure(funxt->O.mu(decode_variablex)t)x(* Because [O.ty] is a nominal representation of types, a type is decoded
in the same way, regardless of how many type binders we have entered.
This makes it possible for the state of an (acyclic) decoder to persist
between invocations. Thanks to this property, the type decoding process
requires only linear time and space, regardless of how many calls to the
decoder are performed. *)(* The function [new_decoder] returns a new decoder. If [rectypes] is on,
the cyclic decoding function, which does not have persistent state, is
used. If [rectypes] is off, then a new acyclic decoder, with persistent
state, is created and returned. *)letnew_decoder~rectypes=letdecode_acyclic:U.variabledecoder=U.new_acyclic_decoderdecode_variable_as_typeO.structureinifrectypesthendecode_cyclicelsedecode_acyclic(* The function [decode_scheme] is parameterized by a type decoder, [decode]. *)letdecode_scheme(decode:U.variabledecoder)(s:G.scheme):O.scheme=List.mapdecode_variable(G.quantifierss),decode(G.bodys)(* -------------------------------------------------------------------------- *)(* The syntax of constraints is as follows. *)(* This syntax is exposed to the user in the low-level interface [SolverLo],
but not in the high-level interface [SolverHi]. So, it could be easily
modified if desired. *)typerange=Lexing.position*Lexing.positiontype_rawco=|CRange:range*'arawco->'arawco|CTrue:unitrawco|CConj:'arawco*'brawco->('a*'b)rawco|CEq:variable*variable->unitrawco|CExist:variable*variableS.structureoption*'arawco->'arawco|CWitness:variable->O.tyrawco|CInstance:tevar*variable->O.tylistrawco|CDef:tevar*variable*'arawco->'arawco|CLet:(tevar*variable)list*'arawco*'brawco->(O.tyvarlist*(tevar*O.scheme)list*'a*'b)rawco|CMap:'arawco*('a->'b)->'brawcoletpprint_rawcoc:PPrint.document=begin[@warning"-4"]letopen!PPrintinletrecprint:typea.arawco->_=func->print_binderscandprint_binders:typea.arawco->_=func->letnext=print_conjinletself=print_bindersingroup@@matchcwith|CRange(_range,c)->selfc|CMap(c,_f)->selfc|CExist(v,s,c)->string"exi"^^space^^group(print_varv^^(matchswith|None->empty|Somes->space^^string"~"^^space^^string(S.to_stringstring_of_vars)))^^space^^string"in"^//^selfc|CDef(x,v,c)->separatespace[string"def";annotxv;string"in";]^//^selfc|CLet(xvs,c1,c2)->separatespace[string"let";separate_map(space^^string"and"^^space)(fun(x,v)->annotxv)xvs;string"=";nextc1;string"in";]^//^selfc2|_->nextcandprint_conj:typea.arawco->_=func->letself=print_conjinletnext=print_simpleingroup@@matchcwith|CRange(_range,c)->selfc|CMap(c,_f)->selfc|CConj(c1,c2)->selfc1^//^separatespace[string"*";selfc2]|_->nextcandprint_simple:typea.arawco->_=func->letself=print_simpleinletnext=print_parenthesizedingroup@@matchcwith|CRange(_range,c)->selfc|CMap(c,_f)->selfc|CTrue->string"True"|CWitnessv->separatespace[string"wit";print_varv]|CEq(v1,v2)->separatespace[print_varv1;string"=";print_varv2]|CInstance(x,v)->separatespace[string"inst";print_tevarx;print_varv]|_->nextcandprint_parenthesized:typea.arawco->_=func->matchcwith|CRange_|CMap_|CTrue|CConj_|CEq_|CExist_|CWitness_|CInstance_|CDef_|CLet_->surround20lparen(printc)rparenandannotxv=separatespace[print_tevarx;print_varv]andprint_tevarx=PPrint.string(X.to_stringx)andprint_varv=PPrint.string(string_of_varv)andstring_of_varv=string_of_intvinprintcendletprint_rawcoppfc=letopen!PPrintinToFormatter.pretty0.980ppf(pprint_rawcoc);Format.pp_print_newlineppf()(* -------------------------------------------------------------------------- *)(* The exceptions [Unify] and [Cycle], raised by the unifier, must be caught
and re-raised in a slightly different format, as the unifier does not know
about ranges.
Note that the cyclic decoder is used when decoding types arising in typing
errors/exceptions, even if the solver was called with [~rectypes:false:
recursive types can appear before the occurs check is successfully run.
*)exceptionUnifyofrange*O.ty*O.tyexceptionCycleofrange*O.tyletunifyrangev1v2=tryU.unifyv1v2withU.Unify(v1,v2)->letdecode=new_decoder~rectypes:trueinraise(Unify(range,decodev1,decodev2))letexitrange~rectypesstatevs=tryG.exit~rectypesstatevswithU.Cyclev->letdecode=new_decoder~rectypes:trueinraise(Cycle(range,decodev))(* -------------------------------------------------------------------------- *)(* The non-recursive wrapper function [solve] is parameterized by the
flag [rectypes], which indicates whether recursive types are
permitted.
[solve] expects a constraint of type [a rawco] and solves it,
returning a witness of tyoe [a]. It proceedings in two phases:
- resolution: first the constraint is traversed, with each part
solved eagerly,
- witness construction: if the resolution succeeded, a global
solution is available, and we construct a witness from the solution.
This is implemented by having the first phase return a closure of
type ['a on_sol], that describes how the witnesses should be
computed when the final value will be available.
*)exceptionUnboundofrange*tevar(* ['a on_sol] represents values of type 'a that will only be
available once the solver has succeeded in finding a global
solution, as opposed to a value that is available as soon as it is
done traversing a sub-constraint. *)type'aon_sol=On_solof(unit->'a)[@@unboxed]letsolve~(rectypes:bool)(typea)(c:arawco):a=(* Initialize the generalization engine. It has mutable state, so [state]
does not need to be an explicit parameter of the recursive function
[solve]. *)letstate=G.init()in(* Constraint variables are immutable, they carry no mutable state.
We map them to unification variables (uvars) by using a table
indexed over the constraint variable integer identifier. *)letmoduleVarTbl=Hashtbl.Make(structtypet=variablelethashv=Hashtbl.hashvletequalv1v2=Int.equalv1v2end)inletuvars=VarTbl.create8inletuvarv=matchVarTbl.finduvarsvwith|None->Printf.ksprintffailwith"Unbound variable %d"v|Someuv->uvinletbind_uvarvs=assert(not(VarTbl.memuvarsv));letuv=G.fresh(Option.map(S.mapuvar)s)inVarTbl.adduvarsv(Someuv);G.registerstateuv;uvinletdecode=new_decoder~rectypesin(* The recursive function [solve] is parameterized with an environment
(which maps term variables to type schemes) and with a range (it is the
range annotation that was most recently encountered on the way down). *)letrecsolve:typea.G.schemeXMap.t->range->arawco->aon_sol=funenvrangec->matchcwith|CRange(range,c)->solveenvrangec|CTrue->On_sol(fun()->())|CMap(c,f)->let(On_solr)=solveenvrangecinOn_sol(fun()->f(r()))|CConj(c1,c2)->let(On_solr1)=solveenvrangec1inlet(On_solr2)=solveenvrangec2inOn_sol(fun()->(r1(),r2()))|CEq(v,w)->unifyrange(uvarv)(uvarw);On_sol(fun()->())|CExist(v,s,c)->ignore(bind_uvarvs);solveenvrangec|CWitnessv->On_sol(fun()->decode(uvarv))|CInstance(x,w)->(* The environment provides a type scheme for [x]. *)lets=tryXMap.findxenvwithNot_found->raise(Unbound(range,x))in(* Instantiating this type scheme yields a variable [v], which we unify with
[w]. It also yields a list of witnesses, which we record, as they will be
useful during the decoding phase. *)letwitnesses,v=G.instantiatestatesinunifyrangev(uvarw);On_sol(fun()->List.mapdecodewitnesses)|CDef(x,v,c)->letenv=XMap.addx(G.trivial(uvarv))envinsolveenvrangec|CLet(xvs,c1,c2)->(* Warn the generalization engine that we are entering the left-hand
side of a [let] construct. *)G.enterstate;(* Register the variables [vs] with the generalization engine, just as if
they were existentially bound in [c1]. This is what they are, basically,
but they also serve as named entry points. *)letvs=List.map(fun(_,v)->bind_uvarvNone)xvsin(* Solve the constraint [c1]. *)let(On_solr1)=solveenvrangec1in(* Ask the generalization engine to perform an occurs check, to adjust the
ranks of the type variables in the young generation (i.e., all of the
type variables that were registered since the call to [G.enter] above),
and to construct a list [ss] of type schemes for our entry points. The
generalization engine also produces a list [generalizable] of the young
variables that should be universally quantified here. *)letgeneralizable,ss=exitrange~rectypesstatevsin(* Extend the environment [env] and compute the type schemes [xss] *)letenv,xss=List.fold_right2(fun(x,_)s(env,xss)->(XMap.addxsenv,(x,s)::xss))xvsss(env,[])in(* Proceed to solve [c2] in the extended environment. *)let(On_solr2)=solveenvrangec2inOn_sol(fun()->List.mapdecode_variablegeneralizable,List.map(fun(x,s)->(x,decode_schemedecodes))xss,r1(),r2())inletenv=XMap.emptyandrange=Lexing.(dummy_pos,dummy_pos)inlet(On_solwitness)=solveenvrangecinwitness()end