Skip to content

Commit b7aa403

Browse files
committed
avoid high order semantics for open recursion
the semantics for open recursion with high order function is tricky let's not use it at all code like this `(fun self -> self#hi)` is very hard to reason about
1 parent 0799242 commit b7aa403

File tree

6 files changed

+125
-155
lines changed

6 files changed

+125
-155
lines changed

jscomp/core/js_analyzer.ml

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,32 +139,28 @@ and no_side_effect (x : J.expression) =
139139

140140
let no_side_effect_expression (x : J.expression) = no_side_effect x
141141

142-
let no_side_effect clean : Js_iter.iter =
142+
let no_side_effect_obj : Js_iter.iter =
143143
object (self)
144144
inherit Js_iter.iter as super
145145
method! statement s =
146-
if !clean then
147146
match s.statement_desc with
148147
| Throw _
149148
| Debugger
150149
| Break
151150
| Variable _
152151
| Continue _ ->
153-
clean := false
152+
raise_notrace Not_found
154153
| Exp e -> self#expression e
155154
| Int_switch _ | String_switch _ | ForRange _
156155
| If _ | While _ | Block _ | Return _ | Try _ -> super#statement s
157-
method! list f x =
158-
if !clean then super#list f x
159156
method! expression s =
160-
if !clean then
161-
clean := no_side_effect_expression s
162-
(** only expression would cause side effec *)
157+
if not (no_side_effect_expression s) then raise_notrace Not_found
163158
end
164159
let no_side_effect_statement st =
165-
let clean = ref true in
166-
(no_side_effect clean)#statement st;
167-
!clean
160+
try
161+
no_side_effect_obj#statement st; true
162+
with _ -> false
163+
168164

