Skip to content

Commit 4442de4

Browse files
committed
Merge pull request #57 from bloomberg/complex_if
FIX #55, simplify if expression compilation
2 parents 695c5c3 + 74898de commit 4442de4

File tree

13 files changed

+204
-196
lines changed

13 files changed

+204
-196
lines changed

jscomp/js_helper.ml

Lines changed: 153 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -177,41 +177,6 @@ module Exp = struct
177177
| _ ->
178178
{expression_desc = Seq(e0,e1); comment}
179179

180-
let rec econd ?comment (b : t) (t : t) (f : t) : t =
181-
match b.expression_desc , t.expression_desc, f.expression_desc with
182-
| Number ((Int { i = 0; _}) ), _, _
183-
-> f (* TODO: constant folding: could be refined *)
184-
| (Number _ | Array _), _, _
185-
-> t (* a block can not be false in OCAML, CF - relies on flow inference*)
186-
187-
| ((Bin ((EqEqEq, {expression_desc = Number (Int { i = 0; _}); _},x))
188-
| Bin (EqEqEq, x,{expression_desc = Number (Int { i = 0; _});_}))), _, _
189-
->
190-
econd ?comment x f t
191-
192-
| (Bin (Ge,
193-
({expression_desc =
194-
(String_length _
195-
| Array_length _ | Bytes_length _ | Function_length _ );
196-
_}), {expression_desc = Number (Int { i = 0 ; _})})), _, _
197-
-> f
198-
199-
| (Bin (Gt,
200-
({expression_desc =
201-
(String_length _
202-
| Array_length _ | Bytes_length _ | Function_length _ );
203-
_} as pred ), {expression_desc = Number (Int {i = 0; })})), _, _
204-
->
205-
(** Add comment when simplified *)
206-
econd ?comment pred t f
207-
| Not e, _, _ -> econd ?comment e f t
208-
| Int_of_boolean b, _, _ -> econd ?comment b t f
209-
210-
| _ ->
211-
if Js_analyzer.eq_expression t f then
212-
if no_side_effect b then t else seq ?comment b t
213-
else
214-
{expression_desc = Cond(b,t,f); comment}
215180

216181
let int ?comment ?c i : t =
217182
{expression_desc = Number (Int {i; c}) ; comment}
@@ -378,6 +343,7 @@ module Exp = struct
378343

379344
let assign ?comment e0 e1 : t = {expression_desc = Bin(Eq, e0,e1); comment}
380345

