Skip to content

Commit c825694

Browse files
committed
Heuristic for pattern matching untagged variants.
1 parent 1313bb8 commit c825694

7 files changed

+100
-46
lines changed

compiler/ml/ast_untagged_variants.ml

+16-6
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,22 @@ module DynamicChecks = struct
458458
Ext_list.fold_right others is_literal_1 (fun literal_n acc ->
459459
is_literal_case literal_n ||| acc))
460460
in
461-
match block_cases with
462-
| [c] -> is_not_block_case c
463-
| c1 :: (_ :: _ as rest) ->
464-
is_not_block_case c1
465-
&&& is_a_literal_case ~literal_cases ~block_cases:rest e
466-
| [] -> assert false
461+
let list_literal_cases = true in
462+
if list_literal_cases then
463+
let rec mk cases =
464+
match cases with
465+
| [case] -> is_literal_case case
466+
| case :: rest -> is_literal_case case ||| mk rest
467+
| [] -> assert false
468+
in
469+
mk literal_cases
470+
else
471+
match block_cases with
472+
| [c] -> is_not_block_case c
473+
| c1 :: (_ :: _ as rest) ->
474+
is_not_block_case c1
475+
&&& is_a_literal_case ~literal_cases ~block_cases:rest e
476+
| [] -> assert false
467477

468478
let is_int_tag ?(has_null_undefined_other = (false, false, false)) (e : _ t) :
469479
_ t =

tests/tests/src/UntaggedVariants.mjs

+25-25
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as Primitive_array from "rescript/lib/es6/Primitive_array.js";
66
import * as Primitive_option from "rescript/lib/es6/Primitive_option.js";
77

