From 49f0d461e125071330f7d45a4d8b44aeb8734b0c Mon Sep 17 00:00:00 2001 From: luozijun <luozijun.assistant@gmail.com> Date: Wed, 27 Feb 2019 05:09:22 +0800 Subject: [PATCH] Support async keyword --- ratel-transformer/src/es2015/arrow.rs | 1 + ratel/src/ast/function.rs | 1 + ratel/src/astgen/expression.rs | 7 +++++ ratel/src/astgen/function.rs | 1 + ratel/src/astgen/statement.rs | 3 ++ ratel/src/parser/expression.rs | 2 ++ ratel/src/parser/function.rs | 41 ++++++++++++++++++++++----- ratel/src/parser/mod.rs | 5 +++- ratel/src/parser/statement.rs | 14 +++++---- 9 files changed, 62 insertions(+), 13 deletions(-) diff --git a/ratel-transformer/src/es2015/arrow.rs b/ratel-transformer/src/es2015/arrow.rs index c01ea7b..e8e4f71 100644 --- a/ratel-transformer/src/es2015/arrow.rs +++ b/ratel-transformer/src/es2015/arrow.rs @@ -35,6 +35,7 @@ impl<'ast> Visitor<'ast> for TransformArrow<'ast> { self.ctx.swap(*ptr, Function { name: OptionalName::empty(), generator: false, + is_async: false, params: node.params, body, }); diff --git a/ratel/src/ast/function.rs b/ratel/src/ast/function.rs index ce75f8b..8c183c2 100644 --- a/ratel/src/ast/function.rs +++ b/ratel/src/ast/function.rs @@ -66,6 +66,7 @@ impl<'ast> From<Option<IdentifierNode<'ast>>> for OptionalName<'ast> { pub struct Function<'ast, N: Name<'ast>> { pub name: N, pub generator: bool, + pub is_async: bool, pub params: PatternList<'ast>, pub body: BlockNode<'ast, Statement<'ast>>, } diff --git a/ratel/src/astgen/expression.rs b/ratel/src/astgen/expression.rs index f9732ee..f1b7289 100644 --- a/ratel/src/astgen/expression.rs +++ b/ratel/src/astgen/expression.rs @@ -927,6 +927,7 @@ mod test { "value": { "type": "FunctionExpression", "generator": false, + "is_async": false, "id": null, "params": [ { @@ -974,6 +975,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "Handler", @@ -1095,6 +1097,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "foo", @@ -1376,6 +1379,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "foo", @@ -1403,6 +1407,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "foo", @@ -1538,6 +1543,7 @@ mod test { "value": { "type": "FunctionExpression", "generator": false, + "is_async": false, "id": null, "params": [], "body": { @@ -1593,6 +1599,7 @@ mod test { "value": { "type": "FunctionExpression", "generator": false, + "is_async": false, "id": null, "params": [], "body": { diff --git a/ratel/src/astgen/function.rs b/ratel/src/astgen/function.rs index 63bb687..7caf961 100644 --- a/ratel/src/astgen/function.rs +++ b/ratel/src/astgen/function.rs @@ -122,6 +122,7 @@ where { self.in_loc(serializer, N::IN_FUNCTION, 3, |state| { state.serialize_field("generator", &self.generator)?; + state.serialize_field("is_async", &self.is_async)?; state.serialize_field("id", &self.name)?; state.serialize_field("params", &self.params)?; state.serialize_field("body", &self.body) diff --git a/ratel/src/astgen/statement.rs b/ratel/src/astgen/statement.rs index 43b1f93..2e99ded 100644 --- a/ratel/src/astgen/statement.rs +++ b/ratel/src/astgen/statement.rs @@ -946,6 +946,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "foo", @@ -973,6 +974,7 @@ mod test { { "type": "FunctionDeclaration", "generator": true, + "is_async": false, "id": { "type": "Identifier", "name": "foo", @@ -1000,6 +1002,7 @@ mod test { { "type": "FunctionDeclaration", "generator": false, + "is_async": false, "id": { "type": "Identifier", "name": "foo", diff --git a/ratel/src/parser/expression.rs b/ratel/src/parser/expression.rs index 7b3aebc..4d214a1 100644 --- a/ratel/src/parser/expression.rs +++ b/ratel/src/parser/expression.rs @@ -1033,6 +1033,7 @@ mod test { let expected = Function { name: None.into(), generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block() }; @@ -1048,6 +1049,7 @@ mod test { let expected = Function { name: mock.name("foo"), generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block() }; diff --git a/ratel/src/parser/function.rs b/ratel/src/parser/function.rs index a9bcbdd..57ee5bb 100644 --- a/ratel/src/parser/function.rs +++ b/ratel/src/parser/function.rs @@ -59,31 +59,40 @@ impl<'ast> Parse<'ast> for Pattern<'ast> { } } -impl<'ast, N> Parse<'ast> for Function<'ast, N> where +impl<'ast, N> Function<'ast, N> where N: Name<'ast> + Parse<'ast, Output = N>, { - type Output = Self; - #[inline] - fn parse(par: &mut Parser<'ast>) -> Self::Output { - let generator: bool = if par.lexer.token == OperatorMultiplication { + pub fn with_async_flag(par: &mut Parser<'ast>, is_async: bool) -> Function<'ast, N> { + let is_generator: bool = if par.lexer.token == OperatorMultiplication { par.lexer.consume(); true } else { false }; - let name = N::parse(par); Function { name, - generator, + generator: is_generator, + is_async, params: par.params(), body: par.block(), } } } +impl<'ast, N> Parse<'ast> for Function<'ast, N> where + N: Name<'ast> + Parse<'ast, Output = N>, +{ + type Output = Self; + + #[inline] + fn parse(par: &mut Parser<'ast>) -> Self::Output { + Self::with_async_flag(par, false) + } +} + impl<'ast, N> Parse<'ast> for Node<'ast, Function<'ast, N>> where N: Name<'ast> + Parse<'ast, Output = N>, { @@ -400,6 +409,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block(), } @@ -418,6 +428,7 @@ mod test { Function { name: mock.name("foo"), generator: true, + is_async: false, params: NodeList::empty(), body: mock.empty_block(), } @@ -434,6 +445,7 @@ mod test { Function { name: mock.name("foo"), generator: true, + is_async: false, params: NodeList::empty(), body: mock.empty_block(), } @@ -450,6 +462,7 @@ mod test { Function { name: mock.name("foo"), generator: true, + is_async: false, params: NodeList::empty(), body: mock.empty_block(), } @@ -468,6 +481,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("bar"), Pattern::Identifier("baz"), @@ -488,6 +502,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: NodeList::empty(), body: mock.block([ mock.ptr("bar"), @@ -508,6 +523,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: mock.list([ Pattern::AssignmentPattern { left: mock.ptr(Pattern::Identifier("a")), @@ -541,6 +557,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("a"), Pattern::Identifier("b"), @@ -569,6 +586,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: mock.list([ Pattern::RestElement { argument: mock.ptr("rest"), @@ -589,6 +607,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("a"), Pattern::AssignmentPattern { @@ -667,6 +686,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("bar"), Pattern::Identifier("baz") @@ -716,6 +736,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("bar"), Pattern::Identifier("baz") @@ -732,6 +753,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("moon") ]), @@ -747,6 +769,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block() }) @@ -758,6 +781,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block() }) @@ -769,6 +793,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block() }) @@ -867,6 +892,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("foo") ]), @@ -880,6 +906,7 @@ mod test { value: mock.ptr(Function { name: EmptyName, generator: false, + is_async: false, params: mock.list([ Pattern::Identifier("bar") ]), diff --git a/ratel/src/parser/mod.rs b/ratel/src/parser/mod.rs index 9b99d1a..c5566d0 100644 --- a/ratel/src/parser/mod.rs +++ b/ratel/src/parser/mod.rs @@ -171,7 +171,10 @@ impl<'ast> Parser<'ast> { self.lexer.consume(); ident }, - _ => self.error() + _ => { + println!("eeeee:.....", ); + self.error() + } } } diff --git a/ratel/src/parser/statement.rs b/ratel/src/parser/statement.rs index 30ab6c3..1e2124e 100644 --- a/ratel/src/parser/statement.rs +++ b/ratel/src/parser/statement.rs @@ -80,7 +80,7 @@ create_handlers! { const BRK = |par| par.break_statement(); const THRW = |par| par.throw_statement(); const CONT = |par| par.continue_statement(); - const FUNC = |par| par.function_statement(); + const FUNC = |par| par.function_statement_with_async(false); const CLAS = |par| par.class_statement(); const IF = |par| par.if_statement(); const WHL = |par| par.while_statement(); @@ -190,9 +190,12 @@ impl<'ast> Parser<'ast> { pub fn labeled_or_expression_statement(&mut self) -> StatementNode<'ast> { let label = self.lexer.token_as_str(); let (start, end) = self.lexer.loc(); - + self.lexer.consume(); - + if label == "async" && self.lexer.token == Function { + return self.function_statement_with_async(true); + } + if self.lexer.token == Colon { self.lexer.consume(); @@ -213,9 +216,9 @@ impl<'ast> Parser<'ast> { } #[inline] - pub fn function_statement(&mut self) -> StatementNode<'ast> { + pub fn function_statement_with_async(&mut self, is_async: bool) -> StatementNode<'ast> { let start = self.lexer.start_then_consume(); - let function = Function::parse(self); + let function = Function::with_async_flag(self, is_async); self.alloc_at_loc(start, function.body.end, function) } @@ -1158,6 +1161,7 @@ mod test { Function { name: mock.name("foo"), generator: false, + is_async: false, params: NodeList::empty(), body: mock.empty_block(), }