346+
381347
(** Convert a javascript boolean to ocaml boolean
382348
It's necessary for return value
383349
this should be optmized away for [if] ,[cond] to produce
@@ -411,6 +377,158 @@ module Exp = struct
411377
triple_equal ?comment a b
412378
| _ ->
413379
to_ocaml_boolean {expression_desc = Bin(EqEqEq, e0,e1); comment}
380+
let bin ?comment (op : J.binop) e0 e1 : t =
381+
match op with
382+
| EqEqEq -> triple_equal ?comment e0 e1
383+
| _ -> {expression_desc = Bin(op,e0,e1); comment}
384+
385+
(* TODO: Constant folding, Google Closure will do that?,
386+
Even if Google Clsoure can do that, we will see how it interact with other
387+
optimizations
388+
We wrap all boolean functions here, since OCaml boolean is a
389+
bit different from Javascript, so that we can change it in the future
390+
*)
391+
let rec and_ ?comment (e1 : t) (e2 : t) =
392+
match e1.expression_desc, e2.expression_desc with
393+
| Int_of_boolean e1 , Int_of_boolean e2 ->
394+
and_ ?comment e1 e2
395+
| Int_of_boolean e1 , _ -> and_ ?comment e1 e2
396+
| _, Int_of_boolean e2
397+
-> and_ ?comment e1 e2
398+
(* optimization if [e1 = e2], then and_ e1 e2 -> e2
399+
be careful for side effect
400+
*)
401+
| Var i, Var j when Js_op_util.same_vident i j
402+
->
403+
to_ocaml_boolean e1
404+
| Var i,
405+
(Bin (And, {expression_desc = Var j ; _}, _)
406+
| Bin (And , _, {expression_desc = Var j ; _}))
407+
when Js_op_util.same_vident i j
408+
->
409+
to_ocaml_boolean e2
410+
| _, _ ->
411+
to_ocaml_boolean @@ bin ?comment And e1 e2
412+
413+
let rec or_ ?comment (e1 : t) (e2 : t) =
414+
match e1.expression_desc, e2.expression_desc with
415+
| Int_of_boolean e1 , Int_of_boolean e2
416+
->
417+
or_ ?comment e1 e2
418+
| Int_of_boolean e1 , _ -> or_ ?comment e1 e2
419+
| _, Int_of_boolean e2
420+
-> or_ ?comment e1 e2
421+
| Var i, Var j when Js_op_util.same_vident i j
422+
->
423+
to_ocaml_boolean e1
424+
| Var i,
425+
(Bin (Or, {expression_desc = Var j ; _}, _)
426+
| Bin (Or , _, {expression_desc = Var j ; _}))
427+
when Js_op_util.same_vident i j
428+
-> to_ocaml_boolean e2
429+
| _, _ ->
430+
to_ocaml_boolean @@ bin ?comment Or e1 e2
431+
432+
(* return a value of type boolean *)
433+
(* TODO:
434+
when comparison with Int
435+
it is right that !(x > 3 ) -> x <= 3 *)
436+
let rec not ({expression_desc; comment} as e : t) : t =
437+
match expression_desc with
438+
| Bin(EqEqEq , e0,e1)
439+
-> {expression_desc = Bin(NotEqEq, e0,e1); comment}
440+
| Bin(NotEqEq , e0,e1) -> {expression_desc = Bin(EqEqEq, e0,e1); comment}
441+
442+
(* Note here the compiled js use primtive comparison only
443+
for *primitive types*, so it is safe to do such optimization,
444+
for generic comparison, this does not hold
445+
*)
446+
| Bin(Lt, a, b) -> {e with expression_desc = Bin (Ge,a,b)}
447+
| Bin(Ge,a,b) -> {e with expression_desc = Bin (Lt,a,b)}
448+
| Bin(Le,a,b) -> {e with expression_desc = Bin (Gt,a,b)}
449+
| Bin(Gt,a,b) -> {e with expression_desc = Bin (Le,a,b)}
450+
451+
| Number (Int {i; _}) ->
452+
if i != 0 then false_ else true_
453+
| Int_of_boolean e -> not e
454+
| Not e -> e
455+
| x -> {expression_desc = Not e ; comment = None}
456+
457+
let rec econd ?comment (b : t) (t : t) (f : t) : t =
458+
match b.expression_desc , t.expression_desc, f.expression_desc with
459+
| Number ((Int { i = 0; _}) ), _, _
460+
-> f (* TODO: constant folding: could be refined *)
461+
| (Number _ | Array _), _, _
462+
-> t (* a block can not be false in OCAML, CF - relies on flow inference*)
463+
464+
| ((Bin ((EqEqEq, {expression_desc = Number (Int { i = 0; _}); _},x))
465+
| Bin (EqEqEq, x,{expression_desc = Number (Int { i = 0; _});_}))), _, _
466+
->
467+
econd ?comment x f t
468+
469+
| (Bin (Ge,
470+
({expression_desc =
471+
(String_length _
472+
| Array_length _ | Bytes_length _ | Function_length _ );
473+
_}), {expression_desc = Number (Int { i = 0 ; _})})), _, _
474+
-> f
475+
476+
| (Bin (Gt,
477+
({expression_desc =
478+
(String_length _
479+
| Array_length _ | Bytes_length _ | Function_length _ );
480+
_} as pred ), {expression_desc = Number (Int {i = 0; })})), _, _
481+
->
482+
(** Add comment when simplified *)
483+
econd ?comment pred t f
484+
485+
| _, (Cond (p1, branch_code0, branch_code1)), _
486+
when Js_analyzer.eq_expression branch_code1 f
487+
->
488+
(* {[
489+
if b then (if p1 then branch_code0 else branch_code1)
490+
else branch_code1
491+
]}
492+
is equivalent to
493+
{[
494+
if b && p1 then branch_code0 else branch_code1
495+
]}
496+
*)
497+
econd (and_ b p1) branch_code0 f
498+
| _, (Cond (p1, branch_code0, branch_code1)), _
499+
when Js_analyzer.eq_expression branch_code0 f
500+
->
501+
(* the same as above except we revert the [cond] expression *)
502+
econd (and_ b (not p1)) branch_code1 f
503+
504+
| _, _, (Cond (p1', branch_code0, branch_code1))
505+
when Js_analyzer.eq_expression t branch_code0
506+
(*
507+
{[
508+
if b then branch_code0 else (if p1' then branch_code0 else branch_code1)
509+
]}
510+
is equivalent to
511+
{[
512+
if b or p1' then branch_code0 else branch_code1
513+
]}
514+
*)
515+
->
516+
econd (or_ b p1') t branch_code1
517+
| _, _, (Cond (p1', branch_code0, branch_code1))
518+
when Js_analyzer.eq_expression t branch_code1
519+
->
520+
(* the same as above except we revert the [cond] expression *)
521+
econd (or_ b (not p1')) t branch_code0
522+
523+
| Not e, _, _ -> econd ?comment e f t
524+
| Int_of_boolean b, _, _ -> econd ?comment b t f
525+
526+
| _ ->
527+
if Js_analyzer.eq_expression t f then
528+
if no_side_effect b then t else seq ?comment b t
529+
else
530+
{expression_desc = Cond(b,t,f); comment}
531+
414532

415533
let rec float_equal ?comment (e0 : t) (e1 : t) : t =
416534
match e0.expression_desc, e1.expression_desc with
@@ -429,10 +547,6 @@ module Exp = struct
429547
->
430548
to_ocaml_boolean {expression_desc = Bin(EqEqEq, e0,e1); comment}
431549

432-
let bin ?comment (op : J.binop) e0 e1 : t =
433-
match op with
434-
| EqEqEq -> triple_equal ?comment e0 e1
435-
| _ -> {expression_desc = Bin(op,e0,e1); comment}
436550

437551
let arr ?comment mt es : t =
438552
{expression_desc = Array (es,mt) ; comment}
@@ -462,33 +576,7 @@ module Exp = struct
462576
let is_type_number ?comment (e : t) : t =
463577
string_equal ?comment (typeof e) (str "number")
464578

465-
(* TODO remove this comment ? *)
466-
(* let un ?comment op e : t = {expression_desc = Un(op,e); comment} *)
467-
468-
(* return a value of type boolean *)
469-
(* TODO:
470-
when comparison with Int
471-
it is right that !(x > 3 ) -> x <= 3 *)
472-
let rec not ({expression_desc; comment} as e : t) : t =
473-
match expression_desc with
474-
| Bin(EqEqEq , e0,e1)
475-
-> {expression_desc = Bin(NotEqEq, e0,e1); comment}
476-
| Bin(NotEqEq , e0,e1) -> {expression_desc = Bin(EqEqEq, e0,e1); comment}
477-
478-
(* Note here the compiled js use primtive comparison only
479-
for *primitive types*, so it is safe to do such optimization,
480-
for generic comparison, this does not hold
481-
*)
482-
| Bin(Lt, a, b) -> {e with expression_desc = Bin (Ge,a,b)}
483-
| Bin(Ge,a,b) -> {e with expression_desc = Bin (Lt,a,b)}
484-
| Bin(Le,a,b) -> {e with expression_desc = Bin (Gt,a,b)}
485-
| Bin(Gt,a,b) -> {e with expression_desc = Bin (Le,a,b)}
486579

487-
| Number (Int {i; _}) ->
488-
if i != 0 then false_ else true_
489-
| Int_of_boolean e -> not e
490-
| Not e -> e
491-
| x -> {expression_desc = Not e ; comment = None}
492580

493581
let new_ ?comment e0 args : t =
494582
{ expression_desc = New (e0, Some args ); comment}
@@ -516,52 +604,6 @@ module Exp = struct
516604
| _ -> bin ?comment Plus e (int 1 )
517605

518606

519-
(* TODO: Constant folding, Google Closure will do that?,
520-
Even if Google Clsoure can do that, we will see how it interact with other
521-
optimizations
522-
We wrap all boolean functions here, since OCaml boolean is a
523-
bit different from Javascript, so that we can change it in the future
524-
*)
525-
let rec and_ ?comment (e1 : t) (e2 : t) =
526-
match e1.expression_desc, e2.expression_desc with
527-
| Int_of_boolean e1 , Int_of_boolean e2 ->
528-
and_ ?comment e1 e2
529-
| Int_of_boolean e1 , _ -> and_ ?comment e1 e2
530-
| _, Int_of_boolean e2
531-
-> and_ ?comment e1 e2
532-
(* optimization if [e1 = e2], then and_ e1 e2 -> e2
533-
be careful for side effect
534-
*)
535-
| Var i, Var j when Js_op_util.same_vident i j
536-
->
537-
to_ocaml_boolean e1
538-
| Var i,
539-
(Bin (And, {expression_desc = Var j ; _}, _)
540-
| Bin (And , _, {expression_desc = Var j ; _}))
541-
when Js_op_util.same_vident i j
542-
->
543-
to_ocaml_boolean e2
544-
| _, _ ->
545-
to_ocaml_boolean @@ bin ?comment And e1 e2
546-
547-
let rec or_ ?comment (e1 : t) (e2 : t) =
548-
match e1.expression_desc, e2.expression_desc with
549-
| Int_of_boolean e1 , Int_of_boolean e2
550-
->
551-
or_ ?comment e1 e2
552-
| Int_of_boolean e1 , _ -> or_ ?comment e1 e2
553-
| _, Int_of_boolean e2
554-
-> or_ ?comment e1 e2
555-
| Var i, Var j when Js_op_util.same_vident i j
556-
->
557-
to_ocaml_boolean e1
558-
| Var i,
559-
(Bin (Or, {expression_desc = Var j ; _}, _)
560-
| Bin (Or , _, {expression_desc = Var j ; _}))
561-
when Js_op_util.same_vident i j
562-
-> to_ocaml_boolean e2
563-
| _, _ ->
564-
to_ocaml_boolean @@ bin ?comment Or e1 e2
565607

566608
let string_of_small_int_array ?comment xs : t =
567609
{expression_desc = String_of_small_int_array xs; comment}

jscomp/stdlib/bytes.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,8 @@ function escaped(s) {
197197
var $js;
198198
var exit = 0;
199199
if (c >= 14) {
200-
if (c !== 34) {
201-
if (c !== 92) {
202-
exit = 1;
203-
}
204-
else {
205-
$js = 2;
206-
}
200+
if (c !== 34 && c !== 92) {
201+
exit = 1;
207202
}
208203
else {
209204
$js = 2;

jscomp/stdlib/camlinternalFormat.js

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,31 +2255,23 @@ function fmtty_of_custom(arity, fmtty) {
22552255
}
22562256

22572257
function fmtty_of_padding_fmtty(pad, fmtty) {
2258-
if (typeof pad === "number") {
2258+
if (typeof pad === "number" || !pad[0]) {
22592259
return fmtty;
22602260
}
2261-
else if (pad[0]) {
2261+
else {
22622262
return [
22632263
/* Int_ty */2,
22642264
fmtty
22652265
];
22662266
}
2267-
else {
2268-
return fmtty;
2269-
}
22702267
}
22712268

22722269
function fmtty_of_precision_fmtty(prec, fmtty) {
2273-
if (typeof prec === "number") {
2274-
if (prec !== 0) {
2275-
return [
2276-
/* Int_ty */2,
2277-
fmtty
2278-
];
2279-
}
2280-
else {
2281-
return fmtty;
2282-
}
2270+
if (typeof prec === "number" && prec !== 0) {
2271+
return [
2272+
/* Int_ty */2,
2273+
fmtty
2274+
];
22832275
}
22842276
else {
22852277
return fmtty;
@@ -5884,13 +5876,8 @@ function fmt_ebb_of_string(legacy_behavior, str) {
58845876
prec_used[1] = /* true */1;
58855877
var pad$3;
58865878
var exit$1 = 0;
5887-
if (typeof prec === "number") {
5888-
if (prec !== 0) {
5889-
exit$1 = 9;
5890-
}
5891-
else {
5892-
pad$3 = pad;
5893-
}
5879+
if (typeof prec === "number" && prec === 0) {
5880+
pad$3 = pad;
58945881
}
58955882
else {
58965883
exit$1 = 9;

0 commit comments

Comments
 (0)