88
function classify(x) {
9-
if (x === "A" && typeof x !== "number") {
9+
if (x === "A") {
1010
return "A";
1111
} else if (typeof x === "number") {
1212
return "An integer";
@@ -24,7 +24,7 @@ function classify2(x) {
2424
}
2525

2626
function cls(x) {
27-
if (typeof x !== "object") {
27+
if (x === "Two" || x === "One") {
2828
if (x === "One") {
2929
return "one";
3030
} else {
@@ -40,13 +40,13 @@ let ListWithTuples = {};
4040
let ListWithObjects = {};
4141

4242
function tuplesToObjects(l) {
43-
if (Array.isArray(l)) {
43+
if (l === undefined) {
44+
return null;
45+
} else {
4446
return {
4547
hd: l[0],
4648
tl: tuplesToObjects(l[1])
4749
};
48-
} else {
49-
return null;
5050
}
5151
}
5252

@@ -68,7 +68,7 @@ console.log("l1", l1);
6868
console.log("l2", l2);
6969

7070
function isTrue(x) {
71-
if (typeof x !== "object") {
71+
if (x === true) {
7272
return true;
7373
} else {
7474
return x.flag;
@@ -80,7 +80,7 @@ let Truthy = {
8080
};
8181

8282
function classify$1(x) {
83-
if (x === null || typeof x !== "object") {
83+
if (x === undefined || x === null) {
8484
if (x === null) {
8585
return "null";
8686
} else {
@@ -96,7 +96,7 @@ let TwoObjects = {
9696
};
9797

9898
function classify$2(x) {
99-
if (x === "A" || x === "B") {
99+
if (x === "B" || x === "A") {
100100
if (x === "A") {
101101
return "a";
102102
} else {
@@ -112,7 +112,7 @@ let Unknown = {
112112
};
113113

114114
function classify$3(x) {
115-
if (typeof x !== "object" && typeof x !== "number" && (x === "C" || x === "B" || x === "A" || x === "D")) {
115+
if (x === "D" || x === "C" || x === "B" || x === "A") {
116116
switch (x) {
117117
case "A" :
118118
return "a";
@@ -173,7 +173,7 @@ let WithArray = {
173173
};
174174

175175
function classify$6(x) {
176-
if (!Array.isArray(x) && (x === null || typeof x !== "object") && typeof x !== "number" && typeof x !== "string") {
176+
if (x === null || x === true || x === false) {
177177
switch (x) {
178178
case false :
179179
return "JSONFalse";
@@ -214,18 +214,18 @@ let Json = {
214214
};
215215

216216
function check(s, y) {
217-
if (!Array.isArray(s)) {
217+
if (s === "B") {
218218
return 42;
219219
}
220220
let x = s[0];
221-
if (!Array.isArray(x)) {
221+
if (x === "B") {
222222
return 42;
223223
}
224224
let tmp = s[1];
225-
if (Array.isArray(tmp) || x === y) {
226-
return 42;
227-
} else {
225+
if (tmp === "B" && x !== y) {
228226
return 41;
227+
} else {
228+
return 42;
229229
}
230230
}
231231

@@ -234,7 +234,7 @@ let TrickyNested = {
234234
};
235235

236236
function checkEnum(e) {
237-
if (!(e === "Two" || e === "One" || e === "Three")) {
237+
if (!(e === "Three" || e === "Two" || e === "One")) {
238238
return "Something else..." + e;
239239
}
240240
switch (e) {
@@ -252,7 +252,7 @@ let OverlapString = {
252252
};
253253

254254
function checkEnum$1(e) {
255-
if (!(e === "Two" || e === 1.0 || e === "Three")) {
255+
if (!(e === "Three" || e === "Two" || e === 1.0)) {
256256
return "Something else...";
257257
}
258258
switch (e) {
@@ -270,7 +270,7 @@ let OverlapNumber = {
270270
};
271271

272272
function checkEnum$2(e) {
273-
if (!(e === null || typeof e !== "object")) {
273+
if (!(e === "Three" || e === "Two" || e === null)) {
274274
return "Object...";
275275
}
276276
switch (e) {
@@ -376,7 +376,7 @@ let TestFunctionCase = {
376376
let someJson = '[{"name": "Haan"}, {"name": "Mr"}, false]';
377377

378378
function check$1(s) {
379-
if (!Array.isArray(s) && (s === null || typeof s !== "object") && typeof s !== "number" && typeof s !== "string") {
379+
if (s === null || s === true || s === false || s === undefined) {
380380
console.log("Nope...");
381381
return;
382382
}
@@ -386,11 +386,11 @@ function check$1(s) {
386386
return;
387387
}
388388
let match = s[0];
389-
if (match === true) {
389+
if ((match === null || match === true || match === false || match === undefined) && match === true) {
390390
let match$1 = s[1];
391-
if (match$1 === false) {
391+
if ((match$1 === null || match$1 === true || match$1 === false || match$1 === undefined) && match$1 === false) {
392392
let match$2 = s[2];
393-
if (!Array.isArray(match$2) && (match$2 === null || typeof match$2 !== "object") && typeof match$2 !== "number" && typeof match$2 !== "string") {
393+
if (match$2 === null || match$2 === true || match$2 === false || match$2 === undefined) {
394394
console.log("Nope...");
395395
return;
396396
}
@@ -400,13 +400,13 @@ function check$1(s) {
400400
return;
401401
}
402402
let match$3 = match$2[0];
403-
if (!Array.isArray(match$3) && (match$3 === null || typeof match$3 !== "object") && typeof match$3 !== "number" && typeof match$3 !== "string") {
403+
if (match$3 === null || match$3 === true || match$3 === false || match$3 === undefined) {
404404
console.log("Nope...");
405405
return;
406406
}
407407
if (typeof match$3 === "string" && match$3 === "My name is") {
408408
let match$4 = match$2[1];
409-
if (!Array.isArray(match$4) && (match$4 === null || typeof match$4 !== "object") && typeof match$4 !== "number" && typeof match$4 !== "string") {
409+
if (match$4 === null || match$4 === true || match$4 === false || match$4 === undefined) {
410410
console.log("Nope...");
411411
return;
412412
}
@@ -476,7 +476,7 @@ let PromiseSync = {
476476
};
477477

478478
async function classify$10(a) {
479-
if (typeof a !== "object" && !(a instanceof Promise) && (a === "test" || a === 12) && !Array.isArray(a)) {
479+
if (a === 12 || a === "test") {
480480
if (a === "test") {
481481
console.log("testing");
482482
return;

tests/tests/src/core/Core_JsonTests.mjs

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import * as Test from "./Test.mjs";
55
function decodeJsonTest() {
66
let json = {"someProp":{"otherProp": null, "thirdProp": [true, false]}};
77
let decodedCorrectly;
8-
if (!Array.isArray(json) && (json === null || typeof json !== "object") && typeof json !== "number" && typeof json !== "string" && typeof json !== "boolean" || !(typeof json === "object" && !Array.isArray(json))) {
8+
if (json === null || !(typeof json === "object" && !Array.isArray(json))) {
99
decodedCorrectly = false;
1010
} else {
1111
let match = json["someProp"];
12-
if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !(typeof match === "object" && !Array.isArray(match)))) {
12+
if (match !== undefined && !(match === null || !(typeof match === "object" && !Array.isArray(match)))) {
1313
let match$1 = match["thirdProp"];
14-
if (match$1 !== undefined && !(!Array.isArray(match$1) && (match$1 === null || typeof match$1 !== "object") && typeof match$1 !== "number" && typeof match$1 !== "string" && typeof match$1 !== "boolean" || !(Array.isArray(match$1) && match$1.length === 2))) {
14+
if (match$1 !== undefined && !(match$1 === null || !(Array.isArray(match$1) && match$1.length === 2))) {
1515
let match$2 = match$1[0];
16-
if (!Array.isArray(match$2) && (match$2 === null || typeof match$2 !== "object") && typeof match$2 !== "number" && typeof match$2 !== "string" && typeof match$2 !== "boolean" || !(typeof match$2 === "boolean" && match$2)) {
16+
if (match$2 === null || !(typeof match$2 === "boolean" && match$2)) {
1717
decodedCorrectly = false;
1818
} else {
1919
let match$3 = match$1[1];
20-
decodedCorrectly = !Array.isArray(match$3) && (match$3 === null || typeof match$3 !== "object") && typeof match$3 !== "number" && typeof match$3 !== "string" && typeof match$3 !== "boolean" || !(typeof match$3 === "boolean" && !match$3) ? false : true;
20+
decodedCorrectly = match$3 === null || !(typeof match$3 === "boolean" && !match$3) ? false : true;
2121
}
2222
} else {
2323
decodedCorrectly = false;

tests/tests/src/core/Core_NullableTests.mjs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function shouldHandleNullableValues() {
77
let tUndefined = undefined;
88
let tValue = "hello";
99
let tmp;
10-
tmp = (tNull === null || tNull === undefined) && tNull === null ? true : false;
10+
tmp = (tNull === undefined || tNull === null) && tNull === null ? true : false;
1111
Test.run([
1212
[
1313
"Core_NullableTests.res",
@@ -18,7 +18,7 @@ function shouldHandleNullableValues() {
1818
"Should handle null"
1919
], tmp, (prim0, prim1) => prim0 === prim1, true);
2020
let tmp$1;
21-
tmp$1 = (tUndefined === null || tUndefined === undefined) && tUndefined !== null ? true : false;
21+
tmp$1 = (tUndefined === undefined || tUndefined === null) && tUndefined !== null ? true : false;
2222
Test.run([
2323
[
2424
"Core_NullableTests.res",
@@ -29,7 +29,7 @@ function shouldHandleNullableValues() {
2929
"Should handle undefined"
3030
], tmp$1, (prim0, prim1) => prim0 === prim1, true);
3131
let tmp$2;
32-
tmp$2 = tValue === null || tValue === undefined || tValue !== "hello" ? false : true;
32+
tmp$2 = tValue === undefined || tValue === null || tValue !== "hello" ? false : true;
3333
Test.run([
3434
[
3535
"Core_NullableTests.res",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
4+
function f(x) {
5+
if (x !== null) {
6+
return;
7+
}
8+
console.log("abc");
9+
}
10+
11+
function ff(x) {
12+
if (x === "G" || x === "F" || x === "E" || x === "D" || x === "C" || x === "B" || x === "A") {
13+
return;
14+
}
15+
console.log("abc");
16+
}
17+
18+
export {
19+
f,
20+
ff,
21+
}
22+
/* No side effect */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let f = (x: JSON.t) =>
2+
switch x {
3+
| Null => Console.log("abc")
4+
| _ => ()
5+
}
6+
7+
@unboxed
8+
type t =
9+
| A
10+
| B
11+
| C
12+
| D
13+
| E
14+
| F
15+
| G
16+
| Int(int)
17+
18+
let ff = (x: t) =>
19+
switch x {
20+
| Int(_) => Console.log("abc")
21+
| _ => ()
22+
}

tests/tests/src/variantsMatching.mjs

+7-7
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,17 @@ function isUndefined$1(x) {
224224
}
225225

226226
function plus$2(x, y) {
227-
if (x === null || x === undefined) {
227+
if (x === undefined || x === null) {
228228
return y;
229-
} else if (y === null || y === undefined) {
229+
} else if (y === undefined || y === null) {
230230
return x;
231231
} else {
232232
return x + y | 0;
233233
}
234234
}
235235

236236
function kind(x) {
237-
if (x === null || x === undefined) {
237+
if (x === undefined || x === null) {
238238
if (x === null) {
239239
return "null";
240240
} else {
@@ -274,21 +274,21 @@ function isWhyNot(x) {
274274
}
275275

276276
function plus$3(x, y) {
277-
if (x === undefined || x === null || x === "WhyNotAnotherOne") {
277+
if (x === "WhyNotAnotherOne" || x === undefined || x === null) {
278278
switch (x) {
279279
case null :
280280
case undefined :
281281
return y;
282282
case "WhyNotAnotherOne" :
283283
break;
284284
}
285-
} else if (!(y === undefined || y === null || y === "WhyNotAnotherOne")) {
285+
} else if (!(y === "WhyNotAnotherOne" || y === undefined || y === null)) {
286286
return {
287287
x: x.x + y.x,
288288
y: x.y + y.y
289289
};
290290
}
291-
if (!(y === undefined || y === null || y === "WhyNotAnotherOne")) {
291+
if (!(y === "WhyNotAnotherOne" || y === undefined || y === null)) {
292292
return "WhyNotAnotherOne";
293293
}
294294
switch (y) {
@@ -301,7 +301,7 @@ function plus$3(x, y) {
301301
}
302302

303303
function kind$1(x) {
304-
if (!(x === undefined || x === null || x === "WhyNotAnotherOne")) {
304+
if (!(x === "WhyNotAnotherOne" || x === undefined || x === null)) {
305305
return "present";
306306
}
307307
switch (x) {

0 commit comments

Comments
 (0)