Skip to content

Commit 0c12b26

Browse files
authored
Add -j flag to use 'join' rather than 'combine' (#14)
This is required for mailboxer. By default we can't have things like (x, x) in pairs since the components need to be disjoint. This flag allows us to switch to using the 'join' combination wherever we previously needed disjoint environments.
1 parent 42fcfc1 commit 0c12b26

File tree

4 files changed

+52
-42
lines changed

4 files changed

+52
-42
lines changed

bin/main.ml

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ let print_ir (prog, _prety, ir, _ty, _env, _constrs) =
2323
"=== Intermediate Representation: ===\n%a\n\n"
2424
(Ir.pp_program) ir
2525

26-
let process filename is_verbose is_debug is_ir mode benchmark_count disable_ql () =
26+
let process filename is_verbose is_debug is_ir mode benchmark_count disable_ql use_join () =
2727
Settings.(set verbose is_verbose);
2828
Settings.(set debug is_debug);
2929
Settings.(set receive_typing_strategy mode);
3030
Settings.(set benchmark benchmark_count);
3131
Settings.(set disable_quasilinearity disable_ql);
32+
Settings.(set join_not_combine use_join);
3233
try
3334
Frontend.Parse.parse_file filename ()
3435
|> Frontend.Pipeline.pipeline
@@ -51,6 +52,7 @@ let () =
5152
$ Arg.(value & opt int (-1) & info ["b"; "benchmark"]
5253
~docv:"BENCHMARK" ~doc:"number of repetitions for benchmark; -1 (default) for no benchmarking")
5354
$ Arg.(value & flag & info ["q"; "disable-quasilinearity"] ~doc:"disable quasilinearity checking")
55+
$ Arg.(value & flag & info ["j"; "join-not-combine"] ~doc:"use sequential join for value subterms, rather than requiring disjointness")
5456
$ const ()) in
5557
let info = Cmd.info "mbcheck" ~doc:"Typechecker for mailbox calculus" in
5658
Cmd.v info mbcheck_t

lib/common/settings.ml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ let debug = ref false
1313
let benchmark = ref (-1)
1414
let receive_typing_strategy = ref ReceiveTypingStrategy.Interface
1515
let disable_quasilinearity = ref false
16+
let join_not_combine = ref false
1617

1718
let set : 'a setting -> 'a -> unit = fun setting value ->
1819
setting := value

lib/common/settings.mli

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ val debug : bool setting
1111
val benchmark : int setting
1212
val receive_typing_strategy : ReceiveTypingStrategy.t setting
1313
val disable_quasilinearity : bool setting
14+
val join_not_combine : bool setting
1415

1516
val set : 'a setting -> 'a -> unit
1617
val get : 'a setting -> 'a

lib/typecheck/ty_env.ml

+47-41
Original file line numberDiff line numberDiff line change
@@ -25,47 +25,6 @@ let union = VarMap.union
2525
let from_list xs = List.to_seq xs |> VarMap.of_seq
2626

2727

28-
(* Combines two environments. The environments should only intersect
29-
on unrestricted types. *)
30-
let combine : Interface_env.t -> t -> t -> t * Constraint_set.t =
31-
fun ienv env1 env2 ->
32-
(* Types must be *the same* and *unrestricted* *)
33-
(* Subtype in both directions *)
34-
let join_types var (ty1: Type.t) (ty2: Type.t) =
35-
(* The subtyping and constraints are enough to rule out
36-
re-use of mailboxes, but it's worth special-casing to
37-
get a better error message. *)
38-
if Type.contains_mailbox_type ty1 && Type.contains_mailbox_type ty2
39-
then
40-
Gripers.combine_mailbox_type var
41-
else
42-
Constraint_set.union_many
43-
[
44-
make_unrestricted ty1;
45-
make_unrestricted ty2;
46-
subtype ienv ty1 ty2;
47-
subtype ienv ty2 ty1
48-
]
49-
in
50-
(* Find the overlapping keys, zip up, and join. *)
51-
(* Since the subtyping in both directions will ensure equality of types,
52-
and that the relevant constraints are generated, it is safe to just
53-
use either type in the combined environment. *)
54-
let overlap_constrs =
55-
bindings env1
56-
|> List.filter_map (fun (k, ty1) ->
57-
match lookup_opt k env2 with
58-
| None -> None
59-
| Some ty2 -> Some (join_types k ty1 ty2)
60-
61-
)
62-
|> Constraint_set.union_many
63-
in
64-
let combined_env =
65-
union (fun _ ty1 _ -> Some ty1) env1 env2
66-
in
67-
(combined_env, overlap_constrs)
68-
6928
(* Joins two sequential or concurrent environments (i.e., where *both*
7029
actions will happen). *)
7130
let join : Interface_env.t -> t -> t -> t * Constraint_set.t =
@@ -155,6 +114,53 @@ let join : Interface_env.t -> t -> t -> t * Constraint_set.t =
155114
) ([], Constraint_set.empty) isect1 in
156115
from_list (joined @ disjoint1 @ disjoint2), constrs
157116

117+
(* Combines two environments. The environments should only intersect
118+
on unrestricted types. *)
119+
let combine : Interface_env.t -> t -> t -> t * Constraint_set.t =
120+
fun ienv env1 env2 ->
121+
let combine_really ienv env1 env2 =
122+
(* Types must be *the same* and *unrestricted* *)
123+
(* Subtype in both directions *)
124+
let join_types var (ty1: Type.t) (ty2: Type.t) =
125+
(* The subtyping and constraints are enough to rule out
126+
re-use of mailboxes, but it's worth special-casing to
127+
get a better error message. *)
128+
if Type.contains_mailbox_type ty1 && Type.contains_mailbox_type ty2
129+
then
130+
Gripers.combine_mailbox_type var
131+
else
132+
Constraint_set.union_many
133+
[
134+
make_unrestricted ty1;
135+
make_unrestricted ty2;
136+
subtype ienv ty1 ty2;
137+
subtype ienv ty2 ty1
138+
]
139+
in
140+
(* Find the overlapping keys, zip up, and join. *)
141+
(* Since the subtyping in both directions will ensure equality of types,
142+
and that the relevant constraints are generated, it is safe to just
143+
use either type in the combined environment. *)
144+
let overlap_constrs =
145+
bindings env1
146+
|> List.filter_map (fun (k, ty1) ->
147+
match lookup_opt k env2 with
148+
| None -> None
149+
| Some ty2 -> Some (join_types k ty1 ty2)
150+
151+
)
152+
|> Constraint_set.union_many
153+
in
154+
let combined_env =
155+
union (fun _ ty1 _ -> Some ty1) env1 env2
156+
in
157+
(combined_env, overlap_constrs)
158+
in
159+
let fn =
160+
if Settings.(get join_not_combine) then join else combine_really
161+
in
162+
fn ienv env1 env2
163+
158164
(* Merges environments resulting from branching control flow. *)
159165
(* Core idea is that linear types must be used in precisely the same way in
160166
each branch. Unrestricted types must be used at the same type, but need

0 commit comments

Comments
 (0)