169165
(* TODO: generate [fold2]
170166
This make sense, for example:

jscomp/core/js_iter.ml

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11

22
open J
33

4-
let option sub = fun v ->
4+
let option sub v =
55
match v with
66
| None -> ()
77
| Some v -> sub v
8-
class iter =
9-
object ((_self : 'self_type))
10-
method list :
11-
'a. ('a -> unit) -> 'a list -> unit =
12-
fun _f_a ->
13-
function
14-
| [] -> ()
15-
| _x :: _x_i1 -> _f_a _x ; _self#list _f_a _x_i1
8+
let rec list sub v =
9+
match v with
10+
| [] -> ()
11+
| x::xs -> sub x ; list sub xs
12+
class iter = object (_self : 'self_type)
1613
method label : label -> unit = ignore
17-
method required_modules : required_modules -> unit = _self#list _self#module_id
14+
method required_modules : required_modules -> unit = (list _self#module_id)
1815
method ident : ident -> unit = ignore
1916
method module_id : module_id -> unit = fun { id = _x0;kind = _x1} -> begin _self#ident _x0 end
2017
method vident : vident -> unit = function
@@ -25,7 +22,7 @@ method vident : vident -> unit = function
2522
method exception_ident : exception_ident -> unit = _self#ident
2623
method for_ident : for_ident -> unit = _self#ident
2724
method for_direction : for_direction -> unit = ignore
28-
method property_map : property_map -> unit = _self#list (fun ( _x0,_x1) -> begin _self#expression _x1 end)
25+
method property_map : property_map -> unit = (list (fun ( _x0,_x1) -> begin _self#expression _x1 end))
2926
method length_object : length_object -> unit = ignore
3027
method expression_desc : expression_desc -> unit = function
3128
| Length ( _x0,_x1) ->
@@ -52,28 +49,28 @@ method expression_desc : expression_desc -> unit = function
5249
|FlatCall ( _x0,_x1) ->
5350
begin _self#expression _x0;_self#expression _x1 end
5451
|Call ( _x0,_x1,_x2) ->
55-
begin _self#expression _x0;_self#list _self#expression _x1 end
52+
begin _self#expression _x0;(list _self#expression) _x1 end
5653
|String_index ( _x0,_x1) ->
5754
begin _self#expression _x0;_self#expression _x1 end
5855
|Array_index ( _x0,_x1) ->
5956
begin _self#expression _x0;_self#expression _x1 end
6057
|Static_index ( _x0,_x1,_x2) ->
6158
begin _self#expression _x0 end
6259
|New ( _x0,_x1) ->
63-
begin _self#expression _x0;option (_self#list _self#expression) _x1 end
60+
begin _self#expression _x0;(option (list _self#expression)) _x1 end
6461
|Var ( _x0) ->
6562
begin _self#vident _x0 end
6663
|Fun ( _x0,_x1,_x2,_x3) ->
67-
begin _self#list _self#ident _x1;_self#block _x2 end
64+
begin (list _self#ident) _x1;_self#block _x2 end
6865
|Str _ -> ()
6966
|Unicode _ -> ()
7067
|Raw_js_code _ -> ()
7168
|Array ( _x0,_x1) ->
72-
begin _self#list _self#expression _x0 end
69+
begin (list _self#expression) _x0 end
7370
|Optional_block ( _x0,_x1) ->
7471
begin _self#expression _x0 end
7572
|Caml_block ( _x0,_x1,_x2,_x3) ->
76-
begin _self#list _self#expression _x0;_self#expression _x2 end
73+
begin (list _self#expression) _x0;_self#expression _x2 end
7774
|Caml_block_tag ( _x0) ->
7875
begin _self#expression _x0 end
7976
|Number _ -> ()
@@ -93,30 +90,30 @@ method statement_desc : statement_desc -> unit = function
9390
|If ( _x0,_x1,_x2) ->
9491
begin _self#expression _x0;_self#block _x1;_self#block _x2 end
9592
|While ( _x0,_x1,_x2,_x3) ->
96-
begin option (_self#label) _x0;_self#expression _x1;_self#block _x2 end
93+
begin (option _self#label) _x0;_self#expression _x1;_self#block _x2 end
9794
|ForRange ( _x0,_x1,_x2,_x3,_x4,_x5) ->
98-
begin option (_self#for_ident_expression) _x0;_self#finish_ident_expression _x1;_self#for_ident _x2;_self#for_direction _x3;_self#block _x4 end
95+
begin (option _self#for_ident_expression) _x0;_self#finish_ident_expression _x1;_self#for_ident _x2;_self#for_direction _x3;_self#block _x4 end
9996
|Continue ( _x0) ->
10097
begin _self#label _x0 end
10198
|Break -> ()
10299
|Return ( _x0) ->
103100
begin _self#expression _x0 end
104101
|Int_switch ( _x0,_x1,_x2) ->
105-
begin _self#expression _x0;_self#list _self#int_clause _x1;option (_self#block) _x2 end
102+
begin _self#expression _x0;(list _self#int_clause) _x1;(option _self#block) _x2 end
106103
|String_switch ( _x0,_x1,_x2) ->
107-
begin _self#expression _x0;_self#list _self#string_clause _x1;option (_self#block) _x2 end
104+
begin _self#expression _x0;(list _self#string_clause) _x1;(option _self#block) _x2 end
108105
|Throw ( _x0) ->
109106
begin _self#expression _x0 end
110107
|Try ( _x0,_x1,_x2) ->
111-
begin _self#block _x0;option ((fun ( _x0,_x1) -> begin _self#exception_ident _x0;_self#block _x1 end)) _x1;option (_self#block) _x2 end
108+
begin _self#block _x0;(option (fun ( _x0,_x1) -> begin _self#exception_ident _x0;_self#block _x1 end)) _x1;(option _self#block) _x2 end
112109
|Debugger -> ()
113110
method expression : expression -> unit = fun { expression_desc = _x0;comment = _x1} -> begin _self#expression_desc _x0 end
114111
method statement : statement -> unit = fun { statement_desc = _x0;comment = _x1} -> begin _self#statement_desc _x0 end
115-
method variable_declaration : variable_declaration -> unit = fun { ident = _x0;value = _x1;property = _x2;ident_info = _x3} -> begin _self#ident _x0;option (_self#expression) _x1 end
112+
method variable_declaration : variable_declaration -> unit = fun { ident = _x0;value = _x1;property = _x2;ident_info = _x3} -> begin _self#ident _x0;(option _self#expression) _x1 end
116113
method string_clause : string_clause -> unit = (fun ( _x0,_x1) -> begin _self#case_clause _x1 end)
117114
method int_clause : int_clause -> unit = (fun ( _x0,_x1) -> begin _self#case_clause _x1 end)
118115
method case_clause : case_clause -> unit = fun { switch_body = _x0;should_break = _x1;comment = _x2} -> begin _self#block _x0 end
119-
method block : block -> unit = _self#list _self#statement
116+
method block : block -> unit = (list _self#statement)
120117
method program : program -> unit = fun { block = _x0;exports = _x1;export_set = _x2} -> begin _self#block _x0 end
121118
method deps_program : deps_program -> unit = fun { program = _x0;modules = _x1;side_effect = _x2} -> begin _self#program _x0;_self#required_modules _x1 end
122119
end

lib/4.06.1/unstable/js_compiler.ml

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -86507,20 +86507,17 @@ module Js_iter
8650786507

8650886508
open J
8650986509

86510-
let option sub = fun v ->
86510+
let option sub v =
8651186511
match v with
8651286512
| None -> ()
8651386513
| Some v -> sub v
86514-
class iter =
86515-
object ((_self : 'self_type))
86516-
method list :
86517-
'a. ('self_type -> 'a -> unit) -> 'a list -> unit =
86518-
fun _f_a ->
86519-
function
86520-
| [] -> ()
86521-
| _x :: _x_i1 -> _f_a _self _x ; _self#list _f_a _x_i1
86514+
let rec list sub v =
86515+
match v with
86516+
| [] -> ()
86517+
| x::xs -> sub x ; list sub xs
86518+
class iter = object (_self : 'self_type)
8652286519
method label : label -> unit = ignore
86523-
method required_modules : required_modules -> unit = _self#list (fun _self -> _self#module_id)
86520+
method required_modules : required_modules -> unit = (list _self#module_id)
8652486521
method ident : ident -> unit = ignore
8652586522
method module_id : module_id -> unit = fun { id = _x0;kind = _x1} -> begin _self#ident _x0 end
8652686523
method vident : vident -> unit = function
@@ -86531,7 +86528,7 @@ method vident : vident -> unit = function
8653186528
method exception_ident : exception_ident -> unit = _self#ident
8653286529
method for_ident : for_ident -> unit = _self#ident
8653386530
method for_direction : for_direction -> unit = ignore
86534-
method property_map : property_map -> unit = _self#list (fun _self -> fun ( _x0,_x1) -> begin _self#expression _x1 end)
86531+
method property_map : property_map -> unit = (list (fun ( _x0,_x1) -> begin _self#expression _x1 end))
8653586532
method length_object : length_object -> unit = ignore
8653686533
method expression_desc : expression_desc -> unit = function
8653786534
| Length ( _x0,_x1) ->
@@ -86558,28 +86555,28 @@ method expression_desc : expression_desc -> unit = function
8655886555
|FlatCall ( _x0,_x1) ->
8655986556
begin _self#expression _x0;_self#expression _x1 end
8656086557
|Call ( _x0,_x1,_x2) ->
86561-
begin _self#expression _x0;_self#list (fun _self -> _self#expression) _x1 end
86558+
begin _self#expression _x0;(list _self#expression) _x1 end
8656286559
|String_index ( _x0,_x1) ->
8656386560
begin _self#expression _x0;_self#expression _x1 end
8656486561
|Array_index ( _x0,_x1) ->
8656586562
begin _self#expression _x0;_self#expression _x1 end
8656686563
|Static_index ( _x0,_x1,_x2) ->
8656786564
begin _self#expression _x0 end
8656886565
|New ( _x0,_x1) ->
86569-
begin _self#expression _x0;option (_self#list (fun _self -> _self#expression)) _x1 end
86566+
begin _self#expression _x0;(option (list _self#expression)) _x1 end
8657086567
|Var ( _x0) ->
8657186568
begin _self#vident _x0 end
8657286569
|Fun ( _x0,_x1,_x2,_x3) ->
86573-
begin _self#list (fun _self -> _self#ident) _x1;_self#block _x2 end
86570+
begin (list _self#ident) _x1;_self#block _x2 end
8657486571
|Str _ -> ()
8657586572
|Unicode _ -> ()
8657686573
|Raw_js_code _ -> ()
8657786574
|Array ( _x0,_x1) ->
86578-
begin _self#list (fun _self -> _self#expression) _x0 end
86575+
begin (list _self#expression) _x0 end
8657986576
|Optional_block ( _x0,_x1) ->
8658086577
begin _self#expression _x0 end
8658186578
|Caml_block ( _x0,_x1,_x2,_x3) ->
86582-
begin _self#list (fun _self -> _self#expression) _x0;_self#expression _x2 end
86579+
begin (list _self#expression) _x0;_self#expression _x2 end
8658386580
|Caml_block_tag ( _x0) ->
8658486581
begin _self#expression _x0 end
8658586582
|Number _ -> ()
@@ -86599,30 +86596,30 @@ method statement_desc : statement_desc -> unit = function
8659986596
|If ( _x0,_x1,_x2) ->
8660086597
begin _self#expression _x0;_self#block _x1;_self#block _x2 end
8660186598
|While ( _x0,_x1,_x2,_x3) ->
86602-
begin option (_self#label) _x0;_self#expression _x1;_self#block _x2 end
86599+
begin (option _self#label) _x0;_self#expression _x1;_self#block _x2 end
8660386600
|ForRange ( _x0,_x1,_x2,_x3,_x4,_x5) ->
86604-
begin option (_self#for_ident_expression) _x0;_self#finish_ident_expression _x1;_self#for_ident _x2;_self#for_direction _x3;_self#block _x4 end
86601+
begin (option _self#for_ident_expression) _x0;_self#finish_ident_expression _x1;_self#for_ident _x2;_self#for_direction _x3;_self#block _x4 end
8660586602
|Continue ( _x0) ->
8660686603
begin _self#label _x0 end
8660786604
|Break -> ()
8660886605
|Return ( _x0) ->
8660986606
begin _self#expression _x0 end
8661086607
|Int_switch ( _x0,_x1,_x2) ->
86611-
begin _self#expression _x0;_self#list (fun _self -> _self#int_clause) _x1;option (_self#block) _x2 end
86608+
begin _self#expression _x0;(list _self#int_clause) _x1;(option _self#block) _x2 end
8661286609
|String_switch ( _x0,_x1,_x2) ->
86613-
begin _self#expression _x0;_self#list (fun _self -> _self#string_clause) _x1;option (_self#block) _x2 end
86610+
begin _self#expression _x0;(list _self#string_clause) _x1;(option _self#block) _x2 end
8661486611
|Throw ( _x0) ->
8661586612
begin _self#expression _x0 end
8661686613
|Try ( _x0,_x1,_x2) ->
86617-
begin _self#block _x0;option (fun ( _x0,_x1) -> begin _self#exception_ident _x0;_self#block _x1 end) _x1;option (_self#block) _x2 end
86614+
begin _self#block _x0;(option (fun ( _x0,_x1) -> begin _self#exception_ident _x0;_self#block _x1 end)) _x1;(option _self#block) _x2 end
8661886615
|Debugger -> ()
8661986616
method expression : expression -> unit = fun { expression_desc = _x0;comment = _x1} -> begin _self#expression_desc _x0 end
8662086617
method statement : statement -> unit = fun { statement_desc = _x0;comment = _x1} -> begin _self#statement_desc _x0 end
86621-
method variable_declaration : variable_declaration -> unit = fun { ident = _x0;value = _x1;property = _x2;ident_info = _x3} -> begin _self#ident _x0;option (_self#expression) _x1 end
86622-
method string_clause : string_clause -> unit = fun ( _x0,_x1) -> begin _self#case_clause _x1 end
86623-
method int_clause : int_clause -> unit = fun ( _x0,_x1) -> begin _self#case_clause _x1 end
86618+
method variable_declaration : variable_declaration -> unit = fun { ident = _x0;value = _x1;property = _x2;ident_info = _x3} -> begin _self#ident _x0;(option _self#expression) _x1 end
86619+
method string_clause : string_clause -> unit = (fun ( _x0,_x1) -> begin _self#case_clause _x1 end)
86620+
method int_clause : int_clause -> unit = (fun ( _x0,_x1) -> begin _self#case_clause _x1 end)
8662486621
method case_clause : case_clause -> unit = fun { switch_body = _x0;should_break = _x1;comment = _x2} -> begin _self#block _x0 end
86625-
method block : block -> unit = _self#list (fun _self -> _self#statement)
86622+
method block : block -> unit = (list _self#statement)
8662686623
method program : program -> unit = fun { block = _x0;exports = _x1;export_set = _x2} -> begin _self#block _x0 end
8662786624
method deps_program : deps_program -> unit = fun { program = _x0;modules = _x1;side_effect = _x2} -> begin _self#program _x0;_self#required_modules _x1 end
8662886625
end
@@ -87065,32 +87062,28 @@ and no_side_effect (x : J.expression) =
8706587062

8706687063
let no_side_effect_expression (x : J.expression) = no_side_effect x
8706787064

87068-
let no_side_effect clean : Js_iter.iter =
87065+
let no_side_effect_obj : Js_iter.iter =
8706987066
object (self)
8707087067
inherit Js_iter.iter as super
8707187068
method! statement s =
87072-
if !clean then
8707387069
match s.statement_desc with
8707487070
| Throw _
8707587071
| Debugger
8707687072
| Break
8707787073
| Variable _
8707887074
| Continue _ ->
87079-
clean := false
87075+
raise_notrace Not_found
8708087076
| Exp e -> self#expression e
8708187077
| Int_switch _ | String_switch _ | ForRange _
8708287078
| If _ | While _ | Block _ | Return _ | Try _ -> super#statement s
87083-
method! list f x =
87084-
if !clean then super#list f x
8708587079
method! expression s =
87086-
if !clean then
87087-
clean := no_side_effect_expression s
87088-
(** only expression would cause side effec *)
87080+
if not (no_side_effect_expression s) then raise_notrace Not_found
8708987081
end
8709087082
let no_side_effect_statement st =
87091-
let clean = ref true in
87092-
(no_side_effect clean)#statement st;
87093-
!clean
87083+
try
87084+
no_side_effect_obj#statement st; true
87085+
with _ -> false
87086+
8709487087

8709587088
(* TODO: generate [fold2]
8709687089
This make sense, for example:

0 commit comments

Comments
 (0)