Skip to content

Commit 55a7c9b

Browse files
authored
Merge pull request #4553 from BuckleScript/flatten
linearize pattern match over polyvar (off by default)
2 parents 9a2b2da + 854d7a2 commit 55a7c9b

15 files changed

+5733
-5553
lines changed

jscomp/core/polyvar_pattern_match.ml

Lines changed: 111 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,59 +22,139 @@
2222
* along with this program; if not, write to the Free Software
2323
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
2424

25+
type lam = Lambda.lambda
2526

26-
27-
let make_test_sequence_variant_constant
28-
(fail : Lambda.lambda option) (arg : Lambda.lambda)
29-
(int_lambda_list : (int * (string * Lambda.lambda) ) list) : Lambda.lambda=
27+
28+
module Map_lambda = struct
29+
open Map_gen
30+
type key =
31+
| Bottom of int
32+
| Normalized of lam
33+
34+
let bottom_id = ref (-1)
35+
let bottom () = incr bottom_id ; Bottom !bottom_id
36+
let compare_key (x : key) (y : key) = Pervasives.compare x y
37+
let old_order = ref 1
38+
let next_id () =
39+
incr old_order; !old_order
40+
let rec adjust (tree : _ Map_gen.t as 'a) x replace : 'a =
41+
match tree with
42+
| Empty ->
43+
singleton x (replace None)
44+
| Leaf {k ; v} ->
45+
let c = compare_key x k in
46+
if c = 0 then singleton x (replace (Some v)) else
47+
if c < 0 then
48+
Map_gen.unsafe_two_elements x (replace None) k v
49+
else
50+
Map_gen.unsafe_two_elements k v x (replace None)
51+
| Node ({l; k ; r} as tree) ->
52+
let c = compare_key x k in
53+
if c = 0 then
54+
Map_gen.unsafe_node x (replace (Some tree.v)) l r tree.h
55+
else if c < 0 then
56+
bal (adjust l x replace ) k tree.v r
57+
else
58+
bal l k tree.v (adjust r x replace )
59+
60+
61+
let of_list (int_lambda_list : (int * (string * lam)) list) : (key, (int * string) list * lam * int ) t=
62+
Ext_list.fold_left int_lambda_list empty (fun acc (hash,(name,lam)) ->
63+
let key =
64+
match Lambda.make_key lam with
65+
| None -> bottom ()
66+
| Some key -> Normalized key in
67+
adjust acc key (function
68+
| None -> [hash, name], lam, next_id ()
69+
| Some (acc,action,stamp) -> (hash,name) :: acc, action, stamp
70+
))
71+
let rec values_aux s acc =
72+
match s with
73+
| Empty -> acc
74+
| Leaf {v} -> v :: acc
75+
| Node {l;v;r} ->
76+
values_aux l (v ::values_aux r acc)
77+
let values s : ((int * string) list * lam) list =
78+
Ext_list.sort_via_arrayf ( values_aux s [])
79+
(fun (_,_,d0) (_,_,d1) -> compare d0 d1)
80+
(fun (a,b,_) -> (a,b))
81+
82+
end
83+
84+
let or_list (arg : lam) (hash_names : (int * string) list) =
85+
match hash_names with
86+
| (hash,name):: rest ->
87+
let init : lam =
88+
Lprim(Pintcomp Ceq,
89+
[arg; Lconst ((Const_pointer (hash, Pt_variant{name})))],
90+
Location.none) in
91+
Ext_list.fold_left rest init (fun acc (hash,name) ->
92+
Lambda.Lprim
93+
(Psequor ,
94+
[acc ;
95+
Lprim(Pintcomp Ceq,
96+
[arg;
97+
Lconst ((Const_pointer (hash, Pt_variant{name})))],
98+
Location.none)], Location.none)
99+
)
100+
| _ -> assert false
101+
102+
let make_test_sequence_variant_constant
103+
(fail : lam option) (arg : lam)
104+
(int_lambda_list : (int * (string * lam) ) list) : lam =
105+
let int_lambda_list : ((int * string) list * lam) list =
106+
Map_lambda.(values (of_list int_lambda_list)) in
107+
match int_lambda_list, fail with
108+
| (_, act) :: rest, None
109+
| rest, Some act ->
110+
Ext_list.fold_right rest act (fun (hash_names,act1) acc ->
111+
let predicate : lam = or_list arg hash_names in
112+
Lifthenelse (predicate,act1, acc))
113+
| [], None -> assert false
114+
115+
let make_test_sequence_variant_constant_2
116+
(fail : lam option) (arg : lam)
117+
(int_lambda_list : (int * (string * lam) ) list) : lam=
30118
match int_lambda_list, fail with
31-
| (_, (_,act)) :: rest, None ->
119+
| (_, (_,act)) :: rest, None
120+
| rest , Some act ->
32121
Ext_list.fold_right rest act (fun (hash1,(name,act1)) acc ->
33-
Lifthenelse (Lprim(Pintcomp Ceq,
34-
[arg; Lconst ((Const_pointer (hash1, Pt_variant{name})))], Location.none),
35-
act1, acc
36-
)
37-
)
38-
| _, Some fail ->
39-
Ext_list.fold_right int_lambda_list fail (fun (hash1,(name,act1)) acc ->
40122
Lifthenelse (Lprim(Pintcomp Ceq,
41123
[arg; Lconst (Const_pointer(hash1, Pt_variant{name}))], Location.none),
42124
act1, acc
43125
)
44126
)
45127
| [], None -> assert false
46128

47-
let call_switcher_variant_constant
129+
let call_switcher_variant_constant
48130
(_loc : Location.t)
49-
(fail : Lambda.lambda option)
50-
(arg : Lambda.lambda)
51-
(int_lambda_list : (int * (string * Lambda.lambda)) list)
131+
(fail : lam option)
132+
(arg : lam)
133+
(int_lambda_list : (int * (string * lam)) list)
52134
(_names : Lambda.switch_names option) =
53-
Ext_log.dwarn ~__POS__ "%a@." Ext_obj.pp_any _names;
135+
136+
let int_lambda_list : ((int * string) list * lam) list =
137+
Map_lambda.(values (of_list int_lambda_list)) in
54138
match int_lambda_list, fail with
55-
| (_, (_,act)) :: rest, None ->
56-
Ext_list.fold_right rest act (fun (hash1,(name,act1)) acc ->
57-
Lifthenelse (Lprim(Pintcomp Ceq,
58-
[arg; Lconst (Const_pointer(hash1, Pt_variant{name}))], Location.none),
59-
act1, acc
60-
)
61-
)
62-
| _, Some fail ->
63-
Ext_list.fold_right int_lambda_list fail (fun (hash1,(name,act1)) acc ->
64-
Lifthenelse (Lprim(Pintcomp Ceq,
65-
[arg; Lconst (Const_pointer(hash1, Pt_variant{name}))], Location.none),
139+
| (_,act) :: rest, None
140+
| rest, Some act ->
141+
Ext_list.fold_right rest act (fun (hash_names,act1) acc ->
142+
let predicate = or_list arg hash_names in
143+
Lifthenelse (predicate,
66144
act1, acc
67145
)
68146
)
69147
| [], None -> assert false
70148

71149

150+
151+
72152
let call_switcher_variant_constr
73153
(loc : Location.t)
74-
(fail : Lambda.lambda option)
75-
(arg : Lambda.lambda)
154+
(fail : lam option)
155+
(arg : lam)
76156
int_lambda_list
77-
(names : Lambda.switch_names option) : Lambda.lambda =
157+
(names : Lambda.switch_names option) : lam =
78158
let v = Ident.create "variant" in
79159
Llet(Alias, Pgenval, v, Lprim(Pfield (0, Fld_poly_var_tag), [arg], loc),
80160
call_switcher_variant_constant

jscomp/ext/ext_list.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,10 @@ let sort_via_array lst cmp =
673673
Array.sort cmp arr;
674674
Array.to_list arr
675675

676-
676+
let sort_via_arrayf lst cmp f =
677+
let arr = Array.of_list lst in
678+
Array.sort cmp arr;
679+
Ext_array.to_list_f arr f
677680

678681

679682
let rec assoc_by_string lst (k : string) def =

jscomp/ext/ext_list.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ val sort_via_array :
342342
('a -> 'a -> int) ->
343343
'a list
344344

345+
val sort_via_arrayf:
346+
'a list ->
347+
('a -> 'a -> int) ->
348+
('a -> 'b ) ->
349+
'b list
345350

346351

347352

jscomp/ext/map.cppo.ml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,3 @@ let of_list xs = add_list xs empty
215215

216216
let of_array xs =
217217
Ext_array.fold_left xs empty (fun acc (k,v) -> add acc k v )
218-
#ifdef TYPE_FUNCTOR
219-
end
220-
#endif

jscomp/test/poly_variant_test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,17 @@ eq("File \"poly_variant_test.ml\", line 143, characters 5-12", 3, p_is_int_test(
133133
VAL: 2
134134
}));
135135

136+
function hey(x) {
137+
if (x >= 101) {
138+
console.log("v");
139+
console.log(x);
140+
} else {
141+
console.log("u");
142+
console.log(x);
143+
}
144+
145+
}
146+
136147
Mt.from_pair_suites("Poly_variant_test", suites.contents);
137148

138149
function on2(prim, prim$1) {
@@ -158,4 +169,5 @@ exports.on2 = on2;
158169
exports.read = read;
159170
exports.readN = readN;
160171
exports.p_is_int_test = p_is_int_test;
172+
exports.hey = hey;
161173
/* Not a pure module */

jscomp/test/poly_variant_test.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,19 @@ let () =
142142
eq __LOC__ 2 (p_is_int_test `a);
143143
eq __LOC__ 3 (p_is_int_test u)
144144

145+
146+
let hey x =
147+
match x with
148+
| `a
149+
| `b
150+
| `d
151+
| `c as u ->
152+
Js.log "u";
153+
Js.log u
154+
155+
| `e
156+
| `f
157+
| `h as v ->
158+
Js.log "v";
159+
Js.log v
145160
let () = Mt.from_pair_suites __MODULE__ !suites

jscomp/test/poly_variant_test.mli

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@ val on2 :
3333
([ `line of (string -> unit [@bs])
3434
| `close of (unit -> unit [@bs])]
3535
) ->
36-
unit
36+
unit
3737

3838
val read : string -> string
3939
val readN : string -> string
4040

4141
val p_is_int_test
42-
: [`a | `b of int] -> int
42+
: [`a | `b of int] -> int
43+
44+
val hey :
45+
[ `a | `b | `c | `d | `e | `f | `h ] -> unit
46+

lib/4.06.1/bsb.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,11 @@ val sort_via_array :
22892289
('a -> 'a -> int) ->
22902290
'a list
22912291

2292+
val sort_via_arrayf:
2293+
'a list ->
2294+
('a -> 'a -> int) ->
2295+
('a -> 'b ) ->
2296+
'b list
22922297

22932298

22942299

@@ -3030,7 +3035,10 @@ let sort_via_array lst cmp =
30303035
Array.sort cmp arr;
30313036
Array.to_list arr
30323037

3033-
3038+
let sort_via_arrayf lst cmp f =
3039+
let arr = Array.of_list lst in
3040+
Array.sort cmp arr;
3041+
Ext_array.to_list_f arr f
30343042

30353043

30363044
let rec assoc_by_string lst (k : string) def =

lib/4.06.1/unstable/all_ounit_tests.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3805,6 +3805,11 @@ val sort_via_array :
38053805
('a -> 'a -> int) ->
38063806
'a list
38073807

3808+
val sort_via_arrayf:
3809+
'a list ->
3810+
('a -> 'a -> int) ->
3811+
('a -> 'b ) ->
3812+
'b list
38083813

38093814

38103815

@@ -4546,7 +4551,10 @@ let sort_via_array lst cmp =
45464551
Array.sort cmp arr;
45474552
Array.to_list arr
45484553

4549-
4554+
let sort_via_arrayf lst cmp f =
4555+
let arr = Array.of_list lst in
4556+
Array.sort cmp arr;
4557+
Ext_array.to_list_f arr f
45504558

45514559

45524560
let rec assoc_by_string lst (k : string) def =

lib/4.06.1/unstable/bsb_native.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,11 @@ val sort_via_array :
22892289
('a -> 'a -> int) ->
22902290
'a list
22912291

2292+
val sort_via_arrayf:
2293+
'a list ->
2294+
('a -> 'a -> int) ->
2295+
('a -> 'b ) ->
2296+
'b list
22922297

22932298

22942299

@@ -3030,7 +3035,10 @@ let sort_via_array lst cmp =
30303035
Array.sort cmp arr;
30313036
Array.to_list arr
30323037

3033-
3038+
let sort_via_arrayf lst cmp f =
3039+
let arr = Array.of_list lst in
3040+
Array.sort cmp arr;
3041+
Ext_array.to_list_f arr f
30343042

30353043

30363044
let rec assoc_by_string lst (k : string) def =

0 commit comments

Comments
 (0)