Skip to content

Commit b9bcf63

Browse files
committed
Compiler: modernize js parser (part 2)
1 parent fd6ee32 commit b9bcf63

24 files changed

+1245
-721
lines changed

compiler/lib/driver.ml

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -216,20 +216,21 @@ let gen_missing js missing =
216216
, dot (EVar (ident Constant.global_object_)) prim
217217
, EFun
218218
( None
219-
, { async = false; generator = false }
220-
, []
221-
, [ ( Expression_statement
222-
(call
223-
(EVar (ident_s "caml_failwith"))
224-
[ EBin
225-
( Plus
226-
, EStr prim
227-
, EStr (Utf8_string.of_string_exn " not implemented") )
228-
]
229-
N)
230-
, N )
231-
]
232-
, N ) )
219+
, fun_
220+
[]
221+
[ ( Expression_statement
222+
(call
223+
(EVar (ident_s "caml_failwith"))
224+
[ EBin
225+
( Plus
226+
, EStr prim
227+
, EStr (Utf8_string.of_string_exn " not implemented")
228+
)
229+
]
230+
N)
231+
, N )
232+
]
233+
N ) )
233234
, N ) )
234235
:: acc)
235236
missing
@@ -435,14 +436,8 @@ let pack ~wrap_with_fun ~standalone { Linker.runtime_code = js; always_required_
435436
else js
436437
in
437438

438-
let efun args body =
439-
J.EFun (None, { async = false; generator = false }, args, body, J.U)
440-
in
441-
let sfun name args body =
442-
( J.Function_declaration
443-
(name, { async = false; generator = false }, args, body, J.U)
444-
, J.U )
445-
in
439+
let efun args body = J.EFun (None, J.fun_ args body J.U) in
440+
let sfun name args body = J.Function_declaration (name, J.fun_ args body J.U), J.U in
446441
let mk f =
447442
let js = export_shim js in
448443
let js = old_global_object_shim js in
@@ -451,7 +446,7 @@ let pack ~wrap_with_fun ~standalone { Linker.runtime_code = js; always_required_
451446
then expr (J.EStr (Utf8_string.of_string_exn "use strict")) :: js
452447
else js
453448
in
454-
f [ J.param Constant.global_object_ ] js
449+
f [ J.ident Constant.global_object_ ] js
455450
in
456451
match wrap_with_fun with
457452
| `Anonymous -> expr (mk efun)

compiler/lib/dune

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@
3535
--unused-token
3636
T_AT
3737
--unused-token
38-
T_POUND
39-
--unused-token
40-
T_TEMPLATE_PART))
38+
T_POUND))
4139

4240
(menhir
4341
(modules annot_parser)

compiler/lib/flow_lexer.ml

Lines changed: 67 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
open Js_token
99

10+
module Lex_mode = struct
11+
type t =
12+
| NORMAL
13+
| BACKQUOTE
14+
| REGEXP
15+
end
16+
1017
module Loc = struct
1118
(* line numbers are 1-indexed; column numbers are 0-indexed *)
1219

@@ -41,6 +48,7 @@ module Lex_env = struct
4148
{ lex_source : string option
4249
; lex_lb : Sedlexing.lexbuf
4350
; lex_state : lex_state
51+
; lex_mode_stack : Lex_mode.t list
4452
}
4553
[@@ocaml.warning "-69"]
4654

@@ -55,9 +63,24 @@ module Lex_env = struct
5563
| "" -> None
5664
| s -> Some s
5765
in
58-
{ lex_source; lex_lb; lex_state = empty_lex_state }
66+
{ lex_source
67+
; lex_lb
68+
; lex_state = empty_lex_state
69+
; lex_mode_stack = [ Lex_mode.NORMAL ]
70+
}
5971
end
6072

73+
let push_mode env mode =
74+
{ env with Lex_env.lex_mode_stack = mode :: env.Lex_env.lex_mode_stack }
75+
76+
let pop_mode env =
77+
{ env with
78+
Lex_env.lex_mode_stack =
79+
(match env.Lex_env.lex_mode_stack with
80+
| [] -> []
81+
| _ :: xs -> xs)
82+
}
83+
6184
module Lex_result = struct
6285
type t =
6386
{ lex_token : Js_token.t
@@ -424,7 +447,8 @@ let rec string_quote env q buf lexbuf =
424447
| '\\', line_terminator_sequence -> string_quote env q buf lexbuf
425448
| '\\' ->
426449
let env, str = string_escape env lexbuf in
427-
if String.get q 0 <> String.get str 0 then Buffer.add_string buf "\\";
450+
if String.equal str "" || String.get q 0 <> String.get str 0
451+
then Buffer.add_string buf "\\";
428452
Buffer.add_string buf str;
429453
string_quote env q buf lexbuf
430454
| '\n' ->
@@ -444,47 +468,6 @@ let rec string_quote env q buf lexbuf =
444468
string_quote env q buf lexbuf
445469
| _ -> failwith "unreachable string_quote"
446470

447-
let rec template_part env cooked raw literal lexbuf =
448-
match%sedlex lexbuf with
449-
| eof ->
450-
let env = illegal env (loc_of_lexbuf env lexbuf) in
451-
env, true
452-
| '`' ->
453-
Buffer.add_char literal '`';
454-
env, true
455-
| "${" ->
456-
Buffer.add_string literal "${";
457-
env, false
458-
| '\\' ->
459-
Buffer.add_char raw '\\';
460-
Buffer.add_char literal '\\';
461-
let env, str = string_escape env lexbuf in
462-
Buffer.add_string raw str;
463-
Buffer.add_string literal str;
464-
template_part env cooked raw literal lexbuf
465-
(* ECMAScript 6th Syntax, 11.8.6.1 Static Semantics: TV's and TRV's
466-
* Long story short, <LF> is 0xA, <CR> is 0xA, and <CR><LF> is 0xA
467-
* *)
468-
| "\r\n" ->
469-
Buffer.add_string raw "\r\n";
470-
Buffer.add_string literal "\r\n";
471-
Buffer.add_string cooked "\n";
472-
template_part env cooked raw literal lexbuf
473-
| "\n" | "\r" ->
474-
let lf = lexeme lexbuf in
475-
Buffer.add_string raw lf;
476-
Buffer.add_string literal lf;
477-
Buffer.add_char cooked '\n';
478-
template_part env cooked raw literal lexbuf
479-
(* match multi-char substrings that don't contain the start chars of the above patterns *)
480-
| Plus (Compl (eof | '`' | '$' | '\\' | '\r' | '\n')) | any ->
481-
let c = lexeme lexbuf in
482-
Buffer.add_string raw c;
483-
Buffer.add_string literal c;
484-
Buffer.add_string cooked c;
485-
template_part env cooked raw literal lexbuf
486-
| _ -> failwith "unreachable template_part"
487-
488471
let token (env : Lex_env.t) lexbuf : result =
489472
match%sedlex lexbuf with
490473
| line_terminator_sequence -> Continue env
@@ -519,15 +502,8 @@ let token (env : Lex_env.t) lexbuf : result =
519502
, T_STRING (Stdlib.Utf8_string.of_string_exn (Buffer.contents buf), p2 - p1 - 1)
520503
)
521504
| '`' ->
522-
let cooked = Buffer.create 127 in
523-
let raw = Buffer.create 127 in
524-
let literal = Buffer.create 127 in
525-
lexeme_to_buffer lexbuf literal;
526-
let env, is_tail = template_part env cooked raw literal lexbuf in
527-
Token
528-
( env
529-
, T_TEMPLATE_PART (Stdlib.Utf8_string.of_string_exn (Buffer.contents raw), is_tail)
530-
)
505+
let env = push_mode env BACKQUOTE in
506+
Token (env, T_BACKQUOTE)
531507
| binbigint, word ->
532508
(* Numbers cannot be immediately followed by words *)
533509
recover env lexbuf ~f:(fun env lexbuf ->
@@ -632,8 +608,12 @@ let token (env : Lex_env.t) lexbuf : result =
632608
| _ -> failwith "unreachable token wholenumber")
633609
| wholenumber | floatnumber -> Token (env, T_NUMBER (NORMAL, lexeme lexbuf))
634610
(* Syntax *)
635-
| "{" -> Token (env, T_LCURLY)
636-
| "}" -> Token (env, T_RCURLY)
611+
| "{" ->
612+
let env = push_mode env NORMAL in
613+
Token (env, T_LCURLY)
614+
| "}" ->
615+
let env = pop_mode env in
616+
Token (env, T_RCURLY)
637617
| "(" -> Token (env, T_LPAREN)
638618
| ")" -> Token (env, T_RPAREN)
639619
| "[" -> Token (env, T_LBRACKET)
@@ -811,6 +791,31 @@ let regexp env lexbuf =
811791
Token (env, T_ERROR (lexeme lexbuf))
812792
| _ -> failwith "unreachable regexp"
813793

794+
(*****************************************************************************)
795+
(* Rule backquote *)
796+
(*****************************************************************************)
797+
798+
let backquote env lexbuf =
799+
match%sedlex lexbuf with
800+
| '`' ->
801+
let env = pop_mode env in
802+
Token (env, T_BACKQUOTE)
803+
| "${" ->
804+
let env = push_mode env NORMAL in
805+
Token (env, T_DOLLARCURLY)
806+
| Plus (Compl ('`' | '$' | '\\')) -> Token (env, T_ENCAPSED_STRING (lexeme lexbuf))
807+
| '$' -> Token (env, T_ENCAPSED_STRING (lexeme lexbuf))
808+
| '\\' ->
809+
let buf = Buffer.create 127 in
810+
Buffer.add_char buf '\\';
811+
let env, str = string_escape env lexbuf in
812+
Buffer.add_string buf str;
813+
Token (env, T_ENCAPSED_STRING (Buffer.contents buf))
814+
| eof -> Token (env, T_EOF)
815+
| _ ->
816+
let env = illegal env (loc_of_lexbuf env lexbuf) in
817+
Token (env, T_ERROR (lexeme lexbuf))
818+
814819
let wrap f =
815820
let f env =
816821
let start, _ = Sedlexing.lexing_positions env.Lex_env.lex_lb in
@@ -843,3 +848,11 @@ let wrap f =
843848
let regexp = wrap regexp
844849

845850
let token = wrap token
851+
852+
let backquote = wrap backquote
853+
854+
let lex env =
855+
match env.Lex_env.lex_mode_stack with
856+
| Lex_mode.NORMAL :: _ | [] -> token env
857+
| Lex_mode.BACKQUOTE :: _ -> backquote env
858+
| Lex_mode.REGEXP :: _ -> regexp env

compiler/lib/flow_lexer.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
* LICENSE file in the root directory of this source tree.
66
*)
77

8+
module Lex_mode : sig
9+
type t =
10+
| NORMAL
11+
| BACKQUOTE
12+
| REGEXP
13+
end
14+
815
module Parse_error : sig
916
type t
1017

@@ -41,4 +48,6 @@ val regexp : Lex_env.t -> Lex_env.t * Lex_result.t
4148

4249
val token : Lex_env.t -> Lex_env.t * Lex_result.t
4350

51+
val lex : Lex_env.t -> Lex_env.t * Lex_result.t
52+
4453
val is_valid_identifier_name : string -> bool

compiler/lib/generate.ml

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,10 +1014,10 @@ let generate_apply_fun ctx { arity; exact; cps } =
10141014
let params' = List.map params ~f:(fun x -> J.EVar x) in
10151015
J.EFun
10161016
( None
1017-
, { async = false; generator = false }
1018-
, List.map ~f:J.param' (f :: params)
1019-
, [ J.Return_statement (Some (apply_fun_raw ctx f' params' exact cps)), J.N ]
1020-
, J.N )
1017+
, J.fun_
1018+
(f :: params)
1019+
[ J.Return_statement (Some (apply_fun_raw ctx f' params' exact cps)), J.N ]
1020+
J.N )
10211021

