| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 27498)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -433,6 +433,7 @@
|
| name(NULL),
|
| default_value(NULL),
|
| metadata(NULL),
|
| + var(NULL),
|
| is_final(false),
|
| is_field_initializer(false) { }
|
| const AbstractType* type;
|
| @@ -440,6 +441,7 @@
|
| const String* name;
|
| const Object* default_value; // NULL if not an optional parameter.
|
| const Object* metadata; // NULL if no metadata or metadata not evaluated.
|
| + LocalVariable* var; // Scope variable allocated for this parameter.
|
| bool is_final;
|
| bool is_field_initializer;
|
| };
|
| @@ -478,6 +480,20 @@
|
| AddFinalParameter(token_pos, &Symbols::This(), receiver_type);
|
| }
|
|
|
| +
|
| + // Make the parameter variables visible/invisible.
|
| + // Field initializer parameters are always invisible.
|
| + void SetInvisible(bool invisible) {
|
| + const intptr_t num_params = parameters->length();
|
| + for (int i = 0; i < num_params; i++) {
|
| + ParamDesc& param = (*parameters)[i];
|
| + ASSERT(param.var != NULL);
|
| + if (!param.is_field_initializer) {
|
| + param.var->set_invisible(invisible);
|
| + }
|
| + }
|
| + }
|
| +
|
| void SetImplicitlyFinal() {
|
| implicitly_final = true;
|
| }
|
| @@ -2483,16 +2499,6 @@
|
| }
|
|
|
|
|
| -// 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);
|
| - }
|
| -}
|
| -
|
| -
|
| void Parser::CheckRecursiveInvocation() {
|
| const GrowableObjectArray& pending_functions =
|
| GrowableObjectArray::Handle(
|
| @@ -2568,14 +2574,13 @@
|
| // 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);
|
| + params.SetInvisible(true);
|
| GrowableArray<Field*> initialized_fields;
|
| LocalVariable* receiver = current_block_->scope->VariableAt(0);
|
| OpenBlock();
|
| 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);
|
| + params.SetInvisible(false);
|
|
|
| // Turn formal field parameters into field initializers or report error
|
| // if the function is not a constructor.
|
| @@ -2592,13 +2597,12 @@
|
| }
|
| CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
|
| AstNode* instance = new LoadLocalNode(param.name_pos, receiver);
|
| - LocalVariable* p =
|
| - current_block_->scope->LookupVariable(*param.name, false);
|
| - ASSERT(p != NULL);
|
| // Initializing formals cannot be used in the explicit initializer
|
| // list, nor can they be used in the constructor body.
|
| - // Thus, make the parameter invisible.
|
| - p->set_invisible(true);
|
| + // Thus, they are set to be invisible when added to the scope.
|
| + LocalVariable* p = param.var;
|
| + ASSERT(p != NULL);
|
| + ASSERT(p->is_invisible());
|
| AstNode* value = new LoadLocalNode(param.name_pos, p);
|
| EnsureExpressionTemp();
|
| AstNode* initializer = new StoreInstanceFieldNode(
|
| @@ -5171,9 +5175,13 @@
|
| "name '%s' already exists in scope",
|
| param_desc.name->ToCString());
|
| }
|
| + param_desc.var = parameter;
|
| if (param_desc.is_final) {
|
| parameter->set_is_final();
|
| }
|
| + if (param_desc.is_field_initializer) {
|
| + parameter->set_invisible(true);
|
| + }
|
| }
|
| }
|
|
|
|
|