|
|
|
@ -129,11 +129,32 @@ end
|
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
|
|
|
|
|
|
(* Instantiate the solver. *)
|
|
|
|
|
type tvar =
|
|
|
|
|
| Tevar of string
|
|
|
|
|
| SVar of int
|
|
|
|
|
|
|
|
|
|
let fresh () : tvar =
|
|
|
|
|
let uid = Inferno.Utils.gensym()() in
|
|
|
|
|
SVar uid
|
|
|
|
|
|
|
|
|
|
module X = struct
|
|
|
|
|
type tevar = string
|
|
|
|
|
let compare = String.compare
|
|
|
|
|
let to_string s = s
|
|
|
|
|
type tevar = tvar
|
|
|
|
|
let compare v1 v2 =
|
|
|
|
|
match v1, v2 with
|
|
|
|
|
| Tevar v1, Tevar v2 ->
|
|
|
|
|
compare v1 v2
|
|
|
|
|
| SVar v1, SVar v2 ->
|
|
|
|
|
Stdlib.compare v1 v2
|
|
|
|
|
| Tevar _, SVar _ ->
|
|
|
|
|
-1
|
|
|
|
|
| SVar _, Tevar _ ->
|
|
|
|
|
1
|
|
|
|
|
let to_string v =
|
|
|
|
|
match v with
|
|
|
|
|
| Tevar v ->
|
|
|
|
|
v
|
|
|
|
|
| SVar v ->
|
|
|
|
|
string_of_int v
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module Solver = Inferno.Solver.Make(X)(S)(O)
|
|
|
|
@ -304,25 +325,7 @@ let convert env params ty =
|
|
|
|
|
let deep_ty = convert_deep env params ty in
|
|
|
|
|
build deep_ty
|
|
|
|
|
|
|
|
|
|
exception VariableConflict of string
|
|
|
|
|
|
|
|
|
|
let convert_annot env ((flex_vars, ty) : ML.type_annotation)
|
|
|
|
|
: (variable * F.nominal_type co, 'r) binder
|
|
|
|
|
= fun k ->
|
|
|
|
|
let@ params, witnesses =
|
|
|
|
|
flex_vars |> mapM_both (fun alpha k ->
|
|
|
|
|
let@ v = exist in
|
|
|
|
|
k (
|
|
|
|
|
(alpha, v),
|
|
|
|
|
let+ ty' = witness v in (alpha, ty'))
|
|
|
|
|
)
|
|
|
|
|
in
|
|
|
|
|
let@ v = convert env params ty in
|
|
|
|
|
k (v,
|
|
|
|
|
let+ ws = witnesses in
|
|
|
|
|
let translate_var alpha = List.assoc alpha ws in
|
|
|
|
|
ML2F.translate_type translate_var ty
|
|
|
|
|
)
|
|
|
|
|
exception VariableConflict of ML.tevar
|
|
|
|
|
|
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
|
|
|
|
|
@ -351,7 +354,7 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
| ML.Var (pos, x) ->
|
|
|
|
|
|
|
|
|
|
(* [w] must be an instance of the type scheme associated with [x]. *)
|
|
|
|
|
let+ tys = instance x w in
|
|
|
|
|
let+ tys = instance (Tevar x) w in
|
|
|
|
|
(* The translation makes the type application explicit. *)
|
|
|
|
|
F.ftyapp (F.Var (pos, x)) tys
|
|
|
|
|
|
|
|
|
@ -367,7 +370,7 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
let+ () = w --- arrow v1 v2
|
|
|
|
|
(* Under the assumption that [x] has type [domain], the term [u] must
|
|
|
|
|
have type [codomain]. *)
|
|
|
|
|
and+ u' = def x v1 (hastype u v2)
|
|
|
|
|
and+ u' = def (Tevar x) v1 (hastype u v2)
|
|
|
|
|
and+ ty1 = witness v1
|
|
|
|
|
in
|
|
|
|
|
(* Once these constraints are solved, we obtain the translated function
|
|
|
|
@ -388,7 +391,7 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
| ML.Let (pos, x, t, u) ->
|
|
|
|
|
|
|
|
|
|
(* Construct a ``let'' constraint. *)
|
|
|
|
|
let+ ((b, _), a, t', u') = let1 x (hastype t) (hastype u w) in
|
|
|
|
|
let+ ((b, _), a, t', u') = let1 (Tevar x) (hastype t) (hastype u w) in
|
|
|
|
|
(* [a] are the type variables that we must bind (via Lambda abstractions)
|
|
|
|
|
while type-checking [t]. [(b, _)] is the type scheme that [x] must
|
|
|
|
|
receive while type-checking [u]. Its quantifiers [b] are guaranteed to
|
|
|
|
@ -401,11 +404,31 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
u'))
|
|
|
|
|
|
|
|
|
|
| ML.Annot (pos, t, annot) ->
|
|
|
|
|
let@ v, annot' = convert_annot typedecl_env annot in
|
|
|
|
|
let+ () = v -- w
|
|
|
|
|
and+ t' = hastype t v
|
|
|
|
|
and+ annot' = annot' in
|
|
|
|
|
F.Annot (pos, t', annot')
|
|
|
|
|
|
|
|
|
|
let convert_annot typedecl_env params w t ty =
|
|
|
|
|
let@ v = convert typedecl_env params ty in
|
|
|
|
|
let+ () = v -- w
|
|
|
|
|
and+ t' = hastype t v
|
|
|
|
|
and+ ty' = witness v
|
|
|
|
|
in F.Annot (pos, t', ty')
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
begin match annot with
|
|
|
|
|
| (_, [], ty) ->
|
|
|
|
|
convert_annot typedecl_env [] w t ty
|
|
|
|
|
| (ML.Flexible, vs, ty) ->
|
|
|
|
|
let@ params =
|
|
|
|
|
vs |> mapM_now (fun alpha k -> let@ v = exist in k (alpha, v)) in
|
|
|
|
|
convert_annot typedecl_env params w t ty
|
|
|
|
|
| (ML.Rigid, vs, ty) ->
|
|
|
|
|
let sv = fresh () in
|
|
|
|
|
let+ (alphas, t', tys) =
|
|
|
|
|
letr1 vs sv
|
|
|
|
|
(fun tyvs w -> convert_annot typedecl_env tyvs w t ty)
|
|
|
|
|
(instance sv w)
|
|
|
|
|
in
|
|
|
|
|
F.ftyapp (F.ftyabs alphas t') tys
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
| ML.Tuple (pos, ts) ->
|
|
|
|
|
let on_term (t:ML.term) : ('b * 'c co, 'r) binder =
|
|
|
|
@ -424,7 +447,7 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
let on_var (x:ML.tevar) : ('a, 'r) binder =
|
|
|
|
|
fun (k : 'b -> 'r co) : 'r co ->
|
|
|
|
|
let@ v = exist in
|
|
|
|
|
def x v (k v)
|
|
|
|
|
def (Tevar x) v (k v)
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
let@ vs = mapM_now on_var xs in
|
|
|
|
@ -521,7 +544,7 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
as the whole match statement *)
|
|
|
|
|
hastype u v_return
|
|
|
|
|
| (x, v1) :: pat_env ->
|
|
|
|
|
def x v1 @@ bind_pattern_vars pat_env u
|
|
|
|
|
def (Tevar x) v1 @@ bind_pattern_vars pat_env u
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
let on_branch ((pat,u) : ML.branch)
|
|
|
|
@ -552,15 +575,25 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
| ML.PWildcard pos ->
|
|
|
|
|
k ([], pure (F.PWildcard pos))
|
|
|
|
|
|
|
|
|
|
| ML.PAnnot (pos, pat, annot) ->
|
|
|
|
|
let@ v, annot' = convert_annot typedecl_env annot in
|
|
|
|
|
let@ (pat_env, pat) = hastype_pat typedecl_env pat v in
|
|
|
|
|
let+ () = v -- w
|
|
|
|
|
and+ res = k (pat_env,
|
|
|
|
|
let+ pat = pat
|
|
|
|
|
and+ annot' = annot'
|
|
|
|
|
in F.PAnnot(pos, pat, annot'))
|
|
|
|
|
in res
|
|
|
|
|
| ML.PAnnot (pos, pat, (rigidity, vars, ty)) ->
|
|
|
|
|
begin match rigidity with
|
|
|
|
|
| ML.Rigid ->
|
|
|
|
|
failwith "Rigid variables are not supported in pattern annotation"
|
|
|
|
|
| ML.Flexible ->
|
|
|
|
|
let@ params =
|
|
|
|
|
vars |> mapM_now (fun alpha k ->
|
|
|
|
|
let@ v = exist in k(alpha,v)
|
|
|
|
|
)
|
|
|
|
|
in
|
|
|
|
|
let@ v = convert typedecl_env params ty in
|
|
|
|
|
let@ (pat_env, pat) = hastype_pat typedecl_env pat v in
|
|
|
|
|
let+ () = v -- w
|
|
|
|
|
and+ res = k (pat_env,
|
|
|
|
|
let+ pat = pat
|
|
|
|
|
and+ ty' = witness v
|
|
|
|
|
in F.PAnnot(pos, pat, ty'))
|
|
|
|
|
in res
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
| ML.PTuple (pos, pats) ->
|
|
|
|
|
|
|
|
|
@ -619,13 +652,16 @@ let hastype (typedecl_env : ML.datatype_env) (t : ML.term) (w : variable) : F.no
|
|
|
|
|
type; it creates its own using [exist]. And it runs the solver. *)
|
|
|
|
|
|
|
|
|
|
type nonrec range = range
|
|
|
|
|
exception Unbound = Solver.Unbound
|
|
|
|
|
exception Unbound of range * string
|
|
|
|
|
exception Unify = Solver.Unify
|
|
|
|
|
exception Cycle = Solver.Cycle
|
|
|
|
|
|
|
|
|
|
let translate ~rectypes (env : ML.datatype_env) (t : ML.term) : F.nominal_term =
|
|
|
|
|
Solver.solve ~rectypes (
|
|
|
|
|
let+ (vs, t) = let0 (exist (hastype env t)) in
|
|
|
|
|
(* [vs] are the binders that we must introduce *)
|
|
|
|
|
F.ftyabs vs t
|
|
|
|
|
)
|
|
|
|
|
try
|
|
|
|
|
Solver.solve ~rectypes (
|
|
|
|
|
let+ (vs, t) = let0 (exist (hastype env t)) in
|
|
|
|
|
(* [vs] are the binders that we must introduce *)
|
|
|
|
|
F.ftyabs vs t
|
|
|
|
|
)
|
|
|
|
|
with Solver.Unbound (range, Tevar x) ->
|
|
|
|
|
raise (Unbound (range, x))
|
|
|
|
|