Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions compiler/core/js_dump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1348,3 +1348,5 @@ let string_of_expression (e : J.expression) =
let (_ : cxt) = expression ~level:0 Ext_pp_scope.empty f e in
P.flush f ();
Buffer.contents buffer

let () = E.string_of_expression := string_of_expression
78 changes: 65 additions & 13 deletions compiler/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -662,31 +662,43 @@ let bin ?comment (op : J.binop) (e0 : t) (e1 : t) : t =
be careful for side effect
*)

let rec filter_bool (e : t) ~j ~b =
type filter_const = Ctrue | Cnull
let string_of_filter_const = function
| Ctrue -> "Ctrue"
| Cnull -> "Cnull"

let string_of_expression = ref (fun _ -> "")
let debug = false

let rec filter_const (e : t) ~j ~eq ~const =
if debug then
Printf.eprintf "filter_const e:%s eq:%b const:%s\n"
(!string_of_expression e) eq
(string_of_filter_const const);
match e.expression_desc with
| Bin (And, e1, e2) -> (
match (filter_bool e1 ~j ~b, filter_bool e2 ~j ~b) with
match (filter_const e1 ~j ~eq ~const, filter_const e2 ~j ~eq ~const) with
| None, None -> None
| Some e, None | None, Some e -> Some e
| Some e1, Some e2 -> Some {e with expression_desc = Bin (And, e1, e2)})
| Bin (Or, e1, e2) -> (
match (filter_bool e1 ~j ~b, filter_bool e2 ~j ~b) with
match (filter_const e1 ~j ~eq ~const, filter_const e2 ~j ~eq ~const) with
| None, _ | _, None -> None
| Some e1, Some e2 -> Some {e with expression_desc = Bin (Or, e1, e2)})
| Bin (EqEqEq, {expression_desc = Var i}, {expression_desc = Bool b1})
| Bin (EqEqEq, {expression_desc = Bool b1}, {expression_desc = Var i})
when Js_op_util.same_vident i j ->
if b1 = b then None else Some e
when Js_op_util.same_vident i j && const = Ctrue ->
if b1 = eq then None else Some e
| Bin (NotEqEq, {expression_desc = Var i}, {expression_desc = Bool b1})
| Bin (NotEqEq, {expression_desc = Bool b1}, {expression_desc = Var i})
when Js_op_util.same_vident i j ->
if b1 <> b then None else Some e
when Js_op_util.same_vident i j && const = Ctrue ->
if b1 <> eq then None else Some e
| Bin
( NotEqEq,
{expression_desc = Typeof {expression_desc = Var i}},
{expression_desc = Str {txt}} )
when Js_op_util.same_vident i j ->
if txt <> "bool" then None else assert false
{expression_desc = Str {txt = "boolean" | "string"}} )
when Js_op_util.same_vident i j && (const = Ctrue || const = Cnull) ->
None
| Js_not
{
expression_desc =
Expand All @@ -695,7 +707,7 @@ let rec filter_bool (e : t) ~j ~b =
[{expression_desc = Var i}],
_ );
}
when Js_op_util.same_vident i j ->
when Js_op_util.same_vident i j && (const = Ctrue || const = Cnull) ->
None
| _ -> Some e

Expand All @@ -714,8 +726,32 @@ let and_ ?comment (e1 : t) (e2 : t) : t =
)
when Js_op_util.same_vident i j ->
e2
| _, Bin (EqEqEq, {expression_desc = Var j}, {expression_desc = Bool b}) -> (
match filter_bool e1 ~j ~b with
| ( _,
Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Bool b} ) )
| ( Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Bool b} ),
_ ) -> (
match
filter_const e1 ~j ~eq:(if op = EqEqEq then b else not b) ~const:Ctrue
with
| None -> e2
| Some e1 -> {expression_desc = Bin (And, e1, e2); comment})
| ( _,
Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Null} ) )
| ( Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Null} ),
_ ) -> (
match filter_const e1 ~j ~eq:(op = EqEqEq) ~const:Cnull with
| None -> e2
| Some e1 -> {expression_desc = Bin (And, e1, e2); comment})
| _, _ -> {expression_desc = Bin (And, e1, e2); comment}
Expand All @@ -729,6 +765,22 @@ let or_ ?comment (e1 : t) (e2 : t) =
| Var i, Bin (Or, l, ({expression_desc = Var j; _} as r))
when Js_op_util.same_vident i j ->
{e2 with expression_desc = Bin (Or, r, l)}
| ( _,
Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Null} ) ) -> (
match filter_const e1 ~j ~eq:(op <> EqEqEq) ~const:Cnull with
| None -> e2
| Some e1 -> {expression_desc = Bin (Or, e1, e2); comment})
| ( Bin
( ((EqEqEq | NotEqEq) as op),
{expression_desc = Var j},
{expression_desc = Null} ),
_ ) -> (
match filter_const e2 ~j ~eq:(op <> EqEqEq) ~const:Cnull with
| None -> e1
| Some e2 -> {expression_desc = Bin (Or, e1, e2); comment})
| _, _ -> {expression_desc = Bin (Or, e1, e2); comment}

(* return a value of type boolean *)
Expand Down
2 changes: 2 additions & 0 deletions compiler/core/js_exp_make.mli
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,5 @@ val is_null_undefined : ?comment:string -> t -> t
val make_exception : string -> t

val variadic_args : t list -> t list

val string_of_expression : (t -> string) ref
24 changes: 24 additions & 0 deletions tests/tests/src/and_or_simplify.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Generated by ReScript, PLEASE EDIT WITH CARE


function check_null_typeof(x) {
if (x !== null) {
return 4;
} else {
return 3;
}
}

function check_undefined_typeof(x) {
if (typeof x !== "boolean" || x !== undefined) {
return 4;
} else {
return 3;
}
}

export {
check_null_typeof,
check_undefined_typeof,
}
/* No side effect */
14 changes: 14 additions & 0 deletions tests/tests/src/and_or_simplify.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@unboxed
type t = | @as(null) Null | @as(undefined) Undefined | B(bool)

let check_null_typeof = x =>
switch x {
| B(_) if x == Null => 3
| _ => 4
}

let check_undefined_typeof = x =>
switch x {
| B(_) if x == Undefined => 3
| _ => 4
}
Loading