Skip to content

refactoring object usage, avoid functional objects #4913

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

Merged
merged 16 commits into from
Jan 18, 2021
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
3 changes: 1 addition & 2 deletions jscomp/core/j.ml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
(* Copyright (C) 2015- Authors of ReScript
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -70,7 +70,6 @@ and required_modules = module_id list
currently we always use quote
*)
and property_name = Js_op.property_name
and jsint = int32
and ident = Ident.t
and module_id = {
id : ident; kind : Js_op.kind
Expand Down
74 changes: 40 additions & 34 deletions jscomp/core/js_analyzer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@



type idents_stats = {
mutable used_idents : Set_ident.t ;
mutable defined_idents : Set_ident.t;
}

let add_defined_idents (x : idents_stats) ident =
x.defined_idents <- Set_ident.add x.defined_idents ident

(* Assume that functions already calculated closure correctly
Maybe in the future, we should add a dirty flag, to mark the calcuated
Expand All @@ -38,48 +44,48 @@
Note such shaking is done in the toplevel, so that it requires us to
flatten the statement first
*)
let free_variables used_idents defined_idents =
let free_variables (stats : idents_stats) : Js_fold.fold =
object (self)
inherit Js_fold.fold as super
val defined_idents = defined_idents
val used_idents = used_idents
method! variable_declaration st =
match st with
| { ident; value = None}
add_defined_idents stats st.ident;
match st.value with
| None
-> self
| Some v
->
{< defined_idents = Set_ident.add defined_idents ident >}
| { ident; value = Some v}
->
{< defined_idents = Set_ident.add defined_idents ident >} # expression v
self # expression v
method! ident id =
if Set_ident.mem defined_idents id then self
else {<used_idents = Set_ident.add used_idents id>}
(if not (Set_ident.mem stats.defined_idents id )then
stats.used_idents <- Set_ident.add stats.used_idents id);
self
method! expression exp =

match exp.expression_desc with
| Fun(_, _,_, env)
(** a optimization to avoid walking into funciton again
if it's already comuted
*)
->
{< used_idents =
Set_ident.union (Js_fun_env.get_unbounded env) used_idents >}
stats.used_idents <-
Set_ident.union (Js_fun_env.get_unbounded env) stats.used_idents;
self

| _
->
super#expression exp

method get_depenencies =
Set_ident.diff used_idents defined_idents
method get_used_idents = used_idents
method get_defined_idents = defined_idents
end

let free_variables_of_statement used_idents defined_idents st =
((free_variables used_idents defined_idents)#statement st) # get_depenencies
let free_variables_of_statement st =
let init = {used_idents = Set_ident.empty;
defined_idents = Set_ident.empty} in
let _ = (free_variables init)#statement st in
Set_ident.diff init.used_idents init.defined_idents

let free_variables_of_expression used_idents defined_idents st =
((free_variables used_idents defined_idents)#expression st) # get_depenencies
let free_variables_of_expression st =
let init = {used_idents = Set_ident.empty;
defined_idents = Set_ident.empty} in
let _ = (free_variables init)#expression st in
Set_ident.diff init.used_idents init.defined_idents

let rec no_side_effect_expression_desc (x : J.expression_desc) =
match x with
Expand Down Expand Up @@ -133,33 +139,33 @@ and no_side_effect (x : J.expression) =

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

let no_side_effect init =
let no_side_effect clean : Js_fold.fold =
object (self)
inherit Js_fold.fold as super
val no_side_effect = init
method get_no_side_effect = no_side_effect

method! statement s =
if not no_side_effect then self else
if not !clean then self else
match s.statement_desc with
| Throw _
| Debugger
| Break
| Variable _
| Continue _ ->
{< no_side_effect = false>}
clean := false ; self
| Exp e -> self#expression e
| Int_switch _ | String_switch _ | ForRange _
| If _ | While _ | Block _ | Return _ | Try _ -> super#statement s
method! list f x =
if not self#get_no_side_effect then self else super#list f x
if not !clean then self else super#list f x
method! expression s =
if not no_side_effect then self
else {< no_side_effect = no_side_effect_expression s >}

(if !clean then
clean := no_side_effect_expression s);
self
(** only expression would cause side effec *)
end
let no_side_effect_statement st = ((no_side_effect true)#statement st)#get_no_side_effect
let no_side_effect_statement st =
let clean = ref true in
let _ : Js_fold.fold = ((no_side_effect clean)#statement st) in
!clean

(* TODO: generate [fold2]
This make sense, for example:
Expand Down
4 changes: 2 additions & 2 deletions jscomp/core/js_analyzer.mli
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
*)

val free_variables_of_statement :
Set_ident.t -> Set_ident.t -> J.statement -> Set_ident.t
J.statement -> Set_ident.t

val free_variables_of_expression :
Set_ident.t -> Set_ident.t -> J.finish_ident_expression -> Set_ident.t
J.finish_ident_expression -> Set_ident.t

(* val no_side_effect_expression_desc :
J.expression_desc -> bool *)
Expand Down
1 change: 0 additions & 1 deletion jscomp/core/js_fold.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ method exports : exports -> 'self_type = o#unknown
method tag_info : tag_info -> 'self_type = o#unknown
method required_modules : required_modules -> 'self_type = o#list (fun o -> o#module_id)
method property_name : property_name -> 'self_type = o#unknown
method jsint : jsint -> 'self_type = o#int32
method ident : ident -> 'self_type = o#unknown
method module_id : module_id -> 'self_type = fun { id = _x0;kind = _x1} -> let o = o#ident _x0 in
let o = o#unknown _x1 in o
Expand Down
31 changes: 4 additions & 27 deletions jscomp/core/js_fold_basic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,12 @@



(* class count_deps (add : Ident.t -> unit ) =
object(self)
inherit Js_fold.fold as super
method! expression lam =
match lam.expression_desc with
| Fun (_, _, block, _) -> self#block block
(** Call
actually depends on parameter,
since closure
{[
n = n - 1
acc = () => n
]}
should be

{[
acc = (function (n) {() => n} (n))
n = n - 1
]}
*)
| _ -> super#expression lam
method! ident x = add x ; self
end *)

let add_lam_module_ident = Lam_module_ident.Hash_set.add
let create = Lam_module_ident.Hash_set.create
class count_hard_dependencies =
let count_hard_dependencies hard_dependencies =
object(self : 'self_type)
inherit Js_fold.fold as super
val hard_dependencies = create 17
method! module_id vid =
add_lam_module_ident hard_dependencies vid; self
method! expression x : 'self_type =
Expand All @@ -65,11 +41,12 @@ class count_hard_dependencies =
id)
| _ -> ());
super#expression x
method get_hard_dependencies = hard_dependencies
end

let calculate_hard_dependencies block =
((new count_hard_dependencies)#block block) # get_hard_dependencies
let hard_dependencies = create 17 in
let _ : Js_fold.fold = (count_hard_dependencies hard_dependencies)#block block in
hard_dependencies

(*
Given a set of [variables], count which variables [lam] will depend on
Expand Down
1 change: 0 additions & 1 deletion jscomp/core/js_map.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ method exports : exports -> exports = o#unknown
method tag_info : tag_info -> tag_info = o#unknown
method required_modules : required_modules -> required_modules = o#list (fun o -> o#module_id)
method property_name : property_name -> property_name = o#unknown
method jsint : jsint -> jsint = o#int32
method ident : ident -> ident = o#unknown
method module_id : module_id -> module_id = fun { id = _x0;kind = _x1} -> let _x0 = o#ident _x0 in
let _x1 = o#unknown _x1 in {id = _x0;kind = _x1}
Expand Down
4 changes: 2 additions & 2 deletions jscomp/core/js_of_lam_block.mli
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ val make_block :
val field :
Lam_compat.field_dbg_info ->
J.expression ->
J.jsint ->
int32 ->
J.expression

val field_by_exp :
Expand All @@ -48,7 +48,7 @@ val field_by_exp :

val set_field :
Lam_compat.set_field_dbg_info ->
J.expression -> J.jsint -> J.expression -> J.expression
J.expression -> int32 -> J.expression -> J.expression

val set_field_by_exp :
J.expression ->
Expand Down
41 changes: 7 additions & 34 deletions jscomp/core/js_pass_flatten_and_mark_dead.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,7 @@
module E = Js_exp_make
module S = Js_stmt_make

(* class count var = object (self : 'self)
val mutable appears = 0
inherit Js_fold.fold as super
method! ident x =
(if Ident.same x var then
appears <- appears + 1);
self
method get_appears = appears
end *)

(* rewrite return for current block, but don't go into
inner function, mostly for inlinning
*)
(* class rewrite_return ?return_value ()=
let mk_return =
match return_value with
| None -> fun e -> S.exp e
| Some ident -> fun e ->
S.define_variable ~kind:Variable ident e in
object (self : 'self)
inherit Js_map.map as super
method! statement x =
match x.statement_desc with
| Return {return_value = e} ->
mk_return e
| _ -> super#statement x
method! expression x = x (* don't go inside *)
end *)


type meta_info =
| Info of J.ident_info
Expand All @@ -70,7 +43,7 @@ type meta_info =
let mark_dead_code (js : J.program) : J.program =
let ident_use_stats : meta_info Hash_ident.t
= Hash_ident.create 17 in
let mark_dead = object (self)
let mark_dead : Js_fold.fold = object (self)
inherit Js_fold.fold
method! ident ident =
(match Hash_ident.find_opt ident_use_stats ident with
Expand Down Expand Up @@ -180,12 +153,12 @@ let mark_dead_code (js : J.program) : J.program =
]}

*)
let subst_map () = object (self)
let subst_map (substitution : J.expression Hash_ident.t) = object (self)
inherit Js_map.map as super

val mutable substitution : J.expression Hash_ident.t= Hash_ident.create 17

method get_substitution = substitution



method add_substitue (ident : Ident.t) (e:J.expression) =
Hash_ident.replace substitution ident e
Expand Down Expand Up @@ -264,7 +237,7 @@ let subst_map () = object (self)
{expression_desc = Number (Int {i; _})})
| Static_index ({expression_desc = Var (Id (id))}, _, Some i)
->
(match Hash_ident.find_opt self#get_substitution id with
(match Hash_ident.find_opt substitution id with
| Some {expression_desc = Caml_block (ls, Immutable, _, _) }
->
(* user program can be wrong, we should not
Expand All @@ -288,7 +261,7 @@ end

let program (js : J.program) =
js
|> (subst_map () )#program
|> (subst_map (Hash_ident.create 32) )#program
|> mark_dead_code
(* |> mark_dead_code *)
(* mark dead code twice does have effect in some cases, however, we disabled it
Expand Down
Loading