Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

small simplifications #7141

Merged
merged 3 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
- Improve error message when passing an object where a record is expected. https://github.com/rescript-lang/rescript-compiler/pull/7101
- Improve code generation or pattern matching of untagged variants. https://github.com/rescript-lang/rescript-compiler/pull/7128
- Improve negation handling in combination with and/or to simplify generated code (especially coming out of pattern matching). https://github.com/rescript-lang/rescript-compiler/pull/7138
- optimize JavaScript code generation by using x == null checks and improving type-based optimizations for string/number literals. https://github.com/rescript-lang/rescript-compiler/pull/7141


#### :house: Internal
Expand Down
10 changes: 10 additions & 0 deletions compiler/core/js_dump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,16 @@ and expression_desc cxt ~(level : int) f x : cxt =
| Float _ -> "- "
| _ -> "-");
expression ~level:13 cxt f e)
| Bin
( Or,
{expression_desc = Bin (EqEqEq, e1, {expression_desc = Null})},
{expression_desc = Bin (EqEqEq, e2, {expression_desc = Undefined _})} )
| Bin
( Or,
{expression_desc = Bin (EqEqEq, e1, {expression_desc = Undefined _})},
{expression_desc = Bin (EqEqEq, e2, {expression_desc = Null})} )
when e1 = e2 ->
expression_desc cxt ~level:(level : int) f (Is_null_or_undefined e1)
| Bin (op, e1, e2) ->
let out, lft, rght = Js_op_util.op_prec op in
let need_paren =
Expand Down
87 changes: 71 additions & 16 deletions compiler/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -711,16 +711,20 @@ let rec push_negation (e : t) : t option =

Type check optimizations:
- [(typeof x === "boolean") && (x === true/false)] -> [x === true/false]
- [(typeof x ==="boolean" | "string" | "number") && (x === boolean/null/undefined)] -> [false]
- [(Array.isArray(x)) && (x === boolean/null/undefined)] -> [false]
- [(typeof x === "string") && (x === "abc")] -> [x === "abc"]
- [(typeof x === "number") && (x === 123)] -> [x === 123]
- [(typeof x === "boolean" | "string" | "number") && (x === boolean/null/undefined/123/"hello")] -> [false]
- [(Array.isArray(x)) && (x === boolean/null/undefined/123/"hello")] -> [false]

- [(typeof x === "boolean") && (x !== true/false)] -> unchanged
- [(typeof x === "boolean" | "string" | "number") && (x !== boolean/null/undefined)] -> [typeof x === ...]
- [(Array.isArray(x)) && (x !== boolean/null/undefined)] -> [Array.isArray(x)]
- [(typeof x === "string") && (x !== "abc")] -> unchanged
- [(typeof x === "number") && (x !== 123)] -> unchanged
- [(typeof x === "boolean" | "string" | "number") && (x !== boolean/null/undefined/123/"hello")] -> [typeof x === ...]
- [(Array.isArray(x)) && (x !== boolean/null/undefined/123/"hello")] -> [Array.isArray(x)]

Equality optimizations:
- [e && e] -> [e]
- [(x === boolean/null/undefined) && (x === boolean/null/undefined)] -> [false] (when not equal)
- [(x === boolean/null/undefined/123/"hello") && (x === boolean/null/undefined/123/"hello")] -> [false] (when not equal)

