Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 12287) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -770,8 +770,6 @@ |
| } |
| -// TODO(regis): Implement support for non-const final static fields (currently |
| -// supported "final" fields are actually const fields). |
| // TODO(regis): Since a const variable is implicitly final, |
| // rename ParseStaticConstGetter to ParseStaticFinalGetter and |
| // rename kConstImplicitGetter to kImplicitFinalGetter. |
| @@ -801,12 +799,11 @@ |
| // leave the evaluation to the getter function. |
| const intptr_t expr_pos = TokenPos(); |
| AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| - // TODO(hausner): Remove is_final check below once we support |
| - // non-const finals. |
| - if (field.is_const() || field.is_final()) { |
| + |
| + if (field.is_const()) { |
| // This getter will only be called once at compile time. |
| if (expr->EvalConstExpr() == NULL) { |
| - ErrorMsg(expr_pos, "initializer must be a compile time constant"); |
| + ErrorMsg(expr_pos, "initializer must be a compile-time constant"); |
| } |
| ReturnNode* return_node = new ReturnNode(TokenPos(), expr); |
| current_block_->statements->Add(return_node); |
| @@ -823,11 +820,6 @@ |
| // } |
| // return field.value; // Type check is executed here in checked mode. |
| - // TODO(regis): Remove this check once we support proper const fields. |
| - if (expr->EvalConstExpr() == NULL) { |
| - ErrorMsg(expr_pos, "initializer must be a compile time constant"); |
| - } |
| - |
| // Generate code checking for circular dependency in field initialization. |
| AstNode* compare_circular = new ComparisonNode( |
| TokenPos(), |
| @@ -870,6 +862,10 @@ |
| new LiteralNode( |
| TokenPos(), |
| Instance::ZoneHandle(Object::transition_sentinel())))); |
| + // TODO(hausner): If evaluation of the field value throws an exception, |
| + // we leave the field value as 'transition_sentinel', which is wrong. |
| + // A second reference to the field later throws a circular dependency |
| + // exception. The field should instead be set to null after an exception. |
|
regis
2012/09/12 23:46:58
This contradicts the comment on line 814 stating t
hausner
2012/09/12 23:51:54
No. The comment refers to the code under condition
regis
2012/09/12 23:59:04
I stand corrected :-)
Btw, there was an email disc
|
| initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); |
| AstNode* uninitialized_check = |
| new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); |
| @@ -2676,12 +2672,10 @@ |
| } |
| // Create the field object. |
| - // TODO(hausner): For now, all static final fields are constant. Remove |
| - // this when lazy init of static variables is implemented. |
| class_field = Field::New(*field->name, |
| field->has_static, |
| field->has_final, |
| - field->has_const || field->has_final, |
| + field->has_const, |
| current_class(), |
| field->name_pos); |
| class_field.set_type(*field->type); |
| @@ -2697,7 +2691,7 @@ |
| getter = Function::New(getter_name, |
| RawFunction::kConstImplicitGetter, |
| field->has_static, |
| - field->has_final, |
| + field->has_const, |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| current_class(), |
| @@ -3065,7 +3059,6 @@ |
| patch = String::Concat(patch, class_name); |
| patch = Symbols::New(patch); |
| cls = Class::New(patch, script_, classname_pos); |
| - cls.set_library(library_); |
| } else { |
| // Not patching a class, but it has been found. This must be one of the |
| // pre-registered classes from object.cc or a duplicate definition. |
| @@ -3739,8 +3732,9 @@ |
| void Parser::ParseTopLevelVariable(TopLevel* top_level) { |
| TRACE_PARSER("ParseTopLevelVariable"); |
| - const bool is_final = (CurrentToken() == Token::kFINAL); |
| const bool is_const = (CurrentToken() == Token::kCONST); |
| + // Const fields are implicitly final. |
| + const bool is_final = is_const || (CurrentToken() == Token::kFINAL); |
| const bool is_static = true; |
| const AbstractType& type = |
| AbstractType::ZoneHandle(ParseConstFinalVarOrType( |
| @@ -3766,13 +3760,8 @@ |
| var_name.ToCString()); |
| } |
| - // TODO(hausner): const and final are equivalent at the moment. |
| - field = Field::New(var_name, |
| - is_static, |
| - is_final || is_const, // Const fields are also final. |
| - is_const || is_final, |
| - current_class(), |
| - name_pos); |
| + field = Field::New(var_name, is_static, is_final, is_const, |
| + current_class(), name_pos); |
| field.set_type(type); |
| field.set_value(Instance::Handle(Instance::null())); |
| top_level->fields.Add(field); |
| @@ -3781,7 +3770,7 @@ |
| ConsumeToken(); |
| Instance& field_value = Instance::Handle(Object::sentinel()); |
| bool has_simple_literal = false; |
| - if ((is_final || is_const) && (LookaheadToken(1) == Token::kSEMICOLON)) { |
| + if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) { |
| has_simple_literal = IsSimpleLiteral(type, &field_value); |
| } |
| SkipExpr(); |
| @@ -3792,7 +3781,7 @@ |
| getter = Function::New(getter_name, |
| RawFunction::kConstImplicitGetter, |
| is_static, |
| - is_final, |
| + is_const, |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| current_class(), |
| @@ -3800,8 +3789,7 @@ |
| getter.set_result_type(type); |
| top_level->functions.Add(getter); |
| } |
| - |
| - } else if (is_final || is_const) { |
| + } else if (is_final) { |
| ErrorMsg(name_pos, "missing initializer for final or const variable"); |
| } |
| @@ -6787,7 +6775,7 @@ |
| return expr; |
| } |
| if (expr->EvalConstExpr() == NULL) { |
| - ErrorMsg(expr_pos, "expression must be a compile time constant"); |
| + ErrorMsg(expr_pos, "expression must be a compile-time constant"); |
| } |
| return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); |
| } |
| @@ -6942,7 +6930,7 @@ |
| ConsumeToken(); |
| const intptr_t right_expr_pos = TokenPos(); |
| if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { |
| - ErrorMsg(right_expr_pos, "expression must be a compile time constant"); |
| + ErrorMsg(right_expr_pos, "expression must be a compile-time constant"); |
| } |
| AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); |
| AstNode* left_expr = expr; |
| @@ -7181,9 +7169,7 @@ |
| return initializing_getter; |
| } |
| // The field is initialized. |
| - // TODO(hausner): Remove the is_final check when we support non-const |
| - // final static variables. |
| - if (field.is_const() || field.is_final()) { |
| + if (field.is_const()) { |
| ASSERT(field.value() != Object::sentinel()); |
| ASSERT(field.value() != Object::transition_sentinel()); |
| return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); |
| @@ -7752,9 +7738,7 @@ |
| ASSERT(field.is_static()); |
| const Instance& value = Instance::Handle(field.value()); |
| if (value.raw() == Object::transition_sentinel()) { |
| - // TODO(hausner): Remove the check for is_final() once we support |
| - // non-const final fields. |
| - if (field.is_const() || field.is_final()) { |
| + if (field.is_const()) { |
| ErrorMsg("circular dependency while initializing static field '%s'", |
| String::Handle(field.name()).ToCString()); |
| } else { |
| @@ -7769,9 +7753,7 @@ |
| // This field has not been referenced yet and thus the value has |
| // not been evaluated. If the field is const, call the static getter method |
| // to evaluate the expression and canonicalize the value. |
| - // TODO(hausner): Remove the check for is_final() once we support |
| - // non-const final fields. |
| - if (field.is_const() || field.is_final()) { |
| + if (field.is_const()) { |
| field.set_value(Instance::Handle(Object::transition_sentinel())); |
| const String& field_name = String::Handle(field.name()); |
| const String& getter_name = |
| @@ -7797,7 +7779,7 @@ |
| // It is a compile-time error if evaluation of a compile-time constant |
| // would raise an exception. |
| AppendErrorMsg(error, TokenPos(), |
| - "error initializing final field '%s'", |
| + "error initializing const field '%s'", |
| String::Handle(field.name()).ToCString()); |
| } else { |
| Isolate::Current()->long_jump_base()->Jump(1, error); |
| @@ -8567,7 +8549,7 @@ |
| if (key == NULL) { |
| ErrorMsg("map entry key must be string literal"); |
| } else if (is_const && !key->IsLiteralNode()) { |
| - ErrorMsg("map entry key must be compile time constant string"); |
| + ErrorMsg("map entry key must be compile-time constant string"); |
| } |
| ExpectToken(Token::kCOLON); |
| const bool saved_mode = SetAllowFunctionLiterals(true); |