Skip to content

Commit fd2a2e2

Browse files
committed
bidi_local: add var elimination
1 parent 7460be1 commit fd2a2e2

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

bidi_local/infer.ml

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,42 @@ let generalize ~lvl ty =
424424
Caml.Format.printf "GENR lvl:%i %s@." lvl (Ty_sch.show ty_sch);
425425
ty_sch
426426

427-
let subsumes constraints =
427+
let rec promote ~lvl (ty : ty) =
428+
match ty with
429+
| Ty_const _ -> ty
430+
| Ty_var v -> (
431+
match Var.ty v with
432+
| None -> if Var.lvl v > lvl then Ty_top else ty
433+
| Some ty -> promote ~lvl ty)
434+
| Ty_app (ty, args) ->
435+
Ty_app (promote ~lvl ty, List.map args ~f:(promote ~lvl))
436+
| Ty_nullable ty -> Ty_nullable (promote ~lvl ty)
437+
| Ty_arr (args, ty) -> Ty_arr (List.map args ~f:(demote ~lvl), promote ~lvl ty)
438+
| Ty_record row -> Ty_record (promote ~lvl row)
439+
| Ty_row_empty -> ty
440+
| Ty_row_extend ((name, ty), row) ->
441+
Ty_row_extend ((name, promote ~lvl ty), promote ~lvl row)
442+
| Ty_bot -> ty
443+
| Ty_top -> ty
444+
445+
and demote ~lvl (ty : ty) =
446+
match ty with
447+
| Ty_const _ -> ty
448+
| Ty_var v -> (
449+
match Var.ty v with
450+
| None -> if Var.lvl v > lvl then Ty_bot else ty
451+
| Some ty -> demote ~lvl ty)
452+
| Ty_app (ty, args) -> Ty_app (promote ~lvl ty, List.map args ~f:(demote ~lvl))
453+
| Ty_nullable ty -> Ty_nullable (demote ~lvl ty)
454+
| Ty_arr (args, ty) -> Ty_arr (List.map args ~f:(promote ~lvl), demote ~lvl ty)
455+
| Ty_record row -> Ty_record (demote ~lvl row)
456+
| Ty_row_empty -> ty
457+
| Ty_row_extend ((name, ty), row) ->
458+
Ty_row_extend ((name, demote ~lvl ty), demote ~lvl row)
459+
| Ty_bot -> ty
460+
| Ty_top -> ty
461+
462+
let subsumes ~lvl constraints =
428463
let exception Row_rewrite_error in
429464
let rec aux ~super_ty ~sub_ty =
430465
if Debug.log_solve then
@@ -466,18 +501,18 @@ let subsumes constraints =
466501
~merge_upper:(Constraint_set.greatest_lower_bound' constraints)
467502
sub_v super_v
468503
| Some sub_ty, None ->
469-
Constraint_set.add constraints super_v (sub_ty, Ty_top)
504+
Constraint_set.add constraints super_v (promote ~lvl sub_ty, Ty_top)
470505
| None, Some super_ty ->
471-
Constraint_set.add constraints sub_v (Ty_bot, super_ty)
506+
Constraint_set.add constraints sub_v (Ty_bot, demote ~lvl super_ty)
472507
| Some sub_ty, Some super_ty -> aux ~sub_ty ~super_ty)
473508
| Ty_var sub_v, super_ty -> (
474509
match Var.ty sub_v with
475510
| Some sub_ty -> aux ~super_ty ~sub_ty
476-
| None -> Constraint_set.add constraints sub_v (Ty_bot, super_ty))
511+
| None -> Constraint_set.add constraints sub_v (Ty_bot, demote ~lvl super_ty))
477512
| sub_ty, Ty_var super_v -> (
478513
match Var.ty super_v with
479514
| Some super_ty -> aux ~super_ty ~sub_ty
480-
| None -> Constraint_set.add constraints super_v (sub_ty, Ty_top))
515+
| None -> Constraint_set.add constraints super_v (promote ~lvl sub_ty, Ty_top))
481516
| _, Ty_top -> ()
482517
| Ty_bot, _ -> ()
483518
| _ -> Type_error.raise_not_a_subtype ~sub_ty ~super_ty
@@ -673,7 +708,7 @@ and synth' ~ctx expr =
673708
in
674709
let ty = Ty_record row in
675710
let ty', expr = synth ~ctx expr in
676-
subsumes constraints ~sub_ty:ty ~super_ty:ty';
711+
subsumes ~lvl:ctx.lvl constraints ~sub_ty:ty ~super_ty:ty';
677712
Constraint_set.solve constraints;
678713
(ty, E_record_update (expr, List.rev fields))
679714
| E_lit (Lit_string _) -> (Ty_const "string", expr)
@@ -719,7 +754,7 @@ and check' ~ctx ~constraints expr ty =
719754
List.fold2 args args_ty ~init:(env, [])
720755
~f:(fun (env, args) (name, ty') ty ->
721756
Option.iter ty' ~f:(fun ty' ->
722-
subsumes constraints ~sub_ty:ty ~super_ty:ty');
757+
subsumes ~lvl:ctx.lvl constraints ~sub_ty:ty ~super_ty:ty');
723758
let env = Env.add_val env name ([], ty) in
724759
(env, (name, Some ty) :: args))
725760
with
@@ -742,16 +777,16 @@ and check' ~ctx ~constraints expr ty =
742777
let () =
743778
match
744779
List.iter2 args_tys' args_tys ~f:(fun ty' ty ->
745-
subsumes constraints ~sub_ty:ty ~super_ty:ty')
780+
subsumes ~lvl:ctx.lvl constraints ~sub_ty:ty ~super_ty:ty')
746781
with
747782
| Unequal_lengths -> Type_error.raise Error_arity_mismatch
748783
| Ok () -> ()
749784
in
750-
subsumes constraints ~sub_ty:ty' ~super_ty:ty;
785+
subsumes ~lvl:ctx.lvl constraints ~sub_ty:ty' ~super_ty:ty;
751786
E_app (f, args)
752787
| expr ->
753788
let ty', expr = synth ~ctx expr in
754-
subsumes constraints ~sub_ty:ty' ~super_ty:ty;
789+
subsumes ~lvl:ctx.lvl constraints ~sub_ty:ty' ~super_ty:ty;
755790
expr
756791

757792
and check ~ctx expr ty =

bidi_local/test/test_infer.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,13 @@ let%expect_test "" =
248248
| |}]
249249

250250
let%expect_test "" =
251-
infer ~env "(fun x -> let y = fun (z : b) -> z in y : a, b . a -> b -> b)";
251+
(* TODO: missing b variable here *)
252+
infer ~env "(fun x -> let y = fun[b](z : b) -> z in y : a, b . a -> b -> b)";
252253
[%expect
253254
{|
254255
(fun (x: a) ->
255-
let y : b -> b = fun (z: b) -> z in y
256-
: a . a -> b -> b)
256+
let y : b/1 . b/1 -> b/1 = fun[b/1] (z: b/1) -> z in y
257+
: a, b . a -> b -> b)
257258
| |}]
258259

259260
let%expect_test "" =

0 commit comments

Comments
 (0)