Skip to content

Commit dfe959f

Browse files
authored
Merge pull request #1918 from BuckleScript/improve_part_of_the_pattern_match
[code gen] improve the pattern match
2 parents ce3b925 + 8a04464 commit dfe959f

15 files changed

+564
-270
lines changed

jscomp/bin/whole_compiler.ml

Lines changed: 207 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -70661,13 +70661,13 @@ module Js_analyzer : sig
7066170661
(** Analyzing utilities for [J] module *)
7066270662

7066370663
(** for example, whether it has side effect or not.
70664-
*)
70664+
*)
7066570665

7066670666
val free_variables_of_statement :
70667-
Ident_set.t -> Ident_set.t -> J.statement -> Ident_set.t
70667+
Ident_set.t -> Ident_set.t -> J.statement -> Ident_set.t
7066870668

7066970669
val free_variables_of_expression :
70670-
Ident_set.t -> Ident_set.t -> J.finish_ident_expression -> Ident_set.t
70670+
Ident_set.t -> Ident_set.t -> J.finish_ident_expression -> Ident_set.t
7067170671

7067270672
val no_side_effect_expression_desc :
7067370673
J.expression_desc -> bool
@@ -70680,21 +70680,23 @@ val no_side_effect_expression :
7068070680
when you want to do a deep copy, the expression passed to you is pure
7068170681
but you still have to call the function to make a copy,
7068270682
since it maybe changed later
70683-
*)
70683+
*)
7068470684

7068570685
val no_side_effect_statement :
70686-
J.statement -> bool
70686+
J.statement -> bool
7068770687
(**
7068870688
here we say
70689-
{[ var x = no_side_effect_expression ]}
70689+
{[ var x = no_side_effect_expression ]}
7069070690
is [no side effect], but it is actually side effect,
7069170691
since we are defining a variable, however, if it is not exported or used,
7069270692
then it's fine, so we delay this check later
70693-
*)
70693+
*)
7069470694

70695-
val eq_expression : J.expression -> J.expression -> bool
70695+
val eq_expression :
70696+
J.expression -> J.expression -> bool
7069670697

70697-
val eq_statement : J.statement -> J.statement -> bool
70698+
val eq_statement :
70699+
J.statement -> J.statement -> bool
7069870700

7069970701
val rev_flatten_seq : J.expression -> J.block
7070070702

@@ -70709,7 +70711,7 @@ val is_constant : J.expression -> bool
7070970711
*)
7071070712

7071170713
val is_simple_no_side_effect_expression
70712-
: J.expression -> bool
70714+
: J.expression -> bool
7071370715
end = struct
7071470716
#1 "js_analyzer.ml"
7071570717
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
@@ -70751,7 +70753,7 @@ end = struct
7075170753

7075270754
Note such shaking is done in the toplevel, so that it requires us to
7075370755
flatten the statement first
70754-
*)
70756+
*)
7075570757
let free_variables used_idents defined_idents =
7075670758
object (self)
7075770759
inherit Js_fold.fold as super
@@ -70772,9 +70774,9 @@ let free_variables used_idents defined_idents =
7077270774

7077370775
match exp.expression_desc with
7077470776
| Fun(_, _,_, env)
70775-
(** a optimization to avoid walking into funciton again
70776-
if it's already comuted
70777-
*)
70777+
(** a optimization to avoid walking into funciton again
70778+
if it's already comuted
70779+
*)
7077870780
->
7077970781
{< used_idents =
7078070782
Ident_set.union (Js_fun_env.get_unbounded env) used_idents >}
@@ -70808,12 +70810,12 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) =
7080870810
| Array (xs,_mutable_flag)
7080970811
| Caml_block (xs, _mutable_flag, _, _)
7081070812
->
70811-
(** create [immutable] block,
70812-
does not really mean that this opreation itself is [pure].
70813-
70814-
the block is mutable does not mean this operation is non-pure
70815-
*)
70816-
List.for_all no_side_effect xs
70813+
(** create [immutable] block,
70814+
does not really mean that this opreation itself is [pure].
70815+
70816+
the block is mutable does not mean this operation is non-pure
70817+
*)
70818+
List.for_all no_side_effect xs
7081770819
| Bind(fn, obj) -> no_side_effect fn && no_side_effect obj
7081870820
| Object kvs ->
7081970821
List.for_all (fun (_property_name, y) -> no_side_effect y ) kvs
@@ -70865,53 +70867,157 @@ let no_side_effect init =
7086570867

