Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(855)

Unified Diff: src/parsing/parser.cc

Issue 2368083002: [parser] Refactor of ParseClass* and ParseNativeDeclaration (Closed)
Patch Set: Rebase again Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index cd87da8d14bfb46babba23408e08a987b795a9ca..2e2ac1c7ad3c19ed95e4440416a5bede71658fe4 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -1532,94 +1532,6 @@ Variable* Parser::Declare(Declaration* declaration,
return variable;
}
-// Language extension which is only enabled for source files loaded
-// through the API's extension mechanism. A native function
-// declaration is resolved by looking up the function through a
-// callback provided by the extension.
-Statement* Parser::ParseNativeDeclaration(bool* ok) {
- int pos = peek_position();
- Expect(Token::FUNCTION, CHECK_OK);
- // Allow "eval" or "arguments" for backward compatibility.
- const AstRawString* name =
- ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
- bool done = (peek() == Token::RPAREN);
- while (!done) {
- ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
- done = (peek() == Token::RPAREN);
- if (!done) {
- Expect(Token::COMMA, CHECK_OK);
- }
- }
- Expect(Token::RPAREN, CHECK_OK);
- Expect(Token::SEMICOLON, CHECK_OK);
-
- // Make sure that the function containing the native declaration
- // isn't lazily compiled. The extension structures are only
- // accessible while parsing the first time not when reparsing
- // because of lazy compilation.
- GetClosureScope()->ForceEagerCompilation();
-
- // TODO(1240846): It's weird that native function declarations are
- // introduced dynamically when we meet their declarations, whereas
- // other functions are set up when entering the surrounding scope.
- Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
- NativeFunctionLiteral* lit =
- factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
- return factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
- kNoSourcePosition),
- pos);
-}
-
-Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
- bool default_export, bool* ok) {
- // ClassDeclaration ::
- // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
- // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
- //
- // The anonymous form is allowed iff [default_export] is true.
- //
- // 'class' is expected to be consumed by the caller.
- //
- // A ClassDeclaration
- //
- // class C { ... }
- //
- // has the same semantics as:
- //
- // let C = class C { ... };
- //
- // so rewrite it as such.
-
- int pos = position();
-
- const AstRawString* name;
- bool is_strict_reserved;
- const AstRawString* variable_name;
- if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
- name = ast_value_factory()->default_string();
- is_strict_reserved = false;
- variable_name = ast_value_factory()->star_default_star_string();
- } else {
- name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
- variable_name = name;
- }
-
- ExpressionClassifier no_classifier(this);
- Expression* value = ParseClassLiteral(name, scanner()->location(),
- is_strict_reserved, pos, CHECK_OK);
-
- Declaration* decl = DeclareVariable(variable_name, LET, pos, CHECK_OK);
- decl->proxy()->var()->set_initializer_position(position());
- Assignment* assignment =
- factory()->NewAssignment(Token::INIT, decl->proxy(), value, pos);
- Statement* assignment_statement =
- factory()->NewExpressionStatement(assignment, kNoSourcePosition);
- if (names) names->Add(variable_name, zone());
- return assignment_statement;
-}
-
Block* Parser::BuildInitializationBlock(
DeclarationParsingResult* parsing_result,
ZoneList<const AstRawString*>* names, bool* ok) {
@@ -1675,6 +1587,40 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name,
return factory()->NewEmptyStatement(kNoSourcePosition);
}
+Statement* Parser::DeclareClass(const AstRawString* variable_name,
+ Expression* value,
+ ZoneList<const AstRawString*>* names,
+ int class_token_pos, int end_pos, bool* ok) {
+ Declaration* decl =
+ DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK);
+ decl->proxy()->var()->set_initializer_position(end_pos);
+ Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(),
+ value, class_token_pos);
+ Statement* assignment_statement =
+ factory()->NewExpressionStatement(assignment, kNoSourcePosition);
+ if (names) names->Add(variable_name, zone());
+ return assignment_statement;
+}
+
+Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
+ // Make sure that the function containing the native declaration
+ // isn't lazily compiled. The extension structures are only
+ // accessible while parsing the first time not when reparsing
+ // because of lazy compilation.
+ GetClosureScope()->ForceEagerCompilation();
+
+ // TODO(1240846): It's weird that native function declarations are
+ // introduced dynamically when we meet their declarations, whereas
+ // other functions are set up when entering the surrounding scope.
+ Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
+ NativeFunctionLiteral* lit =
+ factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
+ return factory()->NewExpressionStatement(
+ factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
+ kNoSourcePosition),
+ pos);
+}
+
ZoneList<const AstRawString*>* Parser::DeclareLabel(
ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) {
const AstRawString* label = var->raw_name();
@@ -3512,163 +3458,136 @@ FunctionLiteral* Parser::InsertClassFieldInitializer(
return constructor;
}
-Expression* Parser::ParseClassLiteral(const AstRawString* name,
- Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos,
- bool* ok) {
- // All parts of a ClassDeclaration and ClassExpression are strict code.
- if (name_is_strict_reserved) {
- ReportMessageAt(class_name_location,
- MessageTemplate::kUnexpectedStrictReserved);
- *ok = false;
- return nullptr;
- }
- if (IsEvalOrArguments(name)) {
- ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
- *ok = false;
- return nullptr;
- }
-
- BlockState block_state(zone(), &scope_state_);
- RaiseLanguageMode(STRICT);
+// If a class name is specified, this method declares the class variable
+// and sets class_info->proxy to point to that name.
+void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
+ ClassInfo* class_info, int class_token_pos,
+ bool* ok) {
#ifdef DEBUG
scope()->SetScopeName(name);
#endif
- VariableProxy* proxy = nullptr;
if (name != nullptr) {
- proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
- // TODO(verwaest): declare via block_state.
- Declaration* declaration =
- factory()->NewVariableDeclaration(proxy, block_state.scope(), pos);
+ class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
+ Declaration* declaration = factory()->NewVariableDeclaration(
+ class_info->proxy, block_scope, class_token_pos);
Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
- Variable::DefaultInitializationFlag(CONST), CHECK_OK);
- }
-
- Expression* extends = nullptr;
- if (Check(Token::EXTENDS)) {
- block_state.set_start_position(scanner()->location().end_pos);
- ExpressionClassifier extends_classifier(this);
- extends = ParseLeftHandSideExpression(CHECK_OK);
- RewriteNonPattern(CHECK_OK);
- impl()->AccumulateFormalParameterContainmentErrors();
- } else {
- block_state.set_start_position(scanner()->location().end_pos);
+ Variable::DefaultInitializationFlag(CONST), ok);
+ }
+}
+
+// This method declares a property of the given class. It updates the
+// following fields of class_info, as appropriate:
+// - constructor
+// - static_initializer_var
+// - instance_field_initializers
+// - properties
+void Parser::DeclareClassProperty(const AstRawString* class_name,
+ ClassLiteralProperty* property,
+ ClassInfo* class_info, bool* ok) {
+ if (class_info->has_seen_constructor && class_info->constructor == nullptr) {
+ class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral();
+ DCHECK_NOT_NULL(class_info->constructor);
+ class_info->constructor->set_raw_name(
+ class_name != nullptr ? class_name
+ : ast_value_factory()->empty_string());
+ return;
}
-
- ClassLiteralChecker checker(this);
- ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4);
- ZoneList<Expression*>* instance_field_initializers =
- new (zone()) ZoneList<Expression*>(0, zone());
- FunctionLiteral* constructor = nullptr;
- bool has_seen_constructor = false;
- Variable* static_initializer_var = nullptr;
-
- Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
- Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
- DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
-
- Expect(Token::LBRACE, CHECK_OK);
-
- const bool has_extends = extends != nullptr;
- while (peek() != Token::RBRACE) {
- if (Check(Token::SEMICOLON)) continue;
- FuncNameInferrer::State fni_state(fni_);
- bool is_computed_name = false; // Classes do not care about computed
- // property names here.
- ExpressionClassifier property_classifier(this);
- ClassLiteral::Property* property =
- ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name,
- &has_seen_constructor, CHECK_OK);
- RewriteNonPattern(CHECK_OK);
- impl()->AccumulateFormalParameterContainmentErrors();
-
- if (has_seen_constructor && constructor == nullptr) {
- constructor = GetPropertyValue(property)->AsFunctionLiteral();
- DCHECK_NOT_NULL(constructor);
- constructor->set_raw_name(
- name != nullptr ? name : ast_value_factory()->empty_string());
- } else {
- if (property->kind() == ClassLiteralProperty::FIELD) {
- DCHECK(allow_harmony_class_fields());
- if (property->is_static()) {
- if (static_initializer_var == nullptr) {
- static_initializer_var =
- NewTemporary(ast_value_factory()->empty_string());
- }
- // TODO(bakkot) only do this conditionally
- Expression* function = InstallHomeObject(
- property->value(),
- factory()->NewVariableProxy(static_initializer_var));
- ZoneList<Expression*>* args =
- new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(function, zone());
- args->Add(factory()->NewVariableProxy(static_initializer_var),
- zone());
- Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall,
- args, kNoSourcePosition);
- property->set_value(call);
- } else {
- // if (is_computed_name) { // TODO(bakkot) figure out why this is
- // necessary for non-computed names in full-codegen
- ZoneList<Expression*>* to_name_args =
- new (zone()) ZoneList<Expression*>(1, zone());
- to_name_args->Add(property->key(), zone());
- property->set_key(factory()->NewCallRuntime(
- Runtime::kToName, to_name_args, kNoSourcePosition));
- //}
- const AstRawString* name = ClassFieldVariableName(
- true, ast_value_factory(), instance_field_initializers->length());
- VariableProxy* name_proxy =
- factory()->NewVariableProxy(name, NORMAL_VARIABLE);
- Declaration* name_declaration = factory()->NewVariableDeclaration(
- name_proxy, scope(), kNoSourcePosition);
- Variable* name_var =
- Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
- kNeedsInitialization, ok, scope());
- DCHECK(ok);
- if (!ok) return nullptr;
- instance_field_initializers->Add(property->value(), zone());
- property->set_value(factory()->NewVariableProxy(name_var));
- }
+ if (property->kind() == ClassLiteralProperty::FIELD) {
+ DCHECK(allow_harmony_class_fields());
+ if (property->is_static()) {
+ if (class_info->static_initializer_var == nullptr) {
+ class_info->static_initializer_var =
+ NewTemporary(ast_value_factory()->empty_string());
}
- properties->Add(property, zone());
+ // TODO(bakkot) only do this conditionally
+ Expression* function = InstallHomeObject(
+ property->value(),
+ factory()->NewVariableProxy(class_info->static_initializer_var));
+ ZoneList<Expression*>* args =
+ new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(function, zone());
+ args->Add(factory()->NewVariableProxy(class_info->static_initializer_var),
+ zone());
+ Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
+ kNoSourcePosition);
+ property->set_value(call);
+ } else {
+ // if (is_computed_name) { // TODO(bakkot) figure out why this is
+ // necessary for non-computed names in full-codegen
+ ZoneList<Expression*>* to_name_args =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ to_name_args->Add(property->key(), zone());
+ property->set_key(factory()->NewCallRuntime(
+ Runtime::kToName, to_name_args, kNoSourcePosition));
+ //}
+ const AstRawString* name = ClassFieldVariableName(
+ true, ast_value_factory(),
+ class_info->instance_field_initializers->length());
+ VariableProxy* name_proxy =
+ factory()->NewVariableProxy(name, NORMAL_VARIABLE);
+ Declaration* name_declaration = factory()->NewVariableDeclaration(
+ name_proxy, scope(), kNoSourcePosition);
+ Variable* name_var =
+ Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
+ kNeedsInitialization, ok, scope());
+ DCHECK(*ok);
+ if (!*ok) return;
+ class_info->instance_field_initializers->Add(property->value(), zone());
+ property->set_value(factory()->NewVariableProxy(name_var));
}
-
- DCHECK_NOT_NULL(fni_);
- fni_->Infer();
}
+ class_info->properties->Add(property, zone());
+}
- Expect(Token::RBRACE, CHECK_OK);
+// This method rewrites a class literal into a do-expression.
+// It uses the following fields of class_info:
+// - constructor (if missing, it updates it with a default constructor)
+// - proxy
+// - extends
+// - static_initializer_var
+// - instance_field_initializers
+// - properties
+Expression* Parser::RewriteClassLiteral(const AstRawString* name,
+ ClassInfo* class_info, int pos,
+ bool* ok) {
int end_pos = scanner()->location().end_pos;
+ Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
+ Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
+ DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
- bool has_instance_fields = instance_field_initializers->length() > 0;
+ bool has_extends = class_info->extends != nullptr;
+ bool has_instance_fields =
+ class_info->instance_field_initializers->length() > 0;
DCHECK(!has_instance_fields || allow_harmony_class_fields());
- bool has_default_constructor = constructor == nullptr;
+ bool has_default_constructor = class_info->constructor == nullptr;
if (has_default_constructor) {
- constructor = DefaultConstructor(name, has_extends, has_instance_fields,
- pos, end_pos, block_state.language_mode());
+ class_info->constructor =
+ DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos,
+ scope()->language_mode());
}
- if (has_instance_fields && extends == nullptr) {
- constructor = InsertClassFieldInitializer(constructor);
- constructor->set_requires_class_field_init(true);
+ if (has_instance_fields && !has_extends) {
+ class_info->constructor =
+ InsertClassFieldInitializer(class_info->constructor);
+ class_info->constructor->set_requires_class_field_init(true);
} // The derived case is handled by rewriting super calls.
- block_state.set_end_position(end_pos);
+ scope()->set_end_position(end_pos);
if (name != nullptr) {
- DCHECK_NOT_NULL(proxy);
- proxy->var()->set_initializer_position(end_pos);
+ DCHECK_NOT_NULL(class_info->proxy);
+ class_info->proxy->var()->set_initializer_position(end_pos);
}
ClassLiteral* class_literal = factory()->NewClassLiteral(
- proxy, extends, constructor, properties, pos, end_pos);
+ class_info->proxy, class_info->extends, class_info->constructor,
+ class_info->properties, pos, end_pos);
- if (static_initializer_var != nullptr) {
+ if (class_info->static_initializer_var != nullptr) {
class_literal->set_static_initializer_proxy(
- factory()->NewVariableProxy(static_initializer_var));
+ factory()->NewVariableProxy(class_info->static_initializer_var));
}
do_block->statements()->Add(
@@ -3679,8 +3598,7 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
pos),
zone());
if (allow_harmony_class_fields() &&
- (has_instance_fields ||
- (extends != nullptr && !has_default_constructor))) {
+ (has_instance_fields || (has_extends && !has_default_constructor))) {
// Default constructors for derived classes without fields will not try to
// read this variable, so there's no need to create it.
const AstRawString* init_fn_name =
@@ -3690,7 +3608,7 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
Expression* initializer =
has_instance_fields
? static_cast<Expression*>(SynthesizeClassFieldInitializer(
- instance_field_initializers->length()))
+ class_info->instance_field_initializers->length()))
: factory()->NewBooleanLiteral(false, kNoSourcePosition);
Assignment* assignment = factory()->NewAssignment(
Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer,
@@ -3699,7 +3617,7 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
factory()->NewExpressionStatement(assignment, kNoSourcePosition),
zone());
}
- for (int i = 0; i < instance_field_initializers->length(); ++i) {
+ for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) {
const AstRawString* function_name =
ClassFieldVariableName(false, ast_value_factory(), i);
VariableProxy* function_proxy =
@@ -3709,15 +3627,14 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
Variable* function_var =
Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST,
kNeedsInitialization, ok, scope());
- DCHECK(ok);
- if (!ok) return nullptr;
+ if (!*ok) return nullptr;
Property* prototype_property = factory()->NewProperty(
factory()->NewVariableProxy(result_var),
factory()->NewStringLiteral(ast_value_factory()->prototype_string(),
kNoSourcePosition),
kNoSourcePosition);
Expression* function_value = InstallHomeObject(
- instance_field_initializers->at(i),
+ class_info->instance_field_initializers->at(i),
prototype_property); // TODO(bakkot) ideally this would be conditional,
// especially in trivial cases
Assignment* function_assignment = factory()->NewAssignment(
@@ -3727,13 +3644,12 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
function_assignment, kNoSourcePosition),
zone());
}
- do_block->set_scope(block_state.FinalizedBlockScope());
- do_expr->set_represented_function(constructor);
+ do_block->set_scope(scope()->FinalizeBlockScope());
+ do_expr->set_represented_function(class_info->constructor);
return do_expr;
}
-
Literal* Parser::GetLiteralUndefined(int position) {
return factory()->NewUndefinedLiteral(position);
}
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698