10221022
let apply_fun ctx f params exact cps loc =
10231023
(* We always go through an intermediate function when doing CPS
@@ -1246,14 +1246,7 @@ let rec translate_expr ctx queue loc in_tail_position e level : _ * J.statement_
12461246
| (st, J.N) :: rem -> (st, J.U) :: rem
12471247
| _ -> clo
12481248
in
1249-
let clo =
1250-
J.EFun
1251-
( None
1252-
, { async = false; generator = false }
1253-
, List.map args ~f:(fun v -> J.param' (J.V v))
1254-
, clo
1255-
, loc )
1256-
in
1249+
let clo = J.EFun (None, J.fun_ (List.map args ~f:(fun v -> J.V v)) clo loc) in
12571250
(clo, flush_p, queue), []
12581251
| Constant c ->
12591252
let js, instrs = constant ~ctx c level in
@@ -1422,12 +1415,7 @@ let rec translate_expr ctx queue loc in_tail_position e level : _ * J.statement_
14221415
loc
14231416
in
14241417
let e =
1425-
J.EFun
1426-
( Some f
1427-
, { async = false; generator = false }
1428-
, List.map ~f:J.param' args
1429-
, [ J.Return_statement (Some call), J.N ]
1430-
, J.N )
1418+
J.EFun (Some f, J.fun_ args [ J.Return_statement (Some call), J.N ] J.N)
14311419
in
14321420
e, const_p, queue
14331421
| Extern "caml_alloc_dummy_function", _ -> assert false
@@ -2085,8 +2073,7 @@ let generate_shared_value ctx =
20852073
(Share.AppMap.bindings ctx.Ctx.share.Share.vars.Share.applies)
20862074
~f:(fun (desc, v) ->
20872075
match generate_apply_fun ctx desc with
2088-
| J.EFun (_, k, param, body, nid) ->
2089-
J.Function_declaration (v, k, param, body, nid), J.U
2076+
| J.EFun (_, decl) -> J.Function_declaration (v, decl), J.U
20902077
| _ -> assert false)
20912078
in
20922079
strings :: applies

0 commit comments

Comments
 (0)