7086670868
method! statement s =
7086770869
if not no_side_effect then self else
70868-
match s.statement_desc with
70869-
| Throw _
70870-
| Debugger
70871-
| Break
70872-
| Variable _
70873-
| Continue _ ->
70874-
{< no_side_effect = false>}
70875-
| Exp e -> self#expression e
70876-
| Int_switch _ | String_switch _ | ForRange _
70877-
| If _ | While _ | Block _ | Return _ | Try _ -> super#statement s
70870+
match s.statement_desc with
70871+
| Throw _
70872+
| Debugger
70873+
| Break
70874+
| Variable _
70875+
| Continue _ ->
70876+
{< no_side_effect = false>}
70877+
| Exp e -> self#expression e
70878+
| Int_switch _ | String_switch _ | ForRange _
70879+
| If _ | While _ | Block _ | Return _ | Try _ -> super#statement s
7087870880
method! list f x =
7087970881
if not self#get_no_side_effect then self else super#list f x
7088070882
method! expression s =
7088170883
if not no_side_effect then self
7088270884
else {< no_side_effect = no_side_effect_expression s >}
7088370885

70884-
(** only expression would cause side effec *)
70886+
(** only expression would cause side effec *)
7088570887
end
7088670888
let no_side_effect_statement st = ((no_side_effect true)#statement st)#get_no_side_effect
7088770889

7088870890
(* TODO: generate [fold2]
7088970891
This make sense, for example:
7089070892
{[
70891-
let string_of_formatting_gen : type a b c d e f .
70892-
(a, b, c, d, e, f) formatting_gen -> string =
70893-
fun formatting_gen -> match formatting_gen with
70894-
| Open_tag (Format (_, str)) -> str
70895-
| Open_box (Format (_, str)) -> str
70893+
let string_of_formatting_gen : type a b c d e f .
70894+
(a, b, c, d, e, f) formatting_gen -> string =
70895+
fun formatting_gen -> match formatting_gen with
70896+
| Open_tag (Format (_, str)) -> str
70897+
| Open_box (Format (_, str)) -> str
7089670898

7089770899
]}
70898-
*)
70899-
let rec eq_expression (x : J.expression) (y : J.expression) =
70900-
match x.expression_desc, y.expression_desc with
70901-
| Number (Int i) , Number (Int j) -> i = j
70902-
| Number (Float i), Number (Float j) -> false (* TODO *)
70903-
| Math (name00,args00), Math(name10,args10) ->
70904-
name00 = name10 && eq_expression_list args00 args10
70905-
| Access (a0,a1), Access(b0,b1) ->
70906-
eq_expression a0 b0 && eq_expression a1 b1
70907-
| Call (a0,args00,_), Call(b0,args10,_) ->
70908-
eq_expression a0 b0 && eq_expression_list args00 args10
70909-
| Var (Id i), Var (Id j) ->
70910-
Ident.same i j
70911-
| Bin (op0, a0,b0) , Bin(op1,a1,b1) ->
70912-
op0 = op1 && eq_expression a0 a1 && eq_expression b0 b1
70913-
| _, _ -> false
70914-
70900+
*)
70901+
let rec eq_expression
70902+
({expression_desc = x0} : J.expression)
70903+
({expression_desc = y0} : J.expression) =
70904+
begin match x0 with
70905+
| Number (Int i) ->
70906+
begin match y0 with
70907+
| Number (Int j) -> i = j
70908+
| _ -> false
70909+
end
70910+
| Number (Float i) ->
70911+
begin match y0 with
70912+
| Number (Float j) ->
70913+
false (* conservative *)
70914+
| _ -> false
70915+
end
70916+
| Math (name00,args00) ->
70917+
begin match y0 with
70918+
|Math(name10,args10) ->
70919+
name00 = name10 && eq_expression_list args00 args10
70920+
| _ -> false
70921+
end
70922+
| Access (a0,a1) ->
70923+
begin match y0 with
70924+
| Access(b0,b1) ->
70925+
eq_expression a0 b0 && eq_expression a1 b1
70926+
| _ -> false
70927+
end
70928+
| Call (a0,args00,_) ->
70929+
begin match y0 with
70930+
| Call(b0,args10,_) ->
70931+
eq_expression a0 b0 && eq_expression_list args00 args10
70932+
| _ -> false
70933+
end
70934+
| Var (Id i) ->
70935+
begin match y0 with
70936+
| Var (Id j) ->
70937+
Ident.same i j
70938+
| _ -> false
70939+
end
70940+
| Bin (op0, a0,b0) ->
70941+
begin match y0 with
70942+
| Bin(op1,a1,b1) ->
70943+
op0 = op1 && eq_expression a0 a1 && eq_expression b0 b1
70944+
| _ -> false
70945+
end
70946+
| Str(a0,b0) ->
70947+
begin match y0 with
70948+
| Str(a1,b1) -> a0 = a1 && b0 = b1
70949+
| _ -> false
70950+
end
70951+
| Var (Qualified (id0,k0,opts0)) ->
70952+
begin match y0 with
70953+
| Var (Qualified (id1,k1,opts1)) ->
70954+
Ident.same id0 id1 &&
70955+
k0 = k1 &&
70956+
opts0 = opts1
70957+
| _ -> false
70958+
end
70959+
| Dot (e0,p0,b0) ->
70960+
begin match y0 with
70961+
| Dot(e1,p1,b1) ->
70962+
p0 = p1 && b0 = b1 && eq_expression e0 e1
70963+
| _ -> false
70964+
end
70965+
| Dump (l0,es0) ->
70966+
begin match y0 with
70967+
| Dump(l1,es1) ->
70968+
l0 = l1 && eq_expression_list es0 es1
70969+
| _ -> false
70970+
end
70971+
| Seq (a0,b0) ->
70972+
begin match y0 with
70973+
| Seq(a1,b1) ->
70974+
eq_expression a0 a1 && eq_expression b0 b1
70975+
| _ -> false
70976+
end
70977+
| Bool a0 ->
70978+
begin match y0 with
70979+
| Bool b0 -> a0 = b0
70980+
| _ -> false
70981+
end
70982+
| Length _
70983+
| Char_of_int _
70984+
| Char_to_int _
70985+
| Is_null_undefined_to_boolean _
70986+
| Array_of_size _
70987+
| Array_copy _
70988+
| Array_append _
70989+
| String_append _
70990+
| Int_of_boolean _
70991+
| Anything_to_number _
70992+
70993+
| Typeof _
70994+
| Caml_not _
70995+
| Js_not _
70996+
| String_of_small_int_array _
70997+
| Json_stringify _
70998+
| Anything_to_string _
70999+
71000+
71001+
| Cond _
71002+
| FlatCall _
71003+
| Bind _
71004+
| String_access _
71005+
71006+
| New _
71007+
| Fun _
71008+
| Unicode _
71009+
| Raw_js_code _
71010+
| Array _
71011+
| Caml_block _
71012+
| Caml_uninitialized_obj _
71013+
| Caml_block_tag _
71014+
| Caml_block_set_tag _
71015+
| Caml_block_set_length _
71016+
| Object _
71017+
| Number (Uint _ | Nint _)
71018+
71019+
-> false
71020+
end
7091571021
and eq_expression_list xs ys =
7091671022
let rec aux xs ys =
7091771023
match xs,ys with
@@ -70921,13 +71027,49 @@ and eq_expression_list xs ys =
7092171027
| x::xs, y::ys -> eq_expression x y && aux xs ys
7092271028
in
7092371029
aux xs ys
70924-
70925-
and eq_statement (x : J.statement) (y : J.statement) =
70926-
match x.statement_desc, y.statement_desc with
70927-
| Exp a, Exp b
70928-
| Return { return_value = a ; _} , Return { return_value = b; _} ->
70929-
eq_expression a b
70930-
| _, _ ->
71030+
and eq_statement_list xs ys =
71031+
let rec aux xs ys =
71032+
match xs,ys with
71033+
| [], [] -> true
71034+
| [], _ -> false
71035+
| _ , [] -> false
71036+
| x::xs, y::ys -> eq_statement x y && aux xs ys
71037+
in
71038+
aux xs ys
71039+
and eq_statement
71040+
({statement_desc = x0} : J.statement)
71041+
({statement_desc = y0} : J.statement) =
71042+
match x0 with
71043+
| Exp a ->
71044+
begin match y0 with
71045+
| Exp b -> eq_expression a b
71046+
| _ -> false
71047+
end
71048+
| Return { return_value = a ; _} ->
71049+
begin match y0 with
71050+
| Return { return_value = b; _} ->
71051+
eq_expression a b
71052+
| _ -> false
71053+
end
71054+
| Debugger -> y0 = Debugger
71055+
| Break -> y0 = Break
71056+
| Block xs0 ->
71057+
begin match y0 with
71058+
| Block ys0 ->
71059+
eq_statement_list xs0 ys0
71060+
| _ -> false
71061+
end
71062+
| Variable _
71063+
| If _
71064+
| While _
71065+
| ForRange _
71066+
| Continue _
71067+
71068+
| Int_switch _
71069+
| String_switch _
71070+
| Throw _
71071+
| Try _
71072+
->
7093171073
false
7093271074

7093371075
let rev_flatten_seq (x : J.expression) =
@@ -70939,17 +71081,17 @@ let rev_flatten_seq (x : J.expression) =
7093971081

7094071082
(* TODO: optimization,
7094171083
counter the number to know if needed do a loop gain instead of doing a diff
70942-
*)
71084+
*)
7094371085

7094471086
let rev_toplevel_flatten block =
7094571087
let rec aux acc (xs : J.block) : J.block =
7094671088
match xs with
7094771089
| [] -> acc
7094871090
| {statement_desc =
70949-
Variable (
70950-
{ident_info = {used_stats = Dead_pure } ; _}
70951-
| {ident_info = {used_stats = Dead_non_pure}; value = None })
70952-
} :: xs -> aux acc xs
71091+
Variable (
71092+
{ident_info = {used_stats = Dead_pure } ; _}
71093+
| {ident_info = {used_stats = Dead_non_pure}; value = None })
71094+
} :: xs -> aux acc xs
7095371095
| {statement_desc = Block b; _ } ::xs -> aux (aux acc b ) xs
7095471096

7095571097
| x :: xs -> aux (x :: acc) xs in

0 commit comments

Comments
 (0)