diff --git a/jscomp/core/j.ml b/jscomp/core/j.ml index 401a0ab826..00316f9ef2 100644 --- a/jscomp/core/j.ml +++ b/jscomp/core/j.ml @@ -305,8 +305,8 @@ and statement_desc = {[ goto : label option ; ]} *) - | Int_switch of expression * int case_clause list * block option - | String_switch of expression * string case_clause list * block option + | Int_switch of expression * int_clause list * block option + | String_switch of expression * string_clause list * block option | Throw of expression | Try of block * (exception_ident * block) option * block option | Debugger @@ -329,9 +329,9 @@ and variable_declaration = { property : property; ident_info : ident_info; } - -and 'a case_clause = { - switch_case : 'a ; +and string_clause = string * case_clause +and int_clause = int * case_clause +and case_clause = { switch_body : block ; should_break : bool ; (* true means break *) comment : string option ; diff --git a/jscomp/core/js_dump.ml b/jscomp/core/js_dump.ml index 23a4826ec5..aab33c9c37 100644 --- a/jscomp/core/js_dump.ml +++ b/jscomp/core/js_dump.ml @@ -488,9 +488,9 @@ and pp_function ~is_method since it can be either [int] or [string] *) and pp_one_case_clause : 'a . - _ -> P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause -> _ + _ -> P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) -> _ = fun cxt f pp_cond - ({switch_case; switch_body ; should_break; comment; } : _ J.case_clause) -> + (switch_case, ({switch_body ; should_break; comment; } : J.case_clause)) -> let cxt = P.group f 1 (fun _ -> P.group f 1 (fun _ -> @@ -520,7 +520,7 @@ and pp_one_case_clause : 'a . cxt and loop_case_clauses : 'a . cxt -> - P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause list -> cxt + P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) list -> cxt = fun cxt f pp_cond cases -> Ext_list.fold_left cases cxt (fun acc x -> pp_one_case_clause acc f pp_cond x) diff --git a/jscomp/core/js_fold.ml b/jscomp/core/js_fold.ml index a844d573d9..fc99953b7c 100644 --- a/jscomp/core/js_fold.ml +++ b/jscomp/core/js_fold.ml @@ -47,6 +47,9 @@ class virtual fold = let o = o#option (fun o -> o#expression) _x_i1 in let o = o#property _x_i2 in let o = o#ident_info _x_i3 in o method tag_info : tag_info -> 'self_type = o#unknown + method string_clause : string_clause -> 'self_type = + fun (_x, _x_i1) -> + let o = o#string _x in let o = o#case_clause _x_i1 in o method statement_desc : statement_desc -> 'self_type = function | Block _x -> let o = o#block _x in o @@ -70,10 +73,28 @@ class virtual fold = | Return _x -> let o = o#expression _x in o | Int_switch (_x, _x_i1, _x_i2) -> let o = o#expression _x in + let o = o#list (fun o -> o#int_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | String_switch (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#string_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Throw _x -> let o = o#expression _x in o + | Try (_x, _x_i1, _x_i2) -> + let o = o#block _x in let o = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + o#option + (fun o (_x, _x_i1) -> + let o = o#exception_ident _x in let o = o#block _x_i1 in o) + _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Debugger -> o + method statement : statement -> 'self_type = + fun { statement_desc = _x; comment = _x_i1 } -> + let o = o#statement_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method required_modules : required_modules -> 'self_type = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. * * 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 @@ -96,7 +117,7 @@ class virtual fold = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -104,15 +125,18 @@ class virtual fold = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> 'self_type = o#unknown + method property_map : property_map -> 'self_type = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -127,7 +151,74 @@ class virtual fold = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let o = o#property_name _x in let o = o#expression _x_i1 in o) + method property : property -> 'self_type = o#unknown + method program : program -> 'self_type = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let o = o#block _x in + let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o + method number : number -> 'self_type = o#unknown + method mutable_flag : mutable_flag -> 'self_type = o#unknown + method module_id : module_id -> 'self_type = + fun { id = _x; kind = _x_i1 } -> + let o = o#ident _x in let o = o#unknown _x_i1 in o + method length_object : length_object -> 'self_type = o#unknown + method label : label -> 'self_type = o#string + method kind : kind -> 'self_type = o#unknown + method jsint : jsint -> 'self_type = o#int32 + method int_op : int_op -> 'self_type = o#unknown + method int_clause : int_clause -> 'self_type = + fun (_x, _x_i1) -> let o = o#int _x in let o = o#case_clause _x_i1 in o + method ident_info : ident_info -> 'self_type = o#unknown + method ident : ident -> 'self_type = o#unknown + method for_ident_expression : for_ident_expression -> 'self_type = + o#expression + method for_ident : for_ident -> 'self_type = o#ident + method for_direction : for_direction -> 'self_type = o#unknown + method finish_ident_expression : finish_ident_expression -> 'self_type = + o#expression + method expression_desc : expression_desc -> 'self_type = + function + | Length (_x, _x_i1) -> + let o = o#expression _x in let o = o#length_object _x_i1 in o + | Char_of_int _x -> let o = o#expression _x in o + | Char_to_int _x -> let o = o#expression _x in o + | Is_null_or_undefined _x -> let o = o#expression _x in o + | String_append (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Bool _x -> let o = o#bool _x in o + | Typeof _x -> let o = o#expression _x in o + | Js_not _x -> let o = o#expression _x in o + | Seq (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Cond (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | Bin (_x, _x_i1, _x_i2) -> + let o = o#binop _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | FlatCall (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Call (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#expression) _x_i1 in + let o = o#unknown _x_i2 in o + | String_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Array_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Static_index (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#string _x_i1 in + let o = o#option (fun o -> o#int32) _x_i2 in o + | New (_x, _x_i1) -> + let o = o#expression _x in + let o = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -162,11 +253,52 @@ class virtual fold = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in o + | Var _x -> let o = o#vident _x in o + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#bool _x in + let o = o#list (fun o -> o#ident) _x_i1 in + let o = o#block _x_i2 in let o = o#unknown _x_i3 in o + | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o + | Unicode _x -> let o = o#string _x in o + | Raw_js_code _x -> let o = o#unknown _x in o + | Array (_x, _x_i1) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in o + | Optional_block (_x, _x_i1) -> + let o = o#expression _x in let o = o#bool _x_i1 in o + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in + let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o + | Caml_block_tag _x -> let o = o#expression _x in o + | Number _x -> let o = o#number _x in o + | Object _x -> let o = o#property_map _x in o + | Undefined -> o + | Null -> o + method expression : expression -> 'self_type = + fun { expression_desc = _x; comment = _x_i1 } -> + let o = o#expression_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method exports : exports -> 'self_type = o#unknown + method exception_ident : exception_ident -> 'self_type = o#ident + method deps_program : deps_program -> 'self_type = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let o = o#program _x in + let o = o#required_modules _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method case_clause : case_clause -> 'self_type = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let o = o#block _x in + let o = o#bool _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method block : block -> 'self_type = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -174,13 +306,13 @@ class virtual fold = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -189,20 +321,20 @@ class virtual fold = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -228,7 +360,7 @@ class virtual fold = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -237,7 +369,7 @@ class virtual fold = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -249,7 +381,7 @@ class virtual fold = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -259,12 +391,12 @@ class virtual fold = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -274,143 +406,7 @@ class virtual fold = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | String_switch (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Throw _x -> let o = o#expression _x in o - | Try (_x, _x_i1, _x_i2) -> - let o = o#block _x in - let o = - o#option - (fun o (_x, _x_i1) -> - let o = o#exception_ident _x in let o = o#block _x_i1 in o) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Debugger -> o - method statement : statement -> 'self_type = - fun { statement_desc = _x; comment = _x_i1 } -> - let o = o#statement_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method required_modules : required_modules -> 'self_type = - o#list (fun o -> o#module_id) - method property_name : property_name -> 'self_type = o#unknown - method property_map : property_map -> 'self_type = - o#list - (fun o (_x, _x_i1) -> - let o = o#property_name _x in let o = o#expression _x_i1 in o) - method property : property -> 'self_type = o#unknown - method program : program -> 'self_type = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let o = o#block _x in - let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o - method number : number -> 'self_type = o#unknown - method mutable_flag : mutable_flag -> 'self_type = o#unknown - method module_id : module_id -> 'self_type = - fun { id = _x; kind = _x_i1 } -> - let o = o#ident _x in let o = o#unknown _x_i1 in o - method length_object : length_object -> 'self_type = o#unknown - method label : label -> 'self_type = o#string - method kind : kind -> 'self_type = o#unknown - method jsint : jsint -> 'self_type = o#int32 - method int_op : int_op -> 'self_type = o#unknown - method ident_info : ident_info -> 'self_type = o#unknown - method ident : ident -> 'self_type = o#unknown - method for_ident_expression : for_ident_expression -> 'self_type = - o#expression - method for_ident : for_ident -> 'self_type = o#ident - method for_direction : for_direction -> 'self_type = o#unknown - method finish_ident_expression : finish_ident_expression -> 'self_type = - o#expression - method expression_desc : expression_desc -> 'self_type = - function - | Length (_x, _x_i1) -> - let o = o#expression _x in let o = o#length_object _x_i1 in o - | Char_of_int _x -> let o = o#expression _x in o - | Char_to_int _x -> let o = o#expression _x in o - | Is_null_or_undefined _x -> let o = o#expression _x in o - | String_append (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Bool _x -> let o = o#bool _x in o - | Typeof _x -> let o = o#expression _x in o - | Js_not _x -> let o = o#expression _x in o - | Seq (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Cond (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | Bin (_x, _x_i1, _x_i2) -> - let o = o#binop _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | FlatCall (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Call (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#list (fun o -> o#expression) _x_i1 in - let o = o#unknown _x_i2 in o - | String_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Array_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Static_index (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#string _x_i1 in - let o = o#option (fun o -> o#int32) _x_i2 in o - | New (_x, _x_i1) -> - let o = o#expression _x in - let o = o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in o - | Var _x -> let o = o#vident _x in o - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#bool _x in - let o = o#list (fun o -> o#ident) _x_i1 in - let o = o#block _x_i2 in let o = o#unknown _x_i3 in o - | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o - | Unicode _x -> let o = o#string _x in o - | Raw_js_code _x -> let o = o#unknown _x in o - | Array (_x, _x_i1) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in o - | Optional_block (_x, _x_i1) -> - let o = o#expression _x in let o = o#bool _x_i1 in o - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in - let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o - | Caml_block_tag _x -> let o = o#expression _x in o - | Number _x -> let o = o#number _x in o - | Object _x -> let o = o#property_map _x in o - | Undefined -> o - | Null -> o - method expression : expression -> 'self_type = - fun { expression_desc = _x; comment = _x_i1 } -> - let o = o#expression_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method exports : exports -> 'self_type = o#unknown - method exception_ident : exception_ident -> 'self_type = o#ident - method deps_program : deps_program -> 'self_type = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let o = o#program _x in - let o = o#required_modules _x_i1 in - let o = o#option (fun o -> o#string) _x_i2 in o - method case_clause : - 'a. ('self_type -> 'a -> 'self_type) -> 'a case_clause -> 'self_type = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let o = _f_a o _x in - let o = o#block _x_i1 in - let o = o#bool _x_i2 in - let o = o#option (fun o -> o#string) _x_i3 in o - method block : block -> 'self_type = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) diff --git a/jscomp/core/js_map.ml b/jscomp/core/js_map.ml index d7ff54da2b..902889b444 100644 --- a/jscomp/core/js_map.ml +++ b/jscomp/core/js_map.ml @@ -56,6 +56,10 @@ class virtual map = { ident = _x; value = _x_i1; property = _x_i2; ident_info = _x_i3; } method tag_info : tag_info -> tag_info = o#unknown + method string_clause : string_clause -> string_clause = + fun (_x, _x_i1) -> + let _x = o#string _x in + let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) method statement_desc : statement_desc -> statement_desc = function | Block _x -> let _x = o#block _x in Block _x @@ -83,10 +87,33 @@ class virtual map = | Return _x -> let _x = o#expression _x in Return _x | Int_switch (_x, _x_i1, _x_i2) -> let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#int_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Int_switch (_x, _x_i1, _x_i2) + | String_switch (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#string_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in String_switch (_x, _x_i1, _x_i2) + | Throw _x -> let _x = o#expression _x in Throw _x + | Try (_x, _x_i1, _x_i2) -> + let _x = o#block _x in let _x_i1 = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + o#option + (fun o (_x, _x_i1) -> + let _x = o#exception_ident _x in + let _x_i1 = o#block _x_i1 in (_x, _x_i1)) + _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Try (_x, _x_i1, _x_i2) + | Debugger -> Debugger + method statement : statement -> statement = + fun { statement_desc = _x; comment = _x_i1 } -> + let _x = o#statement_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { statement_desc = _x; comment = _x_i1; } + method required_modules : required_modules -> required_modules = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. * * 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 @@ -109,7 +136,7 @@ class virtual map = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -117,15 +144,18 @@ class virtual map = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> property_name = o#unknown + method property_map : property_map -> property_map = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -140,7 +170,89 @@ class virtual map = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let _x = o#property_name _x in + let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) + method property : property -> property = o#unknown + method program : program -> program = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#exports _x_i1 in + let _x_i2 = o#unknown _x_i2 + in { block = _x; exports = _x_i1; export_set = _x_i2; } + method number : number -> number = o#unknown + method mutable_flag : mutable_flag -> mutable_flag = o#unknown + method module_id : module_id -> module_id = + fun { id = _x; kind = _x_i1 } -> + let _x = o#ident _x in + let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } + method length_object : length_object -> length_object = o#unknown + method label : label -> label = o#string + method kind : kind -> kind = o#unknown + method jsint : jsint -> jsint = o#int32 + method int_op : int_op -> int_op = o#unknown + method int_clause : int_clause -> int_clause = + fun (_x, _x_i1) -> + let _x = o#int _x in let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) + method ident_info : ident_info -> ident_info = o#unknown + method ident : ident -> ident = o#unknown + method for_ident_expression : + for_ident_expression -> for_ident_expression = o#expression + method for_ident : for_ident -> for_ident = o#ident + method for_direction : for_direction -> for_direction = o#unknown + method finish_ident_expression : + finish_ident_expression -> finish_ident_expression = o#expression + method expression_desc : expression_desc -> expression_desc = + function + | Length (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) + | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x + | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x + | Is_null_or_undefined _x -> + let _x = o#expression _x in Is_null_or_undefined _x + | String_append (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) + | Bool _x -> let _x = o#bool _x in Bool _x + | Typeof _x -> let _x = o#expression _x in Typeof _x + | Js_not _x -> let _x = o#expression _x in Js_not _x + | Seq (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) + | Cond (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) + | Bin (_x, _x_i1, _x_i2) -> + let _x = o#binop _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) + | FlatCall (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) + | Call (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#expression) _x_i1 in + let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) + | String_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) + | Array_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) + | Static_index (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#string _x_i1 in + let _x_i2 = o#option (fun o -> o#int32) _x_i2 + in Static_index (_x, _x_i1, _x_i2) + | New (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -175,11 +287,60 @@ class virtual map = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in New (_x, _x_i1) + | Var _x -> let _x = o#vident _x in Var _x + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#bool _x in + let _x_i1 = o#list (fun o -> o#ident) _x_i1 in + let _x_i2 = o#block _x_i2 in + let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) + | Str (_x, _x_i1) -> + let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) + | Unicode _x -> let _x = o#string _x in Unicode _x + | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x + | Array (_x, _x_i1) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) + | Optional_block (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in + let _x_i2 = o#expression _x_i2 in + let _x_i3 = o#tag_info _x_i3 + in Caml_block (_x, _x_i1, _x_i2, _x_i3) + | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x + | Number _x -> let _x = o#number _x in Number _x + | Object _x -> let _x = o#property_map _x in Object _x + | Undefined -> Undefined + | Null -> Null + method expression : expression -> expression = + fun { expression_desc = _x; comment = _x_i1 } -> + let _x = o#expression_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { expression_desc = _x; comment = _x_i1; } + method exports : exports -> exports = o#unknown + method exception_ident : exception_ident -> exception_ident = o#ident + method deps_program : deps_program -> deps_program = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let _x = o#program _x in + let _x_i1 = o#required_modules _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { program = _x; modules = _x_i1; side_effect = _x_i2; } + method case_clause : case_clause -> case_clause = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#bool _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { switch_body = _x; should_break = _x_i1; comment = _x_i2; } + method block : block -> block = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -187,13 +348,13 @@ class virtual map = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -202,20 +363,20 @@ class virtual map = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -241,7 +402,7 @@ class virtual map = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -250,7 +411,7 @@ class virtual map = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -262,7 +423,7 @@ class virtual map = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -272,12 +433,12 @@ class virtual map = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -287,178 +448,7 @@ class virtual map = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Int_switch (_x, _x_i1, _x_i2) - | String_switch (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in String_switch (_x, _x_i1, _x_i2) - | Throw _x -> let _x = o#expression _x in Throw _x - | Try (_x, _x_i1, _x_i2) -> - let _x = o#block _x in - let _x_i1 = - o#option - (fun o (_x, _x_i1) -> - let _x = o#exception_ident _x in - let _x_i1 = o#block _x_i1 in (_x, _x_i1)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Try (_x, _x_i1, _x_i2) - | Debugger -> Debugger - method statement : statement -> statement = - fun { statement_desc = _x; comment = _x_i1 } -> - let _x = o#statement_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { statement_desc = _x; comment = _x_i1; } - method required_modules : required_modules -> required_modules = - o#list (fun o -> o#module_id) - method property_name : property_name -> property_name = o#unknown - method property_map : property_map -> property_map = - o#list - (fun o (_x, _x_i1) -> - let _x = o#property_name _x in - let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) - method property : property -> property = o#unknown - method program : program -> program = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let _x = o#block _x in - let _x_i1 = o#exports _x_i1 in - let _x_i2 = o#unknown _x_i2 - in { block = _x; exports = _x_i1; export_set = _x_i2; } - method number : number -> number = o#unknown - method mutable_flag : mutable_flag -> mutable_flag = o#unknown - method module_id : module_id -> module_id = - fun { id = _x; kind = _x_i1 } -> - let _x = o#ident _x in - let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } - method length_object : length_object -> length_object = o#unknown - method label : label -> label = o#string - method kind : kind -> kind = o#unknown - method jsint : jsint -> jsint = o#int32 - method int_op : int_op -> int_op = o#unknown - method ident_info : ident_info -> ident_info = o#unknown - method ident : ident -> ident = o#unknown - method for_ident_expression : - for_ident_expression -> for_ident_expression = o#expression - method for_ident : for_ident -> for_ident = o#ident - method for_direction : for_direction -> for_direction = o#unknown - method finish_ident_expression : - finish_ident_expression -> finish_ident_expression = o#expression - method expression_desc : expression_desc -> expression_desc = - function - | Length (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) - | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x - | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x - | Is_null_or_undefined _x -> - let _x = o#expression _x in Is_null_or_undefined _x - | String_append (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) - | Bool _x -> let _x = o#bool _x in Bool _x - | Typeof _x -> let _x = o#expression _x in Typeof _x - | Js_not _x -> let _x = o#expression _x in Js_not _x - | Seq (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) - | Cond (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) - | Bin (_x, _x_i1, _x_i2) -> - let _x = o#binop _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) - | FlatCall (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) - | Call (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#list (fun o -> o#expression) _x_i1 in - let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) - | String_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) - | Array_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) - | Static_index (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#string _x_i1 in - let _x_i2 = o#option (fun o -> o#int32) _x_i2 - in Static_index (_x, _x_i1, _x_i2) - | New (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = - o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in New (_x, _x_i1) - | Var _x -> let _x = o#vident _x in Var _x - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#bool _x in - let _x_i1 = o#list (fun o -> o#ident) _x_i1 in - let _x_i2 = o#block _x_i2 in - let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) - | Str (_x, _x_i1) -> - let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) - | Unicode _x -> let _x = o#string _x in Unicode _x - | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x - | Array (_x, _x_i1) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) - | Optional_block (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in - let _x_i2 = o#expression _x_i2 in - let _x_i3 = o#tag_info _x_i3 - in Caml_block (_x, _x_i1, _x_i2, _x_i3) - | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x - | Number _x -> let _x = o#number _x in Number _x - | Object _x -> let _x = o#property_map _x in Object _x - | Undefined -> Undefined - | Null -> Null - method expression : expression -> expression = - fun { expression_desc = _x; comment = _x_i1 } -> - let _x = o#expression_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { expression_desc = _x; comment = _x_i1; } - method exports : exports -> exports = o#unknown - method exception_ident : exception_ident -> exception_ident = o#ident - method deps_program : deps_program -> deps_program = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let _x = o#program _x in - let _x_i1 = o#required_modules _x_i1 in - let _x_i2 = o#option (fun o -> o#string) _x_i2 - in { program = _x; modules = _x_i1; side_effect = _x_i2; } - method case_clause : - 'a 'a_out. - ('self_type -> 'a -> 'a_out) -> 'a case_clause -> 'a_out case_clause = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let _x = _f_a o _x in - let _x_i1 = o#block _x_i1 in - let _x_i2 = o#bool _x_i2 in - let _x_i3 = o#option (fun o -> o#string) _x_i3 - in - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3; - } - method block : block -> block = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) diff --git a/jscomp/core/js_of_lam_variant.ml b/jscomp/core/js_of_lam_variant.ml index a892c612c2..827085c8fc 100644 --- a/jscomp/core/js_of_lam_variant.ml +++ b/jscomp/core/js_of_lam_variant.ml @@ -43,7 +43,7 @@ let eval (arg : J.expression) (dispatches : (string * string) list ) : E.t = E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -71,7 +71,7 @@ let eval_as_event (arg : J.expression) (dispatches : (string * string) list opti (S.string_switch (E.poly_var_tag_access arg) (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -103,7 +103,7 @@ let eval_as_int (arg : J.expression) (dispatches : (string * int) list ) : E.t E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.int (Int32.of_int r))]; should_break = false; (* FIXME: if true, still print break*) comment = None; diff --git a/jscomp/core/js_stmt_make.ml b/jscomp/core/js_stmt_make.ml index a2c9c1d430..b2018d7189 100644 --- a/jscomp/core/js_stmt_make.ml +++ b/jscomp/core/js_stmt_make.ml @@ -98,13 +98,13 @@ let int_switch ?(declaration : (J.property * Ident.t) option ) ?(default : J.block option) (e : J.expression) - (clauses : int J.case_clause list): t = + (clauses : (int * J.case_clause) list): t = match e.expression_desc with | Number (Int {i; _}) -> let continuation = match Ext_list.find_opt clauses - (fun x -> - if x.switch_case = Int32.to_int i then + (fun (switch_case,x) -> + if switch_case = Int32.to_int i then Some x.switch_body else None ) with | Some case -> case @@ -137,12 +137,12 @@ let string_switch ?(declaration : (J.property * Ident.t) option) ?(default : J.block option) (e : J.expression) - (clauses : string J.case_clause list): t= + (clauses : (string * J.case_clause) list): t= match e.expression_desc with | Str (_,s) -> let continuation = - match Ext_list.find_opt clauses (fun x -> - if x.switch_case = s then + match Ext_list.find_opt clauses (fun (switch_case, x) -> + if switch_case = s then Some x.switch_body else None ) with diff --git a/jscomp/core/js_stmt_make.mli b/jscomp/core/js_stmt_make.mli index b4ee71ec57..eed797598b 100644 --- a/jscomp/core/js_stmt_make.mli +++ b/jscomp/core/js_stmt_make.mli @@ -84,7 +84,7 @@ val int_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - int J.case_clause list -> + (int * J.case_clause) list -> t val string_switch : @@ -92,7 +92,7 @@ val string_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - string J.case_clause list -> + (string * J.case_clause) list -> t (** Just declaration without initialization *) diff --git a/jscomp/core/lam_compile.ml b/jscomp/core/lam_compile.ml index 8ecdefb78c..46ab026c75 100644 --- a/jscomp/core/lam_compile.ml +++ b/jscomp/core/lam_compile.ml @@ -490,7 +490,7 @@ and compile_general_cases Lam_compile_context.t -> (?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> 'a J.case_clause list -> J.statement) -> + _ -> ('a * J.case_clause) list -> J.statement) -> _ -> ('a * Lam.t) list -> default_case -> J.block = fun @@ -501,7 +501,7 @@ and compile_general_cases (switch : ?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> _ J.case_clause list -> J.statement + _ -> (_ * J.case_clause) list -> J.statement ) (switch_exp : J.expression) (cases : (_ * Lam.t) list) @@ -571,13 +571,13 @@ and compile_general_cases should_break else should_break && Lam_exit_code.has_exit lam in - {J.switch_case ; + switch_case , J.{ switch_body; should_break; comment = make_comment switch_case; } else - { switch_case; switch_body = []; should_break = false; comment = make_comment switch_case; } + switch_case, {switch_body = []; should_break = false; comment = make_comment switch_case; } ) (* TODO: we should also group default *) diff --git a/lib/4.06.1/unstable/js_compiler.ml b/lib/4.06.1/unstable/js_compiler.ml index 90f910f0b6..6fa6af795e 100644 --- a/lib/4.06.1/unstable/js_compiler.ml +++ b/lib/4.06.1/unstable/js_compiler.ml @@ -86060,8 +86060,8 @@ and statement_desc = {[ goto : label option ; ]} *) - | Int_switch of expression * int case_clause list * block option - | String_switch of expression * string case_clause list * block option + | Int_switch of expression * int_clause list * block option + | String_switch of expression * string_clause list * block option | Throw of expression | Try of block * (exception_ident * block) option * block option | Debugger @@ -86084,9 +86084,9 @@ and variable_declaration = { property : property; ident_info : ident_info; } - -and 'a case_clause = { - switch_case : 'a ; +and string_clause = string * case_clause +and int_clause = int * case_clause +and case_clause = { switch_body : block ; should_break : bool ; (* true means break *) comment : string option ; @@ -86557,6 +86557,9 @@ class virtual fold = let o = o#option (fun o -> o#expression) _x_i1 in let o = o#property _x_i2 in let o = o#ident_info _x_i3 in o method tag_info : tag_info -> 'self_type = o#unknown + method string_clause : string_clause -> 'self_type = + fun (_x, _x_i1) -> + let o = o#string _x in let o = o#case_clause _x_i1 in o method statement_desc : statement_desc -> 'self_type = function | Block _x -> let o = o#block _x in o @@ -86580,10 +86583,28 @@ class virtual fold = | Return _x -> let o = o#expression _x in o | Int_switch (_x, _x_i1, _x_i2) -> let o = o#expression _x in + let o = o#list (fun o -> o#int_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | String_switch (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#string_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Throw _x -> let o = o#expression _x in o + | Try (_x, _x_i1, _x_i2) -> + let o = o#block _x in let o = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + o#option + (fun o (_x, _x_i1) -> + let o = o#exception_ident _x in let o = o#block _x_i1 in o) + _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Debugger -> o + method statement : statement -> 'self_type = + fun { statement_desc = _x; comment = _x_i1 } -> + let o = o#statement_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method required_modules : required_modules -> 'self_type = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. * * 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 @@ -86606,7 +86627,7 @@ class virtual fold = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -86614,15 +86635,18 @@ class virtual fold = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> 'self_type = o#unknown + method property_map : property_map -> 'self_type = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -86637,7 +86661,74 @@ class virtual fold = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let o = o#property_name _x in let o = o#expression _x_i1 in o) + method property : property -> 'self_type = o#unknown + method program : program -> 'self_type = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let o = o#block _x in + let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o + method number : number -> 'self_type = o#unknown + method mutable_flag : mutable_flag -> 'self_type = o#unknown + method module_id : module_id -> 'self_type = + fun { id = _x; kind = _x_i1 } -> + let o = o#ident _x in let o = o#unknown _x_i1 in o + method length_object : length_object -> 'self_type = o#unknown + method label : label -> 'self_type = o#string + method kind : kind -> 'self_type = o#unknown + method jsint : jsint -> 'self_type = o#int32 + method int_op : int_op -> 'self_type = o#unknown + method int_clause : int_clause -> 'self_type = + fun (_x, _x_i1) -> let o = o#int _x in let o = o#case_clause _x_i1 in o + method ident_info : ident_info -> 'self_type = o#unknown + method ident : ident -> 'self_type = o#unknown + method for_ident_expression : for_ident_expression -> 'self_type = + o#expression + method for_ident : for_ident -> 'self_type = o#ident + method for_direction : for_direction -> 'self_type = o#unknown + method finish_ident_expression : finish_ident_expression -> 'self_type = + o#expression + method expression_desc : expression_desc -> 'self_type = + function + | Length (_x, _x_i1) -> + let o = o#expression _x in let o = o#length_object _x_i1 in o + | Char_of_int _x -> let o = o#expression _x in o + | Char_to_int _x -> let o = o#expression _x in o + | Is_null_or_undefined _x -> let o = o#expression _x in o + | String_append (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Bool _x -> let o = o#bool _x in o + | Typeof _x -> let o = o#expression _x in o + | Js_not _x -> let o = o#expression _x in o + | Seq (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Cond (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | Bin (_x, _x_i1, _x_i2) -> + let o = o#binop _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | FlatCall (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Call (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#expression) _x_i1 in + let o = o#unknown _x_i2 in o + | String_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Array_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Static_index (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#string _x_i1 in + let o = o#option (fun o -> o#int32) _x_i2 in o + | New (_x, _x_i1) -> + let o = o#expression _x in + let o = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -86672,11 +86763,52 @@ class virtual fold = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in o + | Var _x -> let o = o#vident _x in o + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#bool _x in + let o = o#list (fun o -> o#ident) _x_i1 in + let o = o#block _x_i2 in let o = o#unknown _x_i3 in o + | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o + | Unicode _x -> let o = o#string _x in o + | Raw_js_code _x -> let o = o#unknown _x in o + | Array (_x, _x_i1) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in o + | Optional_block (_x, _x_i1) -> + let o = o#expression _x in let o = o#bool _x_i1 in o + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in + let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o + | Caml_block_tag _x -> let o = o#expression _x in o + | Number _x -> let o = o#number _x in o + | Object _x -> let o = o#property_map _x in o + | Undefined -> o + | Null -> o + method expression : expression -> 'self_type = + fun { expression_desc = _x; comment = _x_i1 } -> + let o = o#expression_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method exports : exports -> 'self_type = o#unknown + method exception_ident : exception_ident -> 'self_type = o#ident + method deps_program : deps_program -> 'self_type = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let o = o#program _x in + let o = o#required_modules _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method case_clause : case_clause -> 'self_type = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let o = o#block _x in + let o = o#bool _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method block : block -> 'self_type = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -86684,13 +86816,13 @@ class virtual fold = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -86699,20 +86831,20 @@ class virtual fold = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -86738,7 +86870,7 @@ class virtual fold = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -86747,7 +86879,7 @@ class virtual fold = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -86759,7 +86891,7 @@ class virtual fold = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -86769,12 +86901,12 @@ class virtual fold = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -86784,143 +86916,7 @@ class virtual fold = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | String_switch (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Throw _x -> let o = o#expression _x in o - | Try (_x, _x_i1, _x_i2) -> - let o = o#block _x in - let o = - o#option - (fun o (_x, _x_i1) -> - let o = o#exception_ident _x in let o = o#block _x_i1 in o) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Debugger -> o - method statement : statement -> 'self_type = - fun { statement_desc = _x; comment = _x_i1 } -> - let o = o#statement_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method required_modules : required_modules -> 'self_type = - o#list (fun o -> o#module_id) - method property_name : property_name -> 'self_type = o#unknown - method property_map : property_map -> 'self_type = - o#list - (fun o (_x, _x_i1) -> - let o = o#property_name _x in let o = o#expression _x_i1 in o) - method property : property -> 'self_type = o#unknown - method program : program -> 'self_type = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let o = o#block _x in - let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o - method number : number -> 'self_type = o#unknown - method mutable_flag : mutable_flag -> 'self_type = o#unknown - method module_id : module_id -> 'self_type = - fun { id = _x; kind = _x_i1 } -> - let o = o#ident _x in let o = o#unknown _x_i1 in o - method length_object : length_object -> 'self_type = o#unknown - method label : label -> 'self_type = o#string - method kind : kind -> 'self_type = o#unknown - method jsint : jsint -> 'self_type = o#int32 - method int_op : int_op -> 'self_type = o#unknown - method ident_info : ident_info -> 'self_type = o#unknown - method ident : ident -> 'self_type = o#unknown - method for_ident_expression : for_ident_expression -> 'self_type = - o#expression - method for_ident : for_ident -> 'self_type = o#ident - method for_direction : for_direction -> 'self_type = o#unknown - method finish_ident_expression : finish_ident_expression -> 'self_type = - o#expression - method expression_desc : expression_desc -> 'self_type = - function - | Length (_x, _x_i1) -> - let o = o#expression _x in let o = o#length_object _x_i1 in o - | Char_of_int _x -> let o = o#expression _x in o - | Char_to_int _x -> let o = o#expression _x in o - | Is_null_or_undefined _x -> let o = o#expression _x in o - | String_append (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Bool _x -> let o = o#bool _x in o - | Typeof _x -> let o = o#expression _x in o - | Js_not _x -> let o = o#expression _x in o - | Seq (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Cond (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | Bin (_x, _x_i1, _x_i2) -> - let o = o#binop _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | FlatCall (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Call (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#list (fun o -> o#expression) _x_i1 in - let o = o#unknown _x_i2 in o - | String_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Array_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Static_index (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#string _x_i1 in - let o = o#option (fun o -> o#int32) _x_i2 in o - | New (_x, _x_i1) -> - let o = o#expression _x in - let o = o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in o - | Var _x -> let o = o#vident _x in o - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#bool _x in - let o = o#list (fun o -> o#ident) _x_i1 in - let o = o#block _x_i2 in let o = o#unknown _x_i3 in o - | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o - | Unicode _x -> let o = o#string _x in o - | Raw_js_code _x -> let o = o#unknown _x in o - | Array (_x, _x_i1) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in o - | Optional_block (_x, _x_i1) -> - let o = o#expression _x in let o = o#bool _x_i1 in o - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in - let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o - | Caml_block_tag _x -> let o = o#expression _x in o - | Number _x -> let o = o#number _x in o - | Object _x -> let o = o#property_map _x in o - | Undefined -> o - | Null -> o - method expression : expression -> 'self_type = - fun { expression_desc = _x; comment = _x_i1 } -> - let o = o#expression_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method exports : exports -> 'self_type = o#unknown - method exception_ident : exception_ident -> 'self_type = o#ident - method deps_program : deps_program -> 'self_type = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let o = o#program _x in - let o = o#required_modules _x_i1 in - let o = o#option (fun o -> o#string) _x_i2 in o - method case_clause : - 'a. ('self_type -> 'a -> 'self_type) -> 'a case_clause -> 'self_type = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let o = _f_a o _x in - let o = o#block _x_i1 in - let o = o#bool _x_i2 in - let o = o#option (fun o -> o#string) _x_i3 in o - method block : block -> 'self_type = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -90313,9 +90309,9 @@ and pp_function ~is_method since it can be either [int] or [string] *) and pp_one_case_clause : 'a . - _ -> P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause -> _ + _ -> P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) -> _ = fun cxt f pp_cond - ({switch_case; switch_body ; should_break; comment; } : _ J.case_clause) -> + (switch_case, ({switch_body ; should_break; comment; } : J.case_clause)) -> let cxt = P.group f 1 (fun _ -> P.group f 1 (fun _ -> @@ -90345,7 +90341,7 @@ and pp_one_case_clause : 'a . cxt and loop_case_clauses : 'a . cxt -> - P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause list -> cxt + P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) list -> cxt = fun cxt f pp_cond cases -> Ext_list.fold_left cases cxt (fun acc x -> pp_one_case_clause acc f pp_cond x) @@ -99589,7 +99585,7 @@ val int_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - int J.case_clause list -> + (int * J.case_clause) list -> t val string_switch : @@ -99597,7 +99593,7 @@ val string_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - string J.case_clause list -> + (string * J.case_clause) list -> t (** Just declaration without initialization *) @@ -99807,13 +99803,13 @@ let int_switch ?(declaration : (J.property * Ident.t) option ) ?(default : J.block option) (e : J.expression) - (clauses : int J.case_clause list): t = + (clauses : (int * J.case_clause) list): t = match e.expression_desc with | Number (Int {i; _}) -> let continuation = match Ext_list.find_opt clauses - (fun x -> - if x.switch_case = Int32.to_int i then + (fun (switch_case,x) -> + if switch_case = Int32.to_int i then Some x.switch_body else None ) with | Some case -> case @@ -99846,12 +99842,12 @@ let string_switch ?(declaration : (J.property * Ident.t) option) ?(default : J.block option) (e : J.expression) - (clauses : string J.case_clause list): t= + (clauses : (string * J.case_clause) list): t= match e.expression_desc with | Str (_,s) -> let continuation = - match Ext_list.find_opt clauses (fun x -> - if x.switch_case = s then + match Ext_list.find_opt clauses (fun (switch_case, x) -> + if switch_case = s then Some x.switch_body else None ) with @@ -101742,6 +101738,10 @@ class virtual map = { ident = _x; value = _x_i1; property = _x_i2; ident_info = _x_i3; } method tag_info : tag_info -> tag_info = o#unknown + method string_clause : string_clause -> string_clause = + fun (_x, _x_i1) -> + let _x = o#string _x in + let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) method statement_desc : statement_desc -> statement_desc = function | Block _x -> let _x = o#block _x in Block _x @@ -101769,13 +101769,36 @@ class virtual map = | Return _x -> let _x = o#expression _x in Return _x | Int_switch (_x, _x_i1, _x_i2) -> let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#int_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Int_switch (_x, _x_i1, _x_i2) + | String_switch (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#string_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in String_switch (_x, _x_i1, _x_i2) + | Throw _x -> let _x = o#expression _x in Throw _x + | Try (_x, _x_i1, _x_i2) -> + let _x = o#block _x in let _x_i1 = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * 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 + o#option + (fun o (_x, _x_i1) -> + let _x = o#exception_ident _x in + let _x_i1 = o#block _x_i1 in (_x, _x_i1)) + _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Try (_x, _x_i1, _x_i2) + | Debugger -> Debugger + method statement : statement -> statement = + fun { statement_desc = _x; comment = _x_i1 } -> + let _x = o#statement_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { statement_desc = _x; comment = _x_i1; } + method required_modules : required_modules -> required_modules = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + * + * 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * @@ -101795,7 +101818,7 @@ class virtual map = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -101803,15 +101826,18 @@ class virtual map = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> property_name = o#unknown + method property_map : property_map -> property_map = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -101826,7 +101852,89 @@ class virtual map = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let _x = o#property_name _x in + let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) + method property : property -> property = o#unknown + method program : program -> program = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#exports _x_i1 in + let _x_i2 = o#unknown _x_i2 + in { block = _x; exports = _x_i1; export_set = _x_i2; } + method number : number -> number = o#unknown + method mutable_flag : mutable_flag -> mutable_flag = o#unknown + method module_id : module_id -> module_id = + fun { id = _x; kind = _x_i1 } -> + let _x = o#ident _x in + let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } + method length_object : length_object -> length_object = o#unknown + method label : label -> label = o#string + method kind : kind -> kind = o#unknown + method jsint : jsint -> jsint = o#int32 + method int_op : int_op -> int_op = o#unknown + method int_clause : int_clause -> int_clause = + fun (_x, _x_i1) -> + let _x = o#int _x in let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) + method ident_info : ident_info -> ident_info = o#unknown + method ident : ident -> ident = o#unknown + method for_ident_expression : + for_ident_expression -> for_ident_expression = o#expression + method for_ident : for_ident -> for_ident = o#ident + method for_direction : for_direction -> for_direction = o#unknown + method finish_ident_expression : + finish_ident_expression -> finish_ident_expression = o#expression + method expression_desc : expression_desc -> expression_desc = + function + | Length (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) + | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x + | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x + | Is_null_or_undefined _x -> + let _x = o#expression _x in Is_null_or_undefined _x + | String_append (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) + | Bool _x -> let _x = o#bool _x in Bool _x + | Typeof _x -> let _x = o#expression _x in Typeof _x + | Js_not _x -> let _x = o#expression _x in Js_not _x + | Seq (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) + | Cond (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) + | Bin (_x, _x_i1, _x_i2) -> + let _x = o#binop _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) + | FlatCall (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) + | Call (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#expression) _x_i1 in + let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) + | String_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) + | Array_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) + | Static_index (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#string _x_i1 in + let _x_i2 = o#option (fun o -> o#int32) _x_i2 + in Static_index (_x, _x_i1, _x_i2) + | New (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -101861,11 +101969,60 @@ class virtual map = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in New (_x, _x_i1) + | Var _x -> let _x = o#vident _x in Var _x + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#bool _x in + let _x_i1 = o#list (fun o -> o#ident) _x_i1 in + let _x_i2 = o#block _x_i2 in + let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) + | Str (_x, _x_i1) -> + let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) + | Unicode _x -> let _x = o#string _x in Unicode _x + | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x + | Array (_x, _x_i1) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) + | Optional_block (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in + let _x_i2 = o#expression _x_i2 in + let _x_i3 = o#tag_info _x_i3 + in Caml_block (_x, _x_i1, _x_i2, _x_i3) + | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x + | Number _x -> let _x = o#number _x in Number _x + | Object _x -> let _x = o#property_map _x in Object _x + | Undefined -> Undefined + | Null -> Null + method expression : expression -> expression = + fun { expression_desc = _x; comment = _x_i1 } -> + let _x = o#expression_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { expression_desc = _x; comment = _x_i1; } + method exports : exports -> exports = o#unknown + method exception_ident : exception_ident -> exception_ident = o#ident + method deps_program : deps_program -> deps_program = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let _x = o#program _x in + let _x_i1 = o#required_modules _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { program = _x; modules = _x_i1; side_effect = _x_i2; } + method case_clause : case_clause -> case_clause = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#bool _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { switch_body = _x; should_break = _x_i1; comment = _x_i2; } + method block : block -> block = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -101873,13 +102030,13 @@ class virtual map = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -101888,20 +102045,20 @@ class virtual map = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -101927,7 +102084,7 @@ class virtual map = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -101936,7 +102093,7 @@ class virtual map = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -101948,7 +102105,7 @@ class virtual map = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -101958,12 +102115,12 @@ class virtual map = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -101973,178 +102130,7 @@ class virtual map = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Int_switch (_x, _x_i1, _x_i2) - | String_switch (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in String_switch (_x, _x_i1, _x_i2) - | Throw _x -> let _x = o#expression _x in Throw _x - | Try (_x, _x_i1, _x_i2) -> - let _x = o#block _x in - let _x_i1 = - o#option - (fun o (_x, _x_i1) -> - let _x = o#exception_ident _x in - let _x_i1 = o#block _x_i1 in (_x, _x_i1)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Try (_x, _x_i1, _x_i2) - | Debugger -> Debugger - method statement : statement -> statement = - fun { statement_desc = _x; comment = _x_i1 } -> - let _x = o#statement_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { statement_desc = _x; comment = _x_i1; } - method required_modules : required_modules -> required_modules = - o#list (fun o -> o#module_id) - method property_name : property_name -> property_name = o#unknown - method property_map : property_map -> property_map = - o#list - (fun o (_x, _x_i1) -> - let _x = o#property_name _x in - let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) - method property : property -> property = o#unknown - method program : program -> program = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let _x = o#block _x in - let _x_i1 = o#exports _x_i1 in - let _x_i2 = o#unknown _x_i2 - in { block = _x; exports = _x_i1; export_set = _x_i2; } - method number : number -> number = o#unknown - method mutable_flag : mutable_flag -> mutable_flag = o#unknown - method module_id : module_id -> module_id = - fun { id = _x; kind = _x_i1 } -> - let _x = o#ident _x in - let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } - method length_object : length_object -> length_object = o#unknown - method label : label -> label = o#string - method kind : kind -> kind = o#unknown - method jsint : jsint -> jsint = o#int32 - method int_op : int_op -> int_op = o#unknown - method ident_info : ident_info -> ident_info = o#unknown - method ident : ident -> ident = o#unknown - method for_ident_expression : - for_ident_expression -> for_ident_expression = o#expression - method for_ident : for_ident -> for_ident = o#ident - method for_direction : for_direction -> for_direction = o#unknown - method finish_ident_expression : - finish_ident_expression -> finish_ident_expression = o#expression - method expression_desc : expression_desc -> expression_desc = - function - | Length (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) - | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x - | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x - | Is_null_or_undefined _x -> - let _x = o#expression _x in Is_null_or_undefined _x - | String_append (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) - | Bool _x -> let _x = o#bool _x in Bool _x - | Typeof _x -> let _x = o#expression _x in Typeof _x - | Js_not _x -> let _x = o#expression _x in Js_not _x - | Seq (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) - | Cond (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) - | Bin (_x, _x_i1, _x_i2) -> - let _x = o#binop _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) - | FlatCall (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) - | Call (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#list (fun o -> o#expression) _x_i1 in - let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) - | String_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) - | Array_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) - | Static_index (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#string _x_i1 in - let _x_i2 = o#option (fun o -> o#int32) _x_i2 - in Static_index (_x, _x_i1, _x_i2) - | New (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = - o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in New (_x, _x_i1) - | Var _x -> let _x = o#vident _x in Var _x - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#bool _x in - let _x_i1 = o#list (fun o -> o#ident) _x_i1 in - let _x_i2 = o#block _x_i2 in - let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) - | Str (_x, _x_i1) -> - let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) - | Unicode _x -> let _x = o#string _x in Unicode _x - | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x - | Array (_x, _x_i1) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) - | Optional_block (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in - let _x_i2 = o#expression _x_i2 in - let _x_i3 = o#tag_info _x_i3 - in Caml_block (_x, _x_i1, _x_i2, _x_i3) - | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x - | Number _x -> let _x = o#number _x in Number _x - | Object _x -> let _x = o#property_map _x in Object _x - | Undefined -> Undefined - | Null -> Null - method expression : expression -> expression = - fun { expression_desc = _x; comment = _x_i1 } -> - let _x = o#expression_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { expression_desc = _x; comment = _x_i1; } - method exports : exports -> exports = o#unknown - method exception_ident : exception_ident -> exception_ident = o#ident - method deps_program : deps_program -> deps_program = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let _x = o#program _x in - let _x_i1 = o#required_modules _x_i1 in - let _x_i2 = o#option (fun o -> o#string) _x_i2 - in { program = _x; modules = _x_i1; side_effect = _x_i2; } - method case_clause : - 'a 'a_out. - ('self_type -> 'a -> 'a_out) -> 'a case_clause -> 'a_out case_clause = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let _x = _f_a o _x in - let _x_i1 = o#block _x_i1 in - let _x_i2 = o#bool _x_i2 in - let _x_i3 = o#option (fun o -> o#string) _x_i3 - in - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3; - } - method block : block -> block = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -108512,7 +108498,7 @@ let eval (arg : J.expression) (dispatches : (string * string) list ) : E.t = E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -108540,7 +108526,7 @@ let eval_as_event (arg : J.expression) (dispatches : (string * string) list opti (S.string_switch (E.poly_var_tag_access arg) (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -108572,7 +108558,7 @@ let eval_as_int (arg : J.expression) (dispatches : (string * int) list ) : E.t E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.int (Int32.of_int r))]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -113747,7 +113733,7 @@ and compile_general_cases Lam_compile_context.t -> (?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> 'a J.case_clause list -> J.statement) -> + _ -> ('a * J.case_clause) list -> J.statement) -> _ -> ('a * Lam.t) list -> default_case -> J.block = fun @@ -113758,7 +113744,7 @@ and compile_general_cases (switch : ?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> _ J.case_clause list -> J.statement + _ -> (_ * J.case_clause) list -> J.statement ) (switch_exp : J.expression) (cases : (_ * Lam.t) list) @@ -113828,13 +113814,13 @@ and compile_general_cases should_break else should_break && Lam_exit_code.has_exit lam in - {J.switch_case ; + switch_case , J.{ switch_body; should_break; comment = make_comment switch_case; } else - { switch_case; switch_body = []; should_break = false; comment = make_comment switch_case; } + switch_case, {switch_body = []; should_break = false; comment = make_comment switch_case; } ) (* TODO: we should also group default *) diff --git a/lib/4.06.1/unstable/js_refmt_compiler.ml b/lib/4.06.1/unstable/js_refmt_compiler.ml index 4d6379de0b..ddebc15981 100644 --- a/lib/4.06.1/unstable/js_refmt_compiler.ml +++ b/lib/4.06.1/unstable/js_refmt_compiler.ml @@ -86060,8 +86060,8 @@ and statement_desc = {[ goto : label option ; ]} *) - | Int_switch of expression * int case_clause list * block option - | String_switch of expression * string case_clause list * block option + | Int_switch of expression * int_clause list * block option + | String_switch of expression * string_clause list * block option | Throw of expression | Try of block * (exception_ident * block) option * block option | Debugger @@ -86084,9 +86084,9 @@ and variable_declaration = { property : property; ident_info : ident_info; } - -and 'a case_clause = { - switch_case : 'a ; +and string_clause = string * case_clause +and int_clause = int * case_clause +and case_clause = { switch_body : block ; should_break : bool ; (* true means break *) comment : string option ; @@ -86557,6 +86557,9 @@ class virtual fold = let o = o#option (fun o -> o#expression) _x_i1 in let o = o#property _x_i2 in let o = o#ident_info _x_i3 in o method tag_info : tag_info -> 'self_type = o#unknown + method string_clause : string_clause -> 'self_type = + fun (_x, _x_i1) -> + let o = o#string _x in let o = o#case_clause _x_i1 in o method statement_desc : statement_desc -> 'self_type = function | Block _x -> let o = o#block _x in o @@ -86580,10 +86583,28 @@ class virtual fold = | Return _x -> let o = o#expression _x in o | Int_switch (_x, _x_i1, _x_i2) -> let o = o#expression _x in + let o = o#list (fun o -> o#int_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | String_switch (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#string_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Throw _x -> let o = o#expression _x in o + | Try (_x, _x_i1, _x_i2) -> + let o = o#block _x in let o = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + o#option + (fun o (_x, _x_i1) -> + let o = o#exception_ident _x in let o = o#block _x_i1 in o) + _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Debugger -> o + method statement : statement -> 'self_type = + fun { statement_desc = _x; comment = _x_i1 } -> + let o = o#statement_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method required_modules : required_modules -> 'self_type = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. * * 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 @@ -86606,7 +86627,7 @@ class virtual fold = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -86614,15 +86635,18 @@ class virtual fold = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> 'self_type = o#unknown + method property_map : property_map -> 'self_type = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -86637,7 +86661,74 @@ class virtual fold = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let o = o#property_name _x in let o = o#expression _x_i1 in o) + method property : property -> 'self_type = o#unknown + method program : program -> 'self_type = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let o = o#block _x in + let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o + method number : number -> 'self_type = o#unknown + method mutable_flag : mutable_flag -> 'self_type = o#unknown + method module_id : module_id -> 'self_type = + fun { id = _x; kind = _x_i1 } -> + let o = o#ident _x in let o = o#unknown _x_i1 in o + method length_object : length_object -> 'self_type = o#unknown + method label : label -> 'self_type = o#string + method kind : kind -> 'self_type = o#unknown + method jsint : jsint -> 'self_type = o#int32 + method int_op : int_op -> 'self_type = o#unknown + method int_clause : int_clause -> 'self_type = + fun (_x, _x_i1) -> let o = o#int _x in let o = o#case_clause _x_i1 in o + method ident_info : ident_info -> 'self_type = o#unknown + method ident : ident -> 'self_type = o#unknown + method for_ident_expression : for_ident_expression -> 'self_type = + o#expression + method for_ident : for_ident -> 'self_type = o#ident + method for_direction : for_direction -> 'self_type = o#unknown + method finish_ident_expression : finish_ident_expression -> 'self_type = + o#expression + method expression_desc : expression_desc -> 'self_type = + function + | Length (_x, _x_i1) -> + let o = o#expression _x in let o = o#length_object _x_i1 in o + | Char_of_int _x -> let o = o#expression _x in o + | Char_to_int _x -> let o = o#expression _x in o + | Is_null_or_undefined _x -> let o = o#expression _x in o + | String_append (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Bool _x -> let o = o#bool _x in o + | Typeof _x -> let o = o#expression _x in o + | Js_not _x -> let o = o#expression _x in o + | Seq (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Cond (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | Bin (_x, _x_i1, _x_i2) -> + let o = o#binop _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | FlatCall (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Call (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#expression) _x_i1 in + let o = o#unknown _x_i2 in o + | String_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Array_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Static_index (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#string _x_i1 in + let o = o#option (fun o -> o#int32) _x_i2 in o + | New (_x, _x_i1) -> + let o = o#expression _x in + let o = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -86672,11 +86763,52 @@ class virtual fold = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in o + | Var _x -> let o = o#vident _x in o + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#bool _x in + let o = o#list (fun o -> o#ident) _x_i1 in + let o = o#block _x_i2 in let o = o#unknown _x_i3 in o + | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o + | Unicode _x -> let o = o#string _x in o + | Raw_js_code _x -> let o = o#unknown _x in o + | Array (_x, _x_i1) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in o + | Optional_block (_x, _x_i1) -> + let o = o#expression _x in let o = o#bool _x_i1 in o + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in + let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o + | Caml_block_tag _x -> let o = o#expression _x in o + | Number _x -> let o = o#number _x in o + | Object _x -> let o = o#property_map _x in o + | Undefined -> o + | Null -> o + method expression : expression -> 'self_type = + fun { expression_desc = _x; comment = _x_i1 } -> + let o = o#expression_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method exports : exports -> 'self_type = o#unknown + method exception_ident : exception_ident -> 'self_type = o#ident + method deps_program : deps_program -> 'self_type = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let o = o#program _x in + let o = o#required_modules _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method case_clause : case_clause -> 'self_type = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let o = o#block _x in + let o = o#bool _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method block : block -> 'self_type = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -86684,13 +86816,13 @@ class virtual fold = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -86699,20 +86831,20 @@ class virtual fold = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -86738,7 +86870,7 @@ class virtual fold = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -86747,7 +86879,7 @@ class virtual fold = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -86759,7 +86891,7 @@ class virtual fold = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -86769,12 +86901,12 @@ class virtual fold = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -86784,143 +86916,7 @@ class virtual fold = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | String_switch (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Throw _x -> let o = o#expression _x in o - | Try (_x, _x_i1, _x_i2) -> - let o = o#block _x in - let o = - o#option - (fun o (_x, _x_i1) -> - let o = o#exception_ident _x in let o = o#block _x_i1 in o) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Debugger -> o - method statement : statement -> 'self_type = - fun { statement_desc = _x; comment = _x_i1 } -> - let o = o#statement_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method required_modules : required_modules -> 'self_type = - o#list (fun o -> o#module_id) - method property_name : property_name -> 'self_type = o#unknown - method property_map : property_map -> 'self_type = - o#list - (fun o (_x, _x_i1) -> - let o = o#property_name _x in let o = o#expression _x_i1 in o) - method property : property -> 'self_type = o#unknown - method program : program -> 'self_type = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let o = o#block _x in - let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o - method number : number -> 'self_type = o#unknown - method mutable_flag : mutable_flag -> 'self_type = o#unknown - method module_id : module_id -> 'self_type = - fun { id = _x; kind = _x_i1 } -> - let o = o#ident _x in let o = o#unknown _x_i1 in o - method length_object : length_object -> 'self_type = o#unknown - method label : label -> 'self_type = o#string - method kind : kind -> 'self_type = o#unknown - method jsint : jsint -> 'self_type = o#int32 - method int_op : int_op -> 'self_type = o#unknown - method ident_info : ident_info -> 'self_type = o#unknown - method ident : ident -> 'self_type = o#unknown - method for_ident_expression : for_ident_expression -> 'self_type = - o#expression - method for_ident : for_ident -> 'self_type = o#ident - method for_direction : for_direction -> 'self_type = o#unknown - method finish_ident_expression : finish_ident_expression -> 'self_type = - o#expression - method expression_desc : expression_desc -> 'self_type = - function - | Length (_x, _x_i1) -> - let o = o#expression _x in let o = o#length_object _x_i1 in o - | Char_of_int _x -> let o = o#expression _x in o - | Char_to_int _x -> let o = o#expression _x in o - | Is_null_or_undefined _x -> let o = o#expression _x in o - | String_append (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Bool _x -> let o = o#bool _x in o - | Typeof _x -> let o = o#expression _x in o - | Js_not _x -> let o = o#expression _x in o - | Seq (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Cond (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | Bin (_x, _x_i1, _x_i2) -> - let o = o#binop _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | FlatCall (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Call (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#list (fun o -> o#expression) _x_i1 in - let o = o#unknown _x_i2 in o - | String_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Array_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Static_index (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#string _x_i1 in - let o = o#option (fun o -> o#int32) _x_i2 in o - | New (_x, _x_i1) -> - let o = o#expression _x in - let o = o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in o - | Var _x -> let o = o#vident _x in o - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#bool _x in - let o = o#list (fun o -> o#ident) _x_i1 in - let o = o#block _x_i2 in let o = o#unknown _x_i3 in o - | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o - | Unicode _x -> let o = o#string _x in o - | Raw_js_code _x -> let o = o#unknown _x in o - | Array (_x, _x_i1) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in o - | Optional_block (_x, _x_i1) -> - let o = o#expression _x in let o = o#bool _x_i1 in o - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in - let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o - | Caml_block_tag _x -> let o = o#expression _x in o - | Number _x -> let o = o#number _x in o - | Object _x -> let o = o#property_map _x in o - | Undefined -> o - | Null -> o - method expression : expression -> 'self_type = - fun { expression_desc = _x; comment = _x_i1 } -> - let o = o#expression_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method exports : exports -> 'self_type = o#unknown - method exception_ident : exception_ident -> 'self_type = o#ident - method deps_program : deps_program -> 'self_type = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let o = o#program _x in - let o = o#required_modules _x_i1 in - let o = o#option (fun o -> o#string) _x_i2 in o - method case_clause : - 'a. ('self_type -> 'a -> 'self_type) -> 'a case_clause -> 'self_type = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let o = _f_a o _x in - let o = o#block _x_i1 in - let o = o#bool _x_i2 in - let o = o#option (fun o -> o#string) _x_i3 in o - method block : block -> 'self_type = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -90313,9 +90309,9 @@ and pp_function ~is_method since it can be either [int] or [string] *) and pp_one_case_clause : 'a . - _ -> P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause -> _ + _ -> P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) -> _ = fun cxt f pp_cond - ({switch_case; switch_body ; should_break; comment; } : _ J.case_clause) -> + (switch_case, ({switch_body ; should_break; comment; } : J.case_clause)) -> let cxt = P.group f 1 (fun _ -> P.group f 1 (fun _ -> @@ -90345,7 +90341,7 @@ and pp_one_case_clause : 'a . cxt and loop_case_clauses : 'a . cxt -> - P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause list -> cxt + P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) list -> cxt = fun cxt f pp_cond cases -> Ext_list.fold_left cases cxt (fun acc x -> pp_one_case_clause acc f pp_cond x) @@ -99589,7 +99585,7 @@ val int_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - int J.case_clause list -> + (int * J.case_clause) list -> t val string_switch : @@ -99597,7 +99593,7 @@ val string_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - string J.case_clause list -> + (string * J.case_clause) list -> t (** Just declaration without initialization *) @@ -99807,13 +99803,13 @@ let int_switch ?(declaration : (J.property * Ident.t) option ) ?(default : J.block option) (e : J.expression) - (clauses : int J.case_clause list): t = + (clauses : (int * J.case_clause) list): t = match e.expression_desc with | Number (Int {i; _}) -> let continuation = match Ext_list.find_opt clauses - (fun x -> - if x.switch_case = Int32.to_int i then + (fun (switch_case,x) -> + if switch_case = Int32.to_int i then Some x.switch_body else None ) with | Some case -> case @@ -99846,12 +99842,12 @@ let string_switch ?(declaration : (J.property * Ident.t) option) ?(default : J.block option) (e : J.expression) - (clauses : string J.case_clause list): t= + (clauses : (string * J.case_clause) list): t= match e.expression_desc with | Str (_,s) -> let continuation = - match Ext_list.find_opt clauses (fun x -> - if x.switch_case = s then + match Ext_list.find_opt clauses (fun (switch_case, x) -> + if switch_case = s then Some x.switch_body else None ) with @@ -101742,6 +101738,10 @@ class virtual map = { ident = _x; value = _x_i1; property = _x_i2; ident_info = _x_i3; } method tag_info : tag_info -> tag_info = o#unknown + method string_clause : string_clause -> string_clause = + fun (_x, _x_i1) -> + let _x = o#string _x in + let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) method statement_desc : statement_desc -> statement_desc = function | Block _x -> let _x = o#block _x in Block _x @@ -101769,14 +101769,37 @@ class virtual map = | Return _x -> let _x = o#expression _x in Return _x | Int_switch (_x, _x_i1, _x_i2) -> let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#int_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Int_switch (_x, _x_i1, _x_i2) + | String_switch (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#string_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in String_switch (_x, _x_i1, _x_i2) + | Throw _x -> let _x = o#expression _x in Throw _x + | Try (_x, _x_i1, _x_i2) -> + let _x = o#block _x in let _x_i1 = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * 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 - * the Free Software Foundation, either version 3 of the License, or + o#option + (fun o (_x, _x_i1) -> + let _x = o#exception_ident _x in + let _x_i1 = o#block _x_i1 in (_x, _x_i1)) + _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Try (_x, _x_i1, _x_i2) + | Debugger -> Debugger + method statement : statement -> statement = + fun { statement_desc = _x; comment = _x_i1 } -> + let _x = o#statement_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { statement_desc = _x; comment = _x_i1; } + method required_modules : required_modules -> required_modules = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + * + * 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 + * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * In addition to the permissions granted to you by the LGPL, you may combine @@ -101795,7 +101818,7 @@ class virtual map = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -101803,15 +101826,18 @@ class virtual map = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> property_name = o#unknown + method property_map : property_map -> property_map = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -101826,7 +101852,89 @@ class virtual map = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let _x = o#property_name _x in + let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) + method property : property -> property = o#unknown + method program : program -> program = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#exports _x_i1 in + let _x_i2 = o#unknown _x_i2 + in { block = _x; exports = _x_i1; export_set = _x_i2; } + method number : number -> number = o#unknown + method mutable_flag : mutable_flag -> mutable_flag = o#unknown + method module_id : module_id -> module_id = + fun { id = _x; kind = _x_i1 } -> + let _x = o#ident _x in + let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } + method length_object : length_object -> length_object = o#unknown + method label : label -> label = o#string + method kind : kind -> kind = o#unknown + method jsint : jsint -> jsint = o#int32 + method int_op : int_op -> int_op = o#unknown + method int_clause : int_clause -> int_clause = + fun (_x, _x_i1) -> + let _x = o#int _x in let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) + method ident_info : ident_info -> ident_info = o#unknown + method ident : ident -> ident = o#unknown + method for_ident_expression : + for_ident_expression -> for_ident_expression = o#expression + method for_ident : for_ident -> for_ident = o#ident + method for_direction : for_direction -> for_direction = o#unknown + method finish_ident_expression : + finish_ident_expression -> finish_ident_expression = o#expression + method expression_desc : expression_desc -> expression_desc = + function + | Length (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) + | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x + | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x + | Is_null_or_undefined _x -> + let _x = o#expression _x in Is_null_or_undefined _x + | String_append (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) + | Bool _x -> let _x = o#bool _x in Bool _x + | Typeof _x -> let _x = o#expression _x in Typeof _x + | Js_not _x -> let _x = o#expression _x in Js_not _x + | Seq (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) + | Cond (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) + | Bin (_x, _x_i1, _x_i2) -> + let _x = o#binop _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) + | FlatCall (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) + | Call (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#expression) _x_i1 in + let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) + | String_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) + | Array_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) + | Static_index (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#string _x_i1 in + let _x_i2 = o#option (fun o -> o#int32) _x_i2 + in Static_index (_x, _x_i1, _x_i2) + | New (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -101861,11 +101969,60 @@ class virtual map = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in New (_x, _x_i1) + | Var _x -> let _x = o#vident _x in Var _x + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#bool _x in + let _x_i1 = o#list (fun o -> o#ident) _x_i1 in + let _x_i2 = o#block _x_i2 in + let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) + | Str (_x, _x_i1) -> + let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) + | Unicode _x -> let _x = o#string _x in Unicode _x + | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x + | Array (_x, _x_i1) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) + | Optional_block (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in + let _x_i2 = o#expression _x_i2 in + let _x_i3 = o#tag_info _x_i3 + in Caml_block (_x, _x_i1, _x_i2, _x_i3) + | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x + | Number _x -> let _x = o#number _x in Number _x + | Object _x -> let _x = o#property_map _x in Object _x + | Undefined -> Undefined + | Null -> Null + method expression : expression -> expression = + fun { expression_desc = _x; comment = _x_i1 } -> + let _x = o#expression_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { expression_desc = _x; comment = _x_i1; } + method exports : exports -> exports = o#unknown + method exception_ident : exception_ident -> exception_ident = o#ident + method deps_program : deps_program -> deps_program = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let _x = o#program _x in + let _x_i1 = o#required_modules _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { program = _x; modules = _x_i1; side_effect = _x_i2; } + method case_clause : case_clause -> case_clause = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#bool _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { switch_body = _x; should_break = _x_i1; comment = _x_i2; } + method block : block -> block = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -101873,13 +102030,13 @@ class virtual map = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -101888,20 +102045,20 @@ class virtual map = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -101927,7 +102084,7 @@ class virtual map = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -101936,7 +102093,7 @@ class virtual map = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -101948,7 +102105,7 @@ class virtual map = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -101958,12 +102115,12 @@ class virtual map = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -101973,178 +102130,7 @@ class virtual map = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Int_switch (_x, _x_i1, _x_i2) - | String_switch (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in String_switch (_x, _x_i1, _x_i2) - | Throw _x -> let _x = o#expression _x in Throw _x - | Try (_x, _x_i1, _x_i2) -> - let _x = o#block _x in - let _x_i1 = - o#option - (fun o (_x, _x_i1) -> - let _x = o#exception_ident _x in - let _x_i1 = o#block _x_i1 in (_x, _x_i1)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Try (_x, _x_i1, _x_i2) - | Debugger -> Debugger - method statement : statement -> statement = - fun { statement_desc = _x; comment = _x_i1 } -> - let _x = o#statement_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { statement_desc = _x; comment = _x_i1; } - method required_modules : required_modules -> required_modules = - o#list (fun o -> o#module_id) - method property_name : property_name -> property_name = o#unknown - method property_map : property_map -> property_map = - o#list - (fun o (_x, _x_i1) -> - let _x = o#property_name _x in - let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) - method property : property -> property = o#unknown - method program : program -> program = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let _x = o#block _x in - let _x_i1 = o#exports _x_i1 in - let _x_i2 = o#unknown _x_i2 - in { block = _x; exports = _x_i1; export_set = _x_i2; } - method number : number -> number = o#unknown - method mutable_flag : mutable_flag -> mutable_flag = o#unknown - method module_id : module_id -> module_id = - fun { id = _x; kind = _x_i1 } -> - let _x = o#ident _x in - let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } - method length_object : length_object -> length_object = o#unknown - method label : label -> label = o#string - method kind : kind -> kind = o#unknown - method jsint : jsint -> jsint = o#int32 - method int_op : int_op -> int_op = o#unknown - method ident_info : ident_info -> ident_info = o#unknown - method ident : ident -> ident = o#unknown - method for_ident_expression : - for_ident_expression -> for_ident_expression = o#expression - method for_ident : for_ident -> for_ident = o#ident - method for_direction : for_direction -> for_direction = o#unknown - method finish_ident_expression : - finish_ident_expression -> finish_ident_expression = o#expression - method expression_desc : expression_desc -> expression_desc = - function - | Length (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) - | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x - | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x - | Is_null_or_undefined _x -> - let _x = o#expression _x in Is_null_or_undefined _x - | String_append (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) - | Bool _x -> let _x = o#bool _x in Bool _x - | Typeof _x -> let _x = o#expression _x in Typeof _x - | Js_not _x -> let _x = o#expression _x in Js_not _x - | Seq (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) - | Cond (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) - | Bin (_x, _x_i1, _x_i2) -> - let _x = o#binop _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) - | FlatCall (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) - | Call (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#list (fun o -> o#expression) _x_i1 in - let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) - | String_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) - | Array_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) - | Static_index (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#string _x_i1 in - let _x_i2 = o#option (fun o -> o#int32) _x_i2 - in Static_index (_x, _x_i1, _x_i2) - | New (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = - o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in New (_x, _x_i1) - | Var _x -> let _x = o#vident _x in Var _x - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#bool _x in - let _x_i1 = o#list (fun o -> o#ident) _x_i1 in - let _x_i2 = o#block _x_i2 in - let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) - | Str (_x, _x_i1) -> - let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) - | Unicode _x -> let _x = o#string _x in Unicode _x - | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x - | Array (_x, _x_i1) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) - | Optional_block (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in - let _x_i2 = o#expression _x_i2 in - let _x_i3 = o#tag_info _x_i3 - in Caml_block (_x, _x_i1, _x_i2, _x_i3) - | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x - | Number _x -> let _x = o#number _x in Number _x - | Object _x -> let _x = o#property_map _x in Object _x - | Undefined -> Undefined - | Null -> Null - method expression : expression -> expression = - fun { expression_desc = _x; comment = _x_i1 } -> - let _x = o#expression_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { expression_desc = _x; comment = _x_i1; } - method exports : exports -> exports = o#unknown - method exception_ident : exception_ident -> exception_ident = o#ident - method deps_program : deps_program -> deps_program = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let _x = o#program _x in - let _x_i1 = o#required_modules _x_i1 in - let _x_i2 = o#option (fun o -> o#string) _x_i2 - in { program = _x; modules = _x_i1; side_effect = _x_i2; } - method case_clause : - 'a 'a_out. - ('self_type -> 'a -> 'a_out) -> 'a case_clause -> 'a_out case_clause = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let _x = _f_a o _x in - let _x_i1 = o#block _x_i1 in - let _x_i2 = o#bool _x_i2 in - let _x_i3 = o#option (fun o -> o#string) _x_i3 - in - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3; - } - method block : block -> block = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -108512,7 +108498,7 @@ let eval (arg : J.expression) (dispatches : (string * string) list ) : E.t = E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -108540,7 +108526,7 @@ let eval_as_event (arg : J.expression) (dispatches : (string * string) list opti (S.string_switch (E.poly_var_tag_access arg) (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -108572,7 +108558,7 @@ let eval_as_int (arg : J.expression) (dispatches : (string * int) list ) : E.t E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.int (Int32.of_int r))]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -113747,7 +113733,7 @@ and compile_general_cases Lam_compile_context.t -> (?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> 'a J.case_clause list -> J.statement) -> + _ -> ('a * J.case_clause) list -> J.statement) -> _ -> ('a * Lam.t) list -> default_case -> J.block = fun @@ -113758,7 +113744,7 @@ and compile_general_cases (switch : ?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> _ J.case_clause list -> J.statement + _ -> (_ * J.case_clause) list -> J.statement ) (switch_exp : J.expression) (cases : (_ * Lam.t) list) @@ -113828,13 +113814,13 @@ and compile_general_cases should_break else should_break && Lam_exit_code.has_exit lam in - {J.switch_case ; + switch_case , J.{ switch_body; should_break; comment = make_comment switch_case; } else - { switch_case; switch_body = []; should_break = false; comment = make_comment switch_case; } + switch_case, {switch_body = []; should_break = false; comment = make_comment switch_case; } ) (* TODO: we should also group default *) diff --git a/lib/4.06.1/whole_compiler.ml b/lib/4.06.1/whole_compiler.ml index 8023a8efc7..a13379040a 100644 --- a/lib/4.06.1/whole_compiler.ml +++ b/lib/4.06.1/whole_compiler.ml @@ -370301,8 +370301,8 @@ and statement_desc = {[ goto : label option ; ]} *) - | Int_switch of expression * int case_clause list * block option - | String_switch of expression * string case_clause list * block option + | Int_switch of expression * int_clause list * block option + | String_switch of expression * string_clause list * block option | Throw of expression | Try of block * (exception_ident * block) option * block option | Debugger @@ -370325,9 +370325,9 @@ and variable_declaration = { property : property; ident_info : ident_info; } - -and 'a case_clause = { - switch_case : 'a ; +and string_clause = string * case_clause +and int_clause = int * case_clause +and case_clause = { switch_body : block ; should_break : bool ; (* true means break *) comment : string option ; @@ -376424,6 +376424,9 @@ class virtual fold = let o = o#option (fun o -> o#expression) _x_i1 in let o = o#property _x_i2 in let o = o#ident_info _x_i3 in o method tag_info : tag_info -> 'self_type = o#unknown + method string_clause : string_clause -> 'self_type = + fun (_x, _x_i1) -> + let o = o#string _x in let o = o#case_clause _x_i1 in o method statement_desc : statement_desc -> 'self_type = function | Block _x -> let o = o#block _x in o @@ -376447,10 +376450,28 @@ class virtual fold = | Return _x -> let o = o#expression _x in o | Int_switch (_x, _x_i1, _x_i2) -> let o = o#expression _x in + let o = o#list (fun o -> o#int_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | String_switch (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#string_clause) _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Throw _x -> let o = o#expression _x in o + | Try (_x, _x_i1, _x_i2) -> + let o = o#block _x in let o = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + o#option + (fun o (_x, _x_i1) -> + let o = o#exception_ident _x in let o = o#block _x_i1 in o) + _x_i1 in + let o = o#option (fun o -> o#block) _x_i2 in o + | Debugger -> o + method statement : statement -> 'self_type = + fun { statement_desc = _x; comment = _x_i1 } -> + let o = o#statement_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method required_modules : required_modules -> 'self_type = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. * * 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 @@ -376473,7 +376494,7 @@ class virtual fold = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -376481,15 +376502,18 @@ class virtual fold = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> 'self_type = o#unknown + method property_map : property_map -> 'self_type = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -376504,7 +376528,74 @@ class virtual fold = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let o = o#property_name _x in let o = o#expression _x_i1 in o) + method property : property -> 'self_type = o#unknown + method program : program -> 'self_type = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let o = o#block _x in + let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o + method number : number -> 'self_type = o#unknown + method mutable_flag : mutable_flag -> 'self_type = o#unknown + method module_id : module_id -> 'self_type = + fun { id = _x; kind = _x_i1 } -> + let o = o#ident _x in let o = o#unknown _x_i1 in o + method length_object : length_object -> 'self_type = o#unknown + method label : label -> 'self_type = o#string + method kind : kind -> 'self_type = o#unknown + method jsint : jsint -> 'self_type = o#int32 + method int_op : int_op -> 'self_type = o#unknown + method int_clause : int_clause -> 'self_type = + fun (_x, _x_i1) -> let o = o#int _x in let o = o#case_clause _x_i1 in o + method ident_info : ident_info -> 'self_type = o#unknown + method ident : ident -> 'self_type = o#unknown + method for_ident_expression : for_ident_expression -> 'self_type = + o#expression + method for_ident : for_ident -> 'self_type = o#ident + method for_direction : for_direction -> 'self_type = o#unknown + method finish_ident_expression : finish_ident_expression -> 'self_type = + o#expression + method expression_desc : expression_desc -> 'self_type = + function + | Length (_x, _x_i1) -> + let o = o#expression _x in let o = o#length_object _x_i1 in o + | Char_of_int _x -> let o = o#expression _x in o + | Char_to_int _x -> let o = o#expression _x in o + | Is_null_or_undefined _x -> let o = o#expression _x in o + | String_append (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Bool _x -> let o = o#bool _x in o + | Typeof _x -> let o = o#expression _x in o + | Js_not _x -> let o = o#expression _x in o + | Seq (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Cond (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | Bin (_x, _x_i1, _x_i2) -> + let o = o#binop _x in + let o = o#expression _x_i1 in let o = o#expression _x_i2 in o + | FlatCall (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Call (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#list (fun o -> o#expression) _x_i1 in + let o = o#unknown _x_i2 in o + | String_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Array_index (_x, _x_i1) -> + let o = o#expression _x in let o = o#expression _x_i1 in o + | Static_index (_x, _x_i1, _x_i2) -> + let o = o#expression _x in + let o = o#string _x_i1 in + let o = o#option (fun o -> o#int32) _x_i2 in o + | New (_x, _x_i1) -> + let o = o#expression _x in + let o = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -376539,11 +376630,52 @@ class virtual fold = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in o + | Var _x -> let o = o#vident _x in o + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#bool _x in + let o = o#list (fun o -> o#ident) _x_i1 in + let o = o#block _x_i2 in let o = o#unknown _x_i3 in o + | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o + | Unicode _x -> let o = o#string _x in o + | Raw_js_code _x -> let o = o#unknown _x in o + | Array (_x, _x_i1) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in o + | Optional_block (_x, _x_i1) -> + let o = o#expression _x in let o = o#bool _x_i1 in o + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let o = o#list (fun o -> o#expression) _x in + let o = o#mutable_flag _x_i1 in + let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o + | Caml_block_tag _x -> let o = o#expression _x in o + | Number _x -> let o = o#number _x in o + | Object _x -> let o = o#property_map _x in o + | Undefined -> o + | Null -> o + method expression : expression -> 'self_type = + fun { expression_desc = _x; comment = _x_i1 } -> + let o = o#expression_desc _x in + let o = o#option (fun o -> o#string) _x_i1 in o + method exports : exports -> 'self_type = o#unknown + method exception_ident : exception_ident -> 'self_type = o#ident + method deps_program : deps_program -> 'self_type = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let o = o#program _x in + let o = o#required_modules _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method case_clause : case_clause -> 'self_type = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let o = o#block _x in + let o = o#bool _x_i1 in + let o = o#option (fun o -> o#string) _x_i2 in o + method block : block -> 'self_type = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -376551,13 +376683,13 @@ class virtual fold = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -376566,20 +376698,20 @@ class virtual fold = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -376605,7 +376737,7 @@ class virtual fold = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -376614,7 +376746,7 @@ class virtual fold = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -376626,7 +376758,7 @@ class virtual fold = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -376636,12 +376768,12 @@ class virtual fold = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -376651,143 +376783,7 @@ class virtual fold = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | String_switch (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Throw _x -> let o = o#expression _x in o - | Try (_x, _x_i1, _x_i2) -> - let o = o#block _x in - let o = - o#option - (fun o (_x, _x_i1) -> - let o = o#exception_ident _x in let o = o#block _x_i1 in o) - _x_i1 in - let o = o#option (fun o -> o#block) _x_i2 in o - | Debugger -> o - method statement : statement -> 'self_type = - fun { statement_desc = _x; comment = _x_i1 } -> - let o = o#statement_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method required_modules : required_modules -> 'self_type = - o#list (fun o -> o#module_id) - method property_name : property_name -> 'self_type = o#unknown - method property_map : property_map -> 'self_type = - o#list - (fun o (_x, _x_i1) -> - let o = o#property_name _x in let o = o#expression _x_i1 in o) - method property : property -> 'self_type = o#unknown - method program : program -> 'self_type = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let o = o#block _x in - let o = o#exports _x_i1 in let o = o#unknown _x_i2 in o - method number : number -> 'self_type = o#unknown - method mutable_flag : mutable_flag -> 'self_type = o#unknown - method module_id : module_id -> 'self_type = - fun { id = _x; kind = _x_i1 } -> - let o = o#ident _x in let o = o#unknown _x_i1 in o - method length_object : length_object -> 'self_type = o#unknown - method label : label -> 'self_type = o#string - method kind : kind -> 'self_type = o#unknown - method jsint : jsint -> 'self_type = o#int32 - method int_op : int_op -> 'self_type = o#unknown - method ident_info : ident_info -> 'self_type = o#unknown - method ident : ident -> 'self_type = o#unknown - method for_ident_expression : for_ident_expression -> 'self_type = - o#expression - method for_ident : for_ident -> 'self_type = o#ident - method for_direction : for_direction -> 'self_type = o#unknown - method finish_ident_expression : finish_ident_expression -> 'self_type = - o#expression - method expression_desc : expression_desc -> 'self_type = - function - | Length (_x, _x_i1) -> - let o = o#expression _x in let o = o#length_object _x_i1 in o - | Char_of_int _x -> let o = o#expression _x in o - | Char_to_int _x -> let o = o#expression _x in o - | Is_null_or_undefined _x -> let o = o#expression _x in o - | String_append (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Bool _x -> let o = o#bool _x in o - | Typeof _x -> let o = o#expression _x in o - | Js_not _x -> let o = o#expression _x in o - | Seq (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Cond (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | Bin (_x, _x_i1, _x_i2) -> - let o = o#binop _x in - let o = o#expression _x_i1 in let o = o#expression _x_i2 in o - | FlatCall (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Call (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#list (fun o -> o#expression) _x_i1 in - let o = o#unknown _x_i2 in o - | String_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Array_index (_x, _x_i1) -> - let o = o#expression _x in let o = o#expression _x_i1 in o - | Static_index (_x, _x_i1, _x_i2) -> - let o = o#expression _x in - let o = o#string _x_i1 in - let o = o#option (fun o -> o#int32) _x_i2 in o - | New (_x, _x_i1) -> - let o = o#expression _x in - let o = o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in o - | Var _x -> let o = o#vident _x in o - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#bool _x in - let o = o#list (fun o -> o#ident) _x_i1 in - let o = o#block _x_i2 in let o = o#unknown _x_i3 in o - | Str (_x, _x_i1) -> let o = o#bool _x in let o = o#string _x_i1 in o - | Unicode _x -> let o = o#string _x in o - | Raw_js_code _x -> let o = o#unknown _x in o - | Array (_x, _x_i1) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in o - | Optional_block (_x, _x_i1) -> - let o = o#expression _x in let o = o#bool _x_i1 in o - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let o = o#list (fun o -> o#expression) _x in - let o = o#mutable_flag _x_i1 in - let o = o#expression _x_i2 in let o = o#tag_info _x_i3 in o - | Caml_block_tag _x -> let o = o#expression _x in o - | Number _x -> let o = o#number _x in o - | Object _x -> let o = o#property_map _x in o - | Undefined -> o - | Null -> o - method expression : expression -> 'self_type = - fun { expression_desc = _x; comment = _x_i1 } -> - let o = o#expression_desc _x in - let o = o#option (fun o -> o#string) _x_i1 in o - method exports : exports -> 'self_type = o#unknown - method exception_ident : exception_ident -> 'self_type = o#ident - method deps_program : deps_program -> 'self_type = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let o = o#program _x in - let o = o#required_modules _x_i1 in - let o = o#option (fun o -> o#string) _x_i2 in o - method case_clause : - 'a. ('self_type -> 'a -> 'self_type) -> 'a case_clause -> 'self_type = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let o = _f_a o _x in - let o = o#block _x_i1 in - let o = o#bool _x_i2 in - let o = o#option (fun o -> o#string) _x_i3 in o - method block : block -> 'self_type = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -380180,9 +380176,9 @@ and pp_function ~is_method since it can be either [int] or [string] *) and pp_one_case_clause : 'a . - _ -> P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause -> _ + _ -> P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) -> _ = fun cxt f pp_cond - ({switch_case; switch_body ; should_break; comment; } : _ J.case_clause) -> + (switch_case, ({switch_body ; should_break; comment; } : J.case_clause)) -> let cxt = P.group f 1 (fun _ -> P.group f 1 (fun _ -> @@ -380212,7 +380208,7 @@ and pp_one_case_clause : 'a . cxt and loop_case_clauses : 'a . cxt -> - P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause list -> cxt + P.t -> (P.t -> 'a -> unit) -> ('a * J.case_clause) list -> cxt = fun cxt f pp_cond cases -> Ext_list.fold_left cases cxt (fun acc x -> pp_one_case_clause acc f pp_cond x) @@ -382071,7 +382067,7 @@ val int_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - int J.case_clause list -> + (int * J.case_clause) list -> t val string_switch : @@ -382079,7 +382075,7 @@ val string_switch : ?declaration:Lam_compat.let_kind * Ident.t -> ?default:J.block -> J.expression -> - string J.case_clause list -> + (string * J.case_clause) list -> t (** Just declaration without initialization *) @@ -382289,13 +382285,13 @@ let int_switch ?(declaration : (J.property * Ident.t) option ) ?(default : J.block option) (e : J.expression) - (clauses : int J.case_clause list): t = + (clauses : (int * J.case_clause) list): t = match e.expression_desc with | Number (Int {i; _}) -> let continuation = match Ext_list.find_opt clauses - (fun x -> - if x.switch_case = Int32.to_int i then + (fun (switch_case,x) -> + if switch_case = Int32.to_int i then Some x.switch_body else None ) with | Some case -> case @@ -382328,12 +382324,12 @@ let string_switch ?(declaration : (J.property * Ident.t) option) ?(default : J.block option) (e : J.expression) - (clauses : string J.case_clause list): t= + (clauses : (string * J.case_clause) list): t= match e.expression_desc with | Str (_,s) -> let continuation = - match Ext_list.find_opt clauses (fun x -> - if x.switch_case = s then + match Ext_list.find_opt clauses (fun (switch_case, x) -> + if switch_case = s then Some x.switch_body else None ) with @@ -384224,6 +384220,10 @@ class virtual map = { ident = _x; value = _x_i1; property = _x_i2; ident_info = _x_i3; } method tag_info : tag_info -> tag_info = o#unknown + method string_clause : string_clause -> string_clause = + fun (_x, _x_i1) -> + let _x = o#string _x in + let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) method statement_desc : statement_desc -> statement_desc = function | Block _x -> let _x = o#block _x in Block _x @@ -384251,13 +384251,36 @@ class virtual map = | Return _x -> let _x = o#expression _x in Return _x | Int_switch (_x, _x_i1, _x_i2) -> let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#int_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Int_switch (_x, _x_i1, _x_i2) + | String_switch (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#string_clause) _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in String_switch (_x, _x_i1, _x_i2) + | Throw _x -> let _x = o#expression _x in Throw _x + | Try (_x, _x_i1, _x_i2) -> + let _x = o#block _x in let _x_i1 = - o#list - (fun o -> - (* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * 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 + o#option + (fun o (_x, _x_i1) -> + let _x = o#exception_ident _x in + let _x_i1 = o#block _x_i1 in (_x, _x_i1)) + _x_i1 in + let _x_i2 = o#option (fun o -> o#block) _x_i2 + in Try (_x, _x_i1, _x_i2) + | Debugger -> Debugger + method statement : statement -> statement = + fun { statement_desc = _x; comment = _x_i1 } -> + let _x = o#statement_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { statement_desc = _x; comment = _x_i1; } + method required_modules : required_modules -> required_modules = + (* Copyright (C) 2015-2016 Bloomberg Finance L.P. + * + * 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * @@ -384277,7 +384300,7 @@ class virtual map = * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - (* Javascript IR + (* Javascript IR It's a subset of Javascript AST specialized for OCaml lambda backend @@ -384285,15 +384308,18 @@ class virtual map = convention and [Block] is just a sequence of statements, which means it does not introduce new scope *) - (* TODO: it seems that camlp4of supports very limited structures + (* TODO: it seems that camlp4of supports very limited structures it does not even support attributes like `[@@@warning "-30"] we should get rid of such dependency ASAP *) - (** object literal, if key is ident, in this case, it might be renamed by + o#list (fun o -> o#module_id) + method property_name : property_name -> property_name = o#unknown + method property_map : property_map -> property_map = + (** object literal, if key is ident, in this case, it might be renamed by Google Closure optimizer, currently we always use quote *) - (* Since camldot is only available for toplevel module accessors, + (* Since camldot is only available for toplevel module accessors, we don't need print `A.length$2` just print `A.length` - it's guarateed to be unique @@ -384308,7 +384334,89 @@ class virtual map = Qualified (_, Runtime, Some "caml_int_compare") ]} *) - (** where we use a trick [== null ] *) (* js true/false*) + o#list + (fun o (_x, _x_i1) -> + let _x = o#property_name _x in + let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) + method property : property -> property = o#unknown + method program : program -> program = + fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#exports _x_i1 in + let _x_i2 = o#unknown _x_i2 + in { block = _x; exports = _x_i1; export_set = _x_i2; } + method number : number -> number = o#unknown + method mutable_flag : mutable_flag -> mutable_flag = o#unknown + method module_id : module_id -> module_id = + fun { id = _x; kind = _x_i1 } -> + let _x = o#ident _x in + let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } + method length_object : length_object -> length_object = o#unknown + method label : label -> label = o#string + method kind : kind -> kind = o#unknown + method jsint : jsint -> jsint = o#int32 + method int_op : int_op -> int_op = o#unknown + method int_clause : int_clause -> int_clause = + fun (_x, _x_i1) -> + let _x = o#int _x in let _x_i1 = o#case_clause _x_i1 in (_x, _x_i1) + method ident_info : ident_info -> ident_info = o#unknown + method ident : ident -> ident = o#unknown + method for_ident_expression : + for_ident_expression -> for_ident_expression = o#expression + method for_ident : for_ident -> for_ident = o#ident + method for_direction : for_direction -> for_direction = o#unknown + method finish_ident_expression : + finish_ident_expression -> finish_ident_expression = o#expression + method expression_desc : expression_desc -> expression_desc = + function + | Length (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) + | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x + | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x + | Is_null_or_undefined _x -> + let _x = o#expression _x in Is_null_or_undefined _x + | String_append (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) + | Bool _x -> let _x = o#bool _x in Bool _x + | Typeof _x -> let _x = o#expression _x in Typeof _x + | Js_not _x -> let _x = o#expression _x in Js_not _x + | Seq (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) + | Cond (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) + | Bin (_x, _x_i1, _x_i2) -> + let _x = o#binop _x in + let _x_i1 = o#expression _x_i1 in + let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) + | FlatCall (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) + | Call (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#list (fun o -> o#expression) _x_i1 in + let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) + | String_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) + | Array_index (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) + | Static_index (_x, _x_i1, _x_i2) -> + let _x = o#expression _x in + let _x_i1 = o#string _x_i1 in + let _x_i2 = o#option (fun o -> o#int32) _x_i2 + in Static_index (_x, _x_i1, _x_i2) + | New (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = + o#option + (fun o -> (** where we use a trick [== null ] *) + (* js true/false*) (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence [typeof] is an operator *) @@ -384343,11 +384451,60 @@ class virtual map = All exported declarations have to be OCaml identifiers 2. Javascript dot (need to be preserved/or using quote) *) - (* TODO: option remove *) - (* The first parameter by default is false, + o#list (fun o -> o#expression)) + _x_i1 + in New (_x, _x_i1) + | Var _x -> let _x = o#vident _x in Var _x + | Fun (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#bool _x in + let _x_i1 = o#list (fun o -> o#ident) _x_i1 in + let _x_i2 = o#block _x_i2 in + let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) + | Str (_x, _x_i1) -> + let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) + | Unicode _x -> let _x = o#string _x in Unicode _x + | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x + | Array (_x, _x_i1) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) + | Optional_block (_x, _x_i1) -> + let _x = o#expression _x in + let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) + | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> + let _x = o#list (fun o -> o#expression) _x in + let _x_i1 = o#mutable_flag _x_i1 in + let _x_i2 = o#expression _x_i2 in + let _x_i3 = o#tag_info _x_i3 + in Caml_block (_x, _x_i1, _x_i2, _x_i3) + | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x + | Number _x -> let _x = o#number _x in Number _x + | Object _x -> let _x = o#property_map _x in Object _x + | Undefined -> Undefined + | Null -> Null + method expression : expression -> expression = + fun { expression_desc = _x; comment = _x_i1 } -> + let _x = o#expression_desc _x in + let _x_i1 = o#option (fun o -> o#string) _x_i1 + in { expression_desc = _x; comment = _x_i1; } + method exports : exports -> exports = o#unknown + method exception_ident : exception_ident -> exception_ident = o#ident + method deps_program : deps_program -> deps_program = + fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> + let _x = o#program _x in + let _x_i1 = o#required_modules _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { program = _x; modules = _x_i1; side_effect = _x_i2; } + method case_clause : case_clause -> case_clause = + fun { switch_body = _x; should_break = _x_i1; comment = _x_i2 } -> + let _x = o#block _x in + let _x_i1 = o#bool _x_i1 in + let _x_i2 = o#option (fun o -> o#string) _x_i2 + in { switch_body = _x; should_break = _x_i1; comment = _x_i2; } + method block : block -> block = (* TODO: option remove *) + (* The first parameter by default is false, it will be true when it's a method *) - (* A string is UTF-8 encoded, the string may contain + (* A string is UTF-8 encoded, the string may contain escape sequences. The first argument is used to mark it is non-pure, please don't optimize it, since it does have side effec, @@ -384355,13 +384512,13 @@ class virtual map = which is better to leave it alone The last argument is passed from as `j` from `{j||j}` *) - (* It is escaped string, print delimited by '"'*) - (* literally raw JS code + (* It is escaped string, print delimited by '"'*) + (* literally raw JS code *) (* [true] means [identity] *) - (* The third argument is [tag] , forth is [tag_info] *) - (* | Caml_uninitialized_obj of expression * expression *) - (* [tag] and [size] tailed for [Obj.new_block] *) - (* For setter, it still return the value of expression, + (* The third argument is [tag] , forth is [tag_info] *) + (* | Caml_uninitialized_obj of expression * expression *) + (* [tag] and [size] tailed for [Obj.new_block] *) + (* For setter, it still return the value of expression, we can not use {[ type 'a access = Get | Set of 'a @@ -384370,20 +384527,20 @@ class virtual map = [Caml_block_tag] can return [undefined], you have to use [E.tag] in a safe way *) - (* | Caml_block_set_tag of expression * expression *) - (* | Caml_block_set_length of expression * expression *) - (* It will just fetch tag, to make it safe, when creating it, + (* | Caml_block_set_tag of expression * expression *) + (* | Caml_block_set_length of expression * expression *) + (* It will just fetch tag, to make it safe, when creating it, we need apply "|0", we don't do it in the last step since "|0" can potentially be optimized *) - (* pure*) (* pure *) - (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block + (* pure*) (* pure *) + (* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block block can be nested, specified in ES3 *) - (* Delay some units like [primitive] into JS layer , + (* Delay some units like [primitive] into JS layer , benefit: better cross module inlining, and smaller IR size? *) - (* + (* [closure] captured loop mutable values in the outer loop check if it contains loop mutable values, happens in nested loop @@ -384409,7 +384566,7 @@ class virtual map = contains a block side effect TODO: create such example *) - (* Since in OCaml, + (* Since in OCaml, [for i = 0 to k end do done ] k is only evaluated once , to encode this invariant in JS IR, @@ -384418,7 +384575,7 @@ class virtual map = TODO: currently we guarantee that [bound] was only excecuted once, should encode this in AST level *) - (* Can be simplified to keep the semantics of OCaml + (* Can be simplified to keep the semantics of OCaml For (var i, e, ...){ let j = ... } @@ -384430,7 +384587,7 @@ class virtual map = })(i) } *) - (* Single return is good for ininling.. + (* Single return is good for ininling.. However, when you do tail-call optmization you loose the expression oriented semantics Block is useful for implementing goto @@ -384440,12 +384597,12 @@ class virtual map = } ]} *) - (* Function declaration and Variable declaration *) - (* check if it contains loop mutable values, happens in nested loop *) - (* only used when inline a fucntion *) - (* Here we need track back a bit ?, move Return to Function ... + (* Function declaration and Variable declaration *) + (* check if it contains loop mutable values, happens in nested loop *) + (* only used when inline a fucntion *) + (* Here we need track back a bit ?, move Return to Function ... Then we can only have one Return, which is not good *) - (* since in ocaml, it's expression oriented langauge, [return] in + (* since in ocaml, it's expression oriented langauge, [return] in general has no jumps, it only happens when we do tailcall conversion, in that case there is a jump. However, currently a single [break] is good to cover @@ -384455,178 +384612,7 @@ class virtual map = A more robust signature would be {[ goto : label option ; ]} *) - o#case_clause (fun o -> o#int)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Int_switch (_x, _x_i1, _x_i2) - | String_switch (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = - o#list (fun o -> o#case_clause (fun o -> o#string)) _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in String_switch (_x, _x_i1, _x_i2) - | Throw _x -> let _x = o#expression _x in Throw _x - | Try (_x, _x_i1, _x_i2) -> - let _x = o#block _x in - let _x_i1 = - o#option - (fun o (_x, _x_i1) -> - let _x = o#exception_ident _x in - let _x_i1 = o#block _x_i1 in (_x, _x_i1)) - _x_i1 in - let _x_i2 = o#option (fun o -> o#block) _x_i2 - in Try (_x, _x_i1, _x_i2) - | Debugger -> Debugger - method statement : statement -> statement = - fun { statement_desc = _x; comment = _x_i1 } -> - let _x = o#statement_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { statement_desc = _x; comment = _x_i1; } - method required_modules : required_modules -> required_modules = - o#list (fun o -> o#module_id) - method property_name : property_name -> property_name = o#unknown - method property_map : property_map -> property_map = - o#list - (fun o (_x, _x_i1) -> - let _x = o#property_name _x in - let _x_i1 = o#expression _x_i1 in (_x, _x_i1)) - method property : property -> property = o#unknown - method program : program -> program = - fun { block = _x; exports = _x_i1; export_set = _x_i2 } -> - let _x = o#block _x in - let _x_i1 = o#exports _x_i1 in - let _x_i2 = o#unknown _x_i2 - in { block = _x; exports = _x_i1; export_set = _x_i2; } - method number : number -> number = o#unknown - method mutable_flag : mutable_flag -> mutable_flag = o#unknown - method module_id : module_id -> module_id = - fun { id = _x; kind = _x_i1 } -> - let _x = o#ident _x in - let _x_i1 = o#unknown _x_i1 in { id = _x; kind = _x_i1; } - method length_object : length_object -> length_object = o#unknown - method label : label -> label = o#string - method kind : kind -> kind = o#unknown - method jsint : jsint -> jsint = o#int32 - method int_op : int_op -> int_op = o#unknown - method ident_info : ident_info -> ident_info = o#unknown - method ident : ident -> ident = o#unknown - method for_ident_expression : - for_ident_expression -> for_ident_expression = o#expression - method for_ident : for_ident -> for_ident = o#ident - method for_direction : for_direction -> for_direction = o#unknown - method finish_ident_expression : - finish_ident_expression -> finish_ident_expression = o#expression - method expression_desc : expression_desc -> expression_desc = - function - | Length (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#length_object _x_i1 in Length (_x, _x_i1) - | Char_of_int _x -> let _x = o#expression _x in Char_of_int _x - | Char_to_int _x -> let _x = o#expression _x in Char_to_int _x - | Is_null_or_undefined _x -> - let _x = o#expression _x in Is_null_or_undefined _x - | String_append (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_append (_x, _x_i1) - | Bool _x -> let _x = o#bool _x in Bool _x - | Typeof _x -> let _x = o#expression _x in Typeof _x - | Js_not _x -> let _x = o#expression _x in Js_not _x - | Seq (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Seq (_x, _x_i1) - | Cond (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Cond (_x, _x_i1, _x_i2) - | Bin (_x, _x_i1, _x_i2) -> - let _x = o#binop _x in - let _x_i1 = o#expression _x_i1 in - let _x_i2 = o#expression _x_i2 in Bin (_x, _x_i1, _x_i2) - | FlatCall (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in FlatCall (_x, _x_i1) - | Call (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#list (fun o -> o#expression) _x_i1 in - let _x_i2 = o#unknown _x_i2 in Call (_x, _x_i1, _x_i2) - | String_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in String_index (_x, _x_i1) - | Array_index (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#expression _x_i1 in Array_index (_x, _x_i1) - | Static_index (_x, _x_i1, _x_i2) -> - let _x = o#expression _x in - let _x_i1 = o#string _x_i1 in - let _x_i2 = o#option (fun o -> o#int32) _x_i2 - in Static_index (_x, _x_i1, _x_i2) - | New (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = - o#option (fun o -> o#list (fun o -> o#expression)) _x_i1 - in New (_x, _x_i1) - | Var _x -> let _x = o#vident _x in Var _x - | Fun (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#bool _x in - let _x_i1 = o#list (fun o -> o#ident) _x_i1 in - let _x_i2 = o#block _x_i2 in - let _x_i3 = o#unknown _x_i3 in Fun (_x, _x_i1, _x_i2, _x_i3) - | Str (_x, _x_i1) -> - let _x = o#bool _x in let _x_i1 = o#string _x_i1 in Str (_x, _x_i1) - | Unicode _x -> let _x = o#string _x in Unicode _x - | Raw_js_code _x -> let _x = o#unknown _x in Raw_js_code _x - | Array (_x, _x_i1) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in Array (_x, _x_i1) - | Optional_block (_x, _x_i1) -> - let _x = o#expression _x in - let _x_i1 = o#bool _x_i1 in Optional_block (_x, _x_i1) - | Caml_block (_x, _x_i1, _x_i2, _x_i3) -> - let _x = o#list (fun o -> o#expression) _x in - let _x_i1 = o#mutable_flag _x_i1 in - let _x_i2 = o#expression _x_i2 in - let _x_i3 = o#tag_info _x_i3 - in Caml_block (_x, _x_i1, _x_i2, _x_i3) - | Caml_block_tag _x -> let _x = o#expression _x in Caml_block_tag _x - | Number _x -> let _x = o#number _x in Number _x - | Object _x -> let _x = o#property_map _x in Object _x - | Undefined -> Undefined - | Null -> Null - method expression : expression -> expression = - fun { expression_desc = _x; comment = _x_i1 } -> - let _x = o#expression_desc _x in - let _x_i1 = o#option (fun o -> o#string) _x_i1 - in { expression_desc = _x; comment = _x_i1; } - method exports : exports -> exports = o#unknown - method exception_ident : exception_ident -> exception_ident = o#ident - method deps_program : deps_program -> deps_program = - fun { program = _x; modules = _x_i1; side_effect = _x_i2 } -> - let _x = o#program _x in - let _x_i1 = o#required_modules _x_i1 in - let _x_i2 = o#option (fun o -> o#string) _x_i2 - in { program = _x; modules = _x_i1; side_effect = _x_i2; } - method case_clause : - 'a 'a_out. - ('self_type -> 'a -> 'a_out) -> 'a case_clause -> 'a_out case_clause = - fun _f_a - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3 - } -> - let _x = _f_a o _x in - let _x_i1 = o#block _x_i1 in - let _x_i2 = o#bool _x_i2 in - let _x_i3 = o#option (fun o -> o#string) _x_i3 - in - { - switch_case = _x; - switch_body = _x_i1; - should_break = _x_i2; - comment = _x_i3; - } - method block : block -> block = (* true means break *) + (* true means break *) (* TODO: For efficency: block should not be a list, it should be able to be concatenated in both ways *) @@ -390994,7 +390980,7 @@ let eval (arg : J.expression) (dispatches : (string * string) list ) : E.t = E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -391022,7 +391008,7 @@ let eval_as_event (arg : J.expression) (dispatches : (string * string) list opti (S.string_switch (E.poly_var_tag_access arg) (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.str r)]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -391054,7 +391040,7 @@ let eval_as_int (arg : J.expression) (dispatches : (string * int) list ) : E.t E.of_block [(S.string_switch arg (Ext_list.map dispatches (fun (i,r) -> - {J.switch_case = i ; + i, J.{ switch_body = [S.return_stmt (E.int (Int32.of_int r))]; should_break = false; (* FIXME: if true, still print break*) comment = None; @@ -396141,7 +396127,7 @@ and compile_general_cases Lam_compile_context.t -> (?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> 'a J.case_clause list -> J.statement) -> + _ -> ('a * J.case_clause) list -> J.statement) -> _ -> ('a * Lam.t) list -> default_case -> J.block = fun @@ -396152,7 +396138,7 @@ and compile_general_cases (switch : ?default:J.block -> ?declaration:Lam_compat.let_kind * Ident.t -> - _ -> _ J.case_clause list -> J.statement + _ -> (_ * J.case_clause) list -> J.statement ) (switch_exp : J.expression) (cases : (_ * Lam.t) list) @@ -396222,13 +396208,13 @@ and compile_general_cases should_break else should_break && Lam_exit_code.has_exit lam in - {J.switch_case ; + switch_case , J.{ switch_body; should_break; comment = make_comment switch_case; } else - { switch_case; switch_body = []; should_break = false; comment = make_comment switch_case; } + switch_case, {switch_body = []; should_break = false; comment = make_comment switch_case; } ) (* TODO: we should also group default *)