Note: The function preserves the semantics of the original expression while
attempting to reduce it to a simpler form. If no simplification is possible,
Expand Down Expand Up @@ -778,24 +782,51 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
{expression_desc = Str {txt = "boolean"}} ) )
when Js_op_util.same_vident ia ib ->
Some {expression_desc = b; comment = None}
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "string"}} ),
(Bin (EqEqEq, {expression_desc = Var ib}, {expression_desc = Str _}) as s)
)
| ( (Bin (EqEqEq, {expression_desc = Var ib}, {expression_desc = Str _}) as s),
Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "string"}} ) )
when Js_op_util.same_vident ia ib ->
Some {expression_desc = s; comment = None}
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "number"}} ),
(Bin (EqEqEq, {expression_desc = Var ib}, {expression_desc = Number _}) as
i) )
| ( (Bin (EqEqEq, {expression_desc = Var ib}, {expression_desc = Number _}) as
i),
Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "number"}} ) )
when Js_op_util.same_vident ia ib ->
Some {expression_desc = i; comment = None}
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "boolean" | "string" | "number"}} ),
Bin
( EqEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ) )
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ) )
| ( Bin
( EqEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ),
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ),
Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "boolean" | "string" | "number"}} ) )
when Js_op_util.same_vident ia ib ->
(* Note: case boolean / Bool _ is handled above *)
(* Note: cases boolean / Bool _, number / Number _, string / Str _ are handled above *)
Some false_
| ( Call
( {expression_desc = Str {txt = "Array.isArray"}},
Expand All @@ -804,11 +835,11 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
Bin
( EqEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ) )
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ) )
| ( Bin
( EqEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ),
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ),
Call
( {expression_desc = Str {txt = "Array.isArray"}},
[{expression_desc = Var ia}],
Expand All @@ -827,6 +858,30 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
{expression_desc = Str {txt = "boolean"}} ) )
when Js_op_util.same_vident ia ib ->
None
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "string"}} ),
Bin (NotEqEq, {expression_desc = Var ib}, {expression_desc = Str _}) )
| ( Bin (NotEqEq, {expression_desc = Var ib}, {expression_desc = Str _}),
Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "string"}} ) )
when Js_op_util.same_vident ia ib ->
None
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "number"}} ),
Bin (NotEqEq, {expression_desc = Var ib}, {expression_desc = Number _}) )
| ( Bin (NotEqEq, {expression_desc = Var ib}, {expression_desc = Number _}),
Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
{expression_desc = Str {txt = "number"}} ) )
when Js_op_util.same_vident ia ib ->
None
| ( (Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
Expand All @@ -835,7 +890,7 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
Bin
( NotEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ) )
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ) )
| ( Bin
( NotEqEq,
{expression_desc = Var ib},
Expand All @@ -846,7 +901,7 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
{expression_desc = Str {txt = "boolean" | "string" | "number"}} ) as
typeof) )
when Js_op_util.same_vident ia ib ->
(* Note: case boolean / Bool _ is handled above *)
(* Note: cases boolean / Bool _, number / Number _, string / Str _ are handled above *)
Some {expression_desc = typeof; comment = None}
| ( (Call
( {expression_desc = Str {txt = "Array.isArray"}},
Expand All @@ -855,11 +910,11 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
Bin
( NotEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ) )
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ) )
| ( Bin
( NotEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ),
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ),
(Call
( {expression_desc = Str {txt = "Array.isArray"}},
[{expression_desc = Var ia}],
Expand All @@ -870,11 +925,11 @@ let rec simplify_and (e1 : t) (e2 : t) : t option =
| ( Bin
( EqEqEq,
{expression_desc = Var ia},
{expression_desc = Bool _ | Null | Undefined _} ),
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ),
Bin
( EqEqEq,
{expression_desc = Var ib},
{expression_desc = Bool _ | Null | Undefined _} ) )
{expression_desc = Bool _ | Null | Undefined _ | Number _ | Str _} ) )
when Js_op_util.same_vident ia ib ->
(* Note: case x = y is handled above *)
Some false_
Expand Down
4 changes: 2 additions & 2 deletions tests/tests/src/UntaggedVariants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ let Truthy = {
};

function classify$1(x) {
if (x === null || x === undefined) {
if (x == null) {
if (x === null) {
return "null";
} else {
Expand Down Expand Up @@ -404,7 +404,7 @@ function check$1(s) {
console.log("Nope...");
return;
}
if (typeof match$3 === "string" && match$3 === "My name is") {
if (match$3 === "My name is") {
let match$4 = match$2[1];
if (match$4 === undefined || match$4 === null || match$4 === false || match$4 === true) {
console.log("Nope...");
Expand Down
6 changes: 3 additions & 3 deletions tests/tests/src/core/Core_NullableTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function shouldHandleNullableValues() {
let tUndefined = undefined;
let tValue = "hello";
let tmp;
tmp = tNull === null || tNull === undefined ? tNull === null : false;
tmp = (tNull == null) ? tNull === null : false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simplified to tNull === null.

Test.run([
[
"Core_NullableTests.res",
Expand All @@ -18,7 +18,7 @@ function shouldHandleNullableValues() {
"Should handle null"
], tmp, (prim0, prim1) => prim0 === prim1, true);
let tmp$1;
tmp$1 = (tUndefined === null || tUndefined === undefined) && tUndefined !== null;
tmp$1 = (tUndefined == null) && tUndefined !== null;
Copy link
Member

@cknitt cknitt Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simplified to tUndefined === undefined.

Test.run([
[
"Core_NullableTests.res",
Expand All @@ -29,7 +29,7 @@ function shouldHandleNullableValues() {
"Should handle undefined"
], tmp$1, (prim0, prim1) => prim0 === prim1, true);
let tmp$2;
tmp$2 = tValue === null || tValue === undefined ? false : tValue === "hello";
tmp$2 = (tValue == null) ? false : tValue === "hello";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simplified to tValue === "hello".

Test.run([
[
"Core_NullableTests.res",
Expand Down
6 changes: 3 additions & 3 deletions tests/tests/src/variantsMatching.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,17 @@ function isUndefined$1(x) {
}

function plus$2(x, y) {
if (x === null || x === undefined) {
if (x == null) {
return y;
} else if (y === null || y === undefined) {
} else if (y == null) {
return x;
} else {
return x + y | 0;
}
}

function kind(x) {
if (x === null || x === undefined) {
if (x == null) {
if (x === null) {
return "null";
} else {
Expand Down