mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:47:35 +00:00
LibJS: Implement generator functions (only in bytecode mode)
This commit is contained in:
parent
c53a86a3fe
commit
3234697eca
21 changed files with 407 additions and 34 deletions
|
@ -590,9 +590,9 @@ NonnullRefPtr<ClassExpression> Parser::parse_class_expression(bool expect_class_
|
|||
constructor_body->append(create_ast_node<ExpressionStatement>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(super_call)));
|
||||
constructor_body->add_variables(m_parser_state.m_var_scopes.last());
|
||||
|
||||
constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector { FunctionNode::Parameter { FlyString { "args" }, nullptr, true } }, 0, NonnullRefPtrVector<VariableDeclaration>(), true);
|
||||
constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector { FunctionNode::Parameter { FlyString { "args" }, nullptr, true } }, 0, NonnullRefPtrVector<VariableDeclaration>(), false, true);
|
||||
} else {
|
||||
constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector<FunctionNode::Parameter> {}, 0, NonnullRefPtrVector<VariableDeclaration>(), true);
|
||||
constructor = create_ast_node<FunctionExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, class_name, move(constructor_body), Vector<FunctionNode::Parameter> {}, 0, NonnullRefPtrVector<VariableDeclaration>(), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,6 +634,7 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
|
|||
syntax_error("'super' keyword unexpected here");
|
||||
return create_ast_node<SuperExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() });
|
||||
case TokenType::Identifier: {
|
||||
read_as_identifier:;
|
||||
if (!try_parse_arrow_function_expression_failed_at_position(position())) {
|
||||
auto arrow_function_result = try_parse_arrow_function_expression(false);
|
||||
if (!arrow_function_result.is_null())
|
||||
|
@ -674,6 +675,10 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
|
|||
}
|
||||
return parse_new_expression();
|
||||
}
|
||||
case TokenType::Yield:
|
||||
if (!m_parser_state.m_in_generator_function_context)
|
||||
goto read_as_identifier;
|
||||
return parse_yield_expression();
|
||||
default:
|
||||
expected("primary expression");
|
||||
consume();
|
||||
|
@ -1256,6 +1261,16 @@ NonnullRefPtr<NewExpression> Parser::parse_new_expression()
|
|||
return create_ast_node<NewExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(callee), move(arguments));
|
||||
}
|
||||
|
||||
NonnullRefPtr<YieldExpression> Parser::parse_yield_expression()
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
consume(TokenType::Yield);
|
||||
RefPtr<Expression> argument;
|
||||
if (match_expression())
|
||||
argument = parse_expression(0);
|
||||
return create_ast_node<YieldExpression>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, move(argument));
|
||||
}
|
||||
|
||||
NonnullRefPtr<ReturnStatement> Parser::parse_return_statement()
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
|
@ -1336,9 +1351,14 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
|
|||
|
||||
ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Function);
|
||||
|
||||
auto is_generator = false;
|
||||
String name;
|
||||
if (parse_options & FunctionNodeParseOptions::CheckForFunctionAndName) {
|
||||
consume(TokenType::Function);
|
||||
is_generator = match(TokenType::Asterisk);
|
||||
if (is_generator)
|
||||
consume(TokenType::Asterisk);
|
||||
|
||||
if (FunctionNodeType::must_have_name() || match(TokenType::Identifier))
|
||||
name = consume(TokenType::Identifier).value();
|
||||
}
|
||||
|
@ -1351,6 +1371,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
|
|||
function_length = parameters.size();
|
||||
|
||||
TemporaryChange change(m_parser_state.m_in_function_context, true);
|
||||
TemporaryChange generator_change(m_parser_state.m_in_generator_function_context, m_parser_state.m_in_generator_function_context || is_generator);
|
||||
auto old_labels_in_scope = move(m_parser_state.m_labels_in_scope);
|
||||
ScopeGuard guard([&]() {
|
||||
m_parser_state.m_labels_in_scope = move(old_labels_in_scope);
|
||||
|
@ -1360,7 +1381,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
|
|||
auto body = parse_block_statement(is_strict);
|
||||
body->add_variables(m_parser_state.m_var_scopes.last());
|
||||
body->add_functions(m_parser_state.m_function_scopes.last());
|
||||
return create_ast_node<FunctionNodeType>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, name, move(body), move(parameters), function_length, NonnullRefPtrVector<VariableDeclaration>(), is_strict);
|
||||
return create_ast_node<FunctionNodeType>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, name, move(body), move(parameters), function_length, NonnullRefPtrVector<VariableDeclaration>(), is_generator, is_strict);
|
||||
}
|
||||
|
||||
Vector<FunctionNode::Parameter> Parser::parse_formal_parameters(int& function_length, u8 parse_options)
|
||||
|
@ -2009,6 +2030,7 @@ bool Parser::match_expression() const
|
|||
|| type == TokenType::This
|
||||
|| type == TokenType::Super
|
||||
|| type == TokenType::RegexLiteral
|
||||
|| type == TokenType::Yield
|
||||
|| match_unary_prefixed_expression();
|
||||
}
|
||||
|
||||
|
@ -2085,6 +2107,7 @@ bool Parser::match_statement() const
|
|||
auto type = m_parser_state.m_current_token.type();
|
||||
return match_expression()
|
||||
|| type == TokenType::Return
|
||||
|| type == TokenType::Yield
|
||||
|| type == TokenType::Do
|
||||
|| type == TokenType::If
|
||||
|| type == TokenType::Throw
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue