Skip to content

Commit 91dd878

Browse files
committed
Interface: Use kind-inference for outcome variables
Previously these always had kind Type so we didn't need to infer them. We'll probably need a syntax change as the >= 0 constraint is just discarded right now when we infer Nat, as there is nowhere to put it.
1 parent a124773 commit 91dd878

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

src/lib/initial_check.ml

+50-6
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type ctx = {
7272
kinds : (kind_aux * P.l) KBindings.t;
7373
function_type_variables : (kind_aux * P.l) KBindings.t Bindings.t;
7474
type_constructors : type_constructor Bindings.t;
75+
outcome_variables : kind_aux KBindings.t;
7576
scattereds : (P.typquant * ctx) Bindings.t;
7677
fixities : (prec * int) Bindings.t;
7778
internal_files : StringSet.t;
@@ -111,6 +112,10 @@ let merge_ctx l ctx1 ctx2 =
111112
)
112113
)
113114
ctx1.function_type_variables ctx2.function_type_variables;
115+
outcome_variables =
116+
KBindings.merge
117+
(compatible ( = ) (fun v -> "Outcome definitions have different kinds for type variable " ^ string_of_kid v))
118+
ctx1.outcome_variables ctx2.outcome_variables;
114119
type_constructors =
115120
Bindings.merge
116121
(compatible ( = ) (fun id -> "Different definitions for type constructor " ^ string_of_id id ^ " found"))
@@ -788,6 +793,12 @@ module KindInference = struct
788793
in
789794
return (typq, typ, kind)
790795

796+
let check_outcome ctx typq (P.ATyp_aux (_, l) as typ) kopts =
797+
let* kopts = mapM (fun kopt -> fmap List.hd (add_vars [kopt])) kopts in
798+
let* typq = infer_typquant ctx typq in
799+
let* typ = check ctx typ (Kind (K_type, l)) in
800+
return (typq, typ, kopts)
801+
791802
let initial_env = { sets = []; next_unknown = 0; vars = [] }
792803
end
793804

@@ -1457,19 +1468,51 @@ let to_ast_spec ctx (P.VS_aux (P.VS_val_spec (ts, id, ext), l)) =
14571468
let ctx = { ctx with function_type_variables = Bindings.add id ts_ctx.kinds ctx.function_type_variables } in
14581469
(VS_aux (VS_val_spec (typschm, id, ext), (l, empty_uannot)), ctx)
14591470

1460-
let to_ast_outcome ctx (ev : P.outcome_spec) : outcome_spec ctx_out =
1471+
let to_ast_outcome ctx (ev : P.outcome_spec) : outcome_spec * ctx * ctx =
14611472
match ev with
1462-
| P.OV_aux (P.OV_outcome (id, typschm, outcome_args), l) ->
1473+
| P.OV_aux (P.OV_outcome (id, P.TypSchm_aux (P.TypSchm_ts (typq, typ), ts_l), outcome_args), l) ->
1474+
let open KindInference in
1475+
let (typq, typ, outcome_args), kenv = check_outcome ctx typq typ outcome_args initial_env in
14631476
let outcome_args, inner_ctx =
14641477
List.fold_left
14651478
(fun (args, ctx) arg ->
1466-
let (arg, _, ctx), _ = to_ast_kopts ctx arg in
1479+
let (arg, _, ctx), _ = ConvertType.to_ast_kopts kenv ctx arg in
14671480
(arg @ args, ctx)
14681481
)
14691482
([], ctx) outcome_args
14701483
in
1471-
let typschm, _ = to_ast_typschm inner_ctx typschm in
1472-
(OV_aux (OV_outcome (to_ast_id ctx id, typschm, List.rev outcome_args), l), inner_ctx)
1484+
let typq, ts_ctx = ConvertType.to_ast_typquant kenv inner_ctx typq in
1485+
let typ = ConvertType.to_ast_typ kenv ts_ctx typ in
1486+
let ctx =
1487+
List.fold_left
1488+
(fun ctx kopt ->
1489+
let v = kopt_kid kopt in
1490+
let k = unaux_kind (kopt_kind kopt) in
1491+
{
1492+
ctx with
1493+
outcome_variables =
1494+
KBindings.update v
1495+
(function
1496+
| None -> Some k
1497+
| Some k' when k = k' -> Some k'
1498+
| Some k' ->
1499+
let v', _ =
1500+
List.find (fun (v', _) -> Kid.compare v v' = 0) (KBindings.bindings ctx.outcome_variables)
1501+
in
1502+
Printf.sprintf "Outcome variable %s has kind %s here, but previously used with kind %s"
1503+
(string_of_kid v) (string_of_kind_aux k) (string_of_kind_aux k')
1504+
|> Reporting.err_typ (Hint ("previous use here", kid_loc v', kid_loc v))
1505+
|> raise
1506+
)
1507+
ctx.outcome_variables;
1508+
}
1509+
)
1510+
ctx outcome_args
1511+
in
1512+
( OV_aux (OV_outcome (to_ast_id ctx id, TypSchm_aux (TypSchm_ts (typq, typ), ts_l), List.rev outcome_args), l),
1513+
inner_ctx,
1514+
ctx
1515+
)
14731516

14741517
let rec to_ast_range ctx (P.BF_aux (r, l)) =
14751518
(* TODO add check that ranges are sensible for some definition of sensible *)
@@ -2017,7 +2060,7 @@ let rec to_ast_def doc attrs vis ctx (P.DEF_aux (def, l)) : untyped_def list ctx
20172060
let vs, ctx = to_ast_spec ctx val_spec in
20182061
([DEF_aux (DEF_val vs, annot)], ctx)
20192062
| P.DEF_outcome (outcome_spec, defs) ->
2020-
let outcome_spec, inner_ctx = to_ast_outcome ctx outcome_spec in
2063+
let outcome_spec, inner_ctx, ctx = to_ast_outcome ctx outcome_spec in
20212064
let defs, _ =
20222065
List.fold_left
20232066
(fun (defs, ctx) def ->
@@ -2150,6 +2193,7 @@ let initial_ctx =
21502193
("float128", ([], P.K_type));
21512194
("float_rounding_mode", ([], P.K_type));
21522195
];
2196+
outcome_variables = KBindings.empty;
21532197
function_type_variables = Bindings.empty;
21542198
kinds = KBindings.empty;
21552199
scattereds = Bindings.empty;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Type error:
2+
fail/outcome_mismatch_var.sail:5.46-48:
3+
5 |outcome foo : vector('m, 'n) -> unit with 'n, 'm
4+
 | ^^ previous use here
5+
fail/outcome_mismatch_var.sail:7.46-48:
6+
7 |outcome bar : vector('n, 'm) -> unit with 'n, 'm
7+
 | ^^
8+
 | Outcome variable 'm has kind Type here, but previously used with kind Int
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default Order dec
2+
3+
$include <prelude.sail>
4+
5+
outcome foo : vector('m, 'n) -> unit with 'n, 'm
6+
7+
outcome bar : vector('n, 'm) -> unit with 'n, 'm

0 commit comments

Comments
 (0)