Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit d3fe556

Browse files
Maximcristianoc
Maxim
authored andcommitted
Make await a keyword again.
Reasoning: In JavaScript `await` is a keyword *only* inside async functions. ```javascript let await = 1 // OK ✅ async function wait() { let await = 1 // NOT OK ❌ } ``` The plot twist is that the newer browsers (chrome or node) support top-level await. (By implicitly wrapping everything in an async function?) ```javascript let await = 1 // NOT OK, with top level await ❌ ``` This makes me think: * We can replicate JavaScript parser; inside async function expressions, use of `await` as identifier will result into a syntax error - Downside: this feels like a responsibility for another part of the compiler, not the parser? This is already implemented in cristianoc/rescript-compiler-experiments#1, so we would also be doing double work. - Other downside: if we ever allow top-level await, then we just implemented the above for nothing. * Allow `await` as a "non-keyword" everywhere with some "tricks". ```javascript let await = 1 let x = await // Ok, now it gets tricky. Does this start an "await"-expression? = await fetch(url) // could be this = await() // could be this = await await() // or even this = await // or we might just be assigning the identifier `await` to `x` ``` Seems like we can infer the following rules for an `await expression`: - space after `await` - next token is on the same line as `await` - next token indicates the start of a unary expression But this "breaks down" in the case of ```javascript let x = await - 1 // could be a binary expression: "identifier" MINUS "1" // could also be an await expression with a unary expression: `await` `(-1)` ``` These whitespace sensitive rules kinda feel super arbitrary. Which makes me think that introducing `await` as a keyword is an ok compromise.
1 parent 85846b6 commit d3fe556

File tree

3 files changed

+20
-28
lines changed

3 files changed

+20
-28
lines changed

src/res_core.ml

+10-21
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,7 @@ and parseOperandExpr ~context p =
20402040
when isEs6ArrowExpression ~inTernary:(context = TernaryTrueBranchExpr) p
20412041
->
20422042
parseAsyncArrowExpression p
2043-
| Lident "await" -> parseAwaitExpression p
2043+
| Await -> parseAwaitExpression p
20442044
| Lazy ->
20452045
Parser.next p;
20462046
let expr = parseUnaryExpr p in
@@ -2761,13 +2761,6 @@ and parseBracedOrRecordExpr p =
27612761
let loc = mkLoc startPos p.prevEndPos in
27622762
let braces = makeBracesAttr loc in
27632763
{expr with pexp_attributes = braces :: expr.pexp_attributes}
2764-
| Lident "await" ->
2765-
let expr = parseAwaitExpression p in
2766-
let expr = parseExprBlock ~first:expr p in
2767-
Parser.expect Rbrace p;
2768-
let loc = mkLoc startPos p.prevEndPos in
2769-
let braces = makeBracesAttr loc in
2770-
{expr with pexp_attributes = braces :: expr.pexp_attributes}
27712764
| Uident _ | Lident _ -> (
27722765
let startToken = p.token in
27732766
let valueOrConstructor = parseValueOrConstructor p in
@@ -3140,19 +3133,15 @@ and parseAsyncArrowExpression p =
31403133
| _ -> assert false
31413134

31423135
and parseAwaitExpression p =
3143-
let startPos = p.Parser.startPos in
3144-
match p.token with
3145-
| Lident "await" ->
3146-
let awaitLoc = mkLoc startPos p.endPos in
3147-
let awaitAttr = (Location.mkloc "await" awaitLoc, Parsetree.PStr []) in
3148-
Parser.next p;
3149-
let expr = parseUnaryExpr p in
3150-
{
3151-
expr with
3152-
pexp_attributes = awaitAttr :: expr.pexp_attributes;
3153-
pexp_loc = {expr.pexp_loc with loc_start = awaitLoc.loc_start};
3154-
}
3155-
| _ -> assert false
3136+
let awaitLoc = mkLoc p.Parser.startPos p.endPos in
3137+
let awaitAttr = (Location.mkloc "await" awaitLoc, Parsetree.PStr []) in
3138+
Parser.expect Await p;
3139+
let expr = parseUnaryExpr p in
3140+
{
3141+
expr with
3142+
pexp_attributes = awaitAttr :: expr.pexp_attributes;
3143+
pexp_loc = {expr.pexp_loc with loc_start = awaitLoc.loc_start};
3144+
}
31563145

31573146
and parseTryExpression p =
31583147
let startPos = p.Parser.startPos in

src/res_grammar.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ let isExprStart = function
151151
| Underscore (* _ => doThings() *)
152152
| Uident _ | Lident _ | Hash | Lparen | List | Module | Lbracket | Lbrace
153153
| LessThan | Minus | MinusDot | Plus | PlusDot | Bang | Percent | At | If
154-
| Switch | While | For | Assert | Lazy | Try ->
154+
| Switch | While | For | Assert | Await | Lazy | Try ->
155155
true
156156
| _ -> false
157157

@@ -257,9 +257,9 @@ let isJsxChildStart = isAtomicExprStart
257257
let isBlockExprStart = function
258258
| Token.At | Hash | Percent | Minus | MinusDot | Plus | PlusDot | Bang | True
259259
| False | Float _ | Int _ | String _ | Codepoint _ | Lident _ | Uident _
260-
| Lparen | List | Lbracket | Lbrace | Forwardslash | Assert | Lazy | If | For
261-
| While | Switch | Open | Module | Exception | Let | LessThan | Backtick | Try
262-
| Underscore ->
260+
| Lparen | List | Lbracket | Lbrace | Forwardslash | Assert | Await | Lazy
261+
| If | For | While | Switch | Open | Module | Exception | Let | LessThan
262+
| Backtick | Try | Underscore ->
263263
true
264264
| _ -> false
265265

src/res_token.ml

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Comment = Res_comment
22

33
type t =
4+
| Await
45
| Open
56
| True
67
| False
@@ -111,6 +112,7 @@ let precedence = function
111112
| _ -> 0
112113

113114
let toString = function
115+
| Await -> "await"
114116
| Open -> "open"
115117
| True -> "true"
116118
| False -> "false"
@@ -210,6 +212,7 @@ let keywordTable = function
210212
| "and" -> And
211213
| "as" -> As
212214
| "assert" -> Assert
215+
| "await" -> Await
213216
| "constraint" -> Constraint
214217
| "else" -> Else
215218
| "exception" -> Exception
@@ -238,9 +241,9 @@ let keywordTable = function
238241
[@@raises Not_found]
239242

240243
let isKeyword = function
241-
| And | As | Assert | Constraint | Else | Exception | External | False | For
242-
| If | In | Include | Land | Lazy | Let | List | Lor | Module | Mutable | Of
243-
| Open | Private | Rec | Switch | True | Try | Typ | When | While ->
244+
| Await | And | As | Assert | Constraint | Else | Exception | External | False
245+
| For | If | In | Include | Land | Lazy | Let | List | Lor | Module | Mutable
246+
| Of | Open | Private | Rec | Switch | True | Try | Typ | When | While ->
244247
true
245248
| _ -> false
246249

0 commit comments

Comments
 (0)