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

Unified Diff: runtime/vm/parser.cc

Issue 10832283: Allow non-const field initializers (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 10615)
+++ runtime/vm/parser.cc (working copy)
@@ -1617,14 +1617,8 @@
}
-struct FieldInitExpression {
- Field* inst_field;
- AstNode* expr;
-};
-
-
void Parser::ParseInitializedInstanceFields(const Class& cls,
- GrowableArray<FieldInitExpression>* initializers,
+ LocalVariable* receiver,
GrowableArray<Field*>* initialized_fields) {
TRACE_PARSER("ParseInitializedInstanceFields");
const Array& fields = Array::Handle(cls.fields());
@@ -1646,13 +1640,24 @@
ASSERT(IsIdentifier());
ConsumeToken();
ExpectToken(Token::kASSIGN);
- // TODO(hausner): Allow non-const expressions here for final fields.
- AstNode* init_expr = ParseConstExpr();
+
+ AstNode* init_expr = NULL;
+ if (field.is_const()) {
+ init_expr = ParseConstExpr();
+ } else {
+ init_expr = ParseExpr(kAllowConst, kConsumeCascades);
+ if (init_expr->EvalConstExpr() != NULL) {
+ init_expr = new LiteralNode(field_pos, EvaluateConstExpr(init_expr));
+ }
+ }
ASSERT(init_expr != NULL);
- FieldInitExpression initializer;
- initializer.inst_field = &field;
- initializer.expr = init_expr;
- initializers->Add(initializer);
+ AstNode* instance = new LoadLocalNode(field.token_pos(), receiver);
+ AstNode* field_init =
+ new StoreInstanceFieldNode(field.token_pos(),
+ instance,
+ field,
+ init_expr);
+ current_block_->statements->Add(field_init);
}
}
SetPosition(saved_pos);
@@ -1771,17 +1776,8 @@
SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
ASSERT(func.IsConstructor());
const intptr_t ctor_pos = TokenPos();
-
- // Implicit 'this' is the only parameter/local variable.
OpenFunctionBlock(func);
-
- // Parse expressions of instance fields that have an explicit
- // initializers.
- GrowableArray<FieldInitExpression> initializers;
- GrowableArray<Field*> initialized_fields;
- Class& cls = Class::Handle(func.owner());
- ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
-
+ const Class& cls = Class::Handle(func.owner());
LocalVariable* receiver = new LocalVariable(
ctor_pos,
String::ZoneHandle(Symbols::This()),
@@ -1794,18 +1790,13 @@
Type::ZoneHandle(Type::IntInterface()));
current_block_->scope->AddVariable(phase_parameter);
- // Now that the "this" parameter is in scope, we can generate the code
- // to strore the initializer expressions in the respective instance fields.
- for (int i = 0; i < initializers.length(); i++) {
- const Field* field = initializers[i].inst_field;
- AstNode* instance = new LoadLocalNode(field->token_pos(), receiver);
- AstNode* field_init =
- new StoreInstanceFieldNode(field->token_pos(),
- instance,
- *field,
- initializers[i].expr);
- current_block_->statements->Add(field_init);
- }
+ // Parse expressions of instance fields that have an explicit
+ // initializer expression.
+ // The receiver must not be visible to field initializer expressions.
+ receiver->set_invisible(true);
+ GrowableArray<Field*> initialized_fields;
+ ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
+ receiver->set_invisible(false);
GenerateSuperConstructorCall(cls, receiver);
CheckConstFieldsInitialized(cls);
@@ -1816,6 +1807,16 @@
}
+// Helper function to make the first num_variables variables in the
+// given scope visible/invisible.
+static void SetInvisible(LocalScope* scope, int num_variables, bool invisible) {
+ ASSERT(num_variables <= scope->num_variables());
+ for (int i = 0; i < num_variables; i++) {
+ scope->VariableAt(i)->set_invisible(invisible);
+ }
+}
+
+
// Parser is at the opening parenthesis of the formal parameter declaration
// of function. Parse the formal parameters, initializers and code.
SequenceNode* Parser::ParseConstructor(const Function& func,
@@ -1865,35 +1866,23 @@
ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
ASSERT(func.NumberOfParameters() == params.parameters->length());
- // Initialize instance fields that have an explicit initializer expression.
- // This has to be done before code for field initializer parameters
- // is generated.
- // NB: the instance field initializers have to be compiled before
- // the parameters are added to the scope, so that a parameter
- // name cannot shadow a name used in the field initializer expression.
- GrowableArray<FieldInitExpression> initializers;
- GrowableArray<Field*> initialized_fields;
- ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
-
// Now populate function scope with the formal parameters.
AddFormalParamsToScope(&params, current_block_->scope);
- LocalVariable* receiver = current_block_->scope->VariableAt(0);
- // Now that the "this" parameter is in scope, we can generate the code
- // to store the initializer expressions in the respective instance fields.
- // We do this before the field parameters and the initializers from the
- // constructor's initializer list get compiled.
+ // Initialize instance fields that have an explicit initializer expression.
+ // The formal parameter names must not be visible to the instance
+ // field initializer expressions, yet the parameters must be added to
+ // the scope so the expressions use the correct offsets for 'this' when
+ // storing values. We make the formal parameters temporarily invisible
+ // while parsing the instance field initializer expressions.
+ SetInvisible(current_block_->scope, params.parameters->length(), true);
+ GrowableArray<Field*> initialized_fields;
+ LocalVariable* receiver = current_block_->scope->VariableAt(0);
OpenBlock();
- for (int i = 0; i < initializers.length(); i++) {
- const Field* field = initializers[i].inst_field;
- AstNode* instance = new LoadLocalNode(field->token_pos(), receiver);
- AstNode* field_init =
- new StoreInstanceFieldNode(field->token_pos(),
- instance,
- *field,
- initializers[i].expr);
- current_block_->statements->Add(field_init);
- }
+ ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
+ // Make the parameters (which are in the outer scope) visible again.
+ SetInvisible(current_block_->scope->parent(),
+ params.parameters->length(), false);
// Turn formal field parameters into field initializers or report error
// if the function is not a constructor.
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698