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

Side by Side Diff: runtime/vm/parser.cc

Issue 10828053: Support const modifier in fields, variables (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 // Static const fields must have an initializer. 750 // Static const fields must have an initializer.
751 ExpectToken(Token::kASSIGN); 751 ExpectToken(Token::kASSIGN);
752 752
753 // We don't want to use ParseConstExpr() here because we don't want 753 // We don't want to use ParseConstExpr() here because we don't want
754 // the constant folding code to create, compile and execute a code 754 // the constant folding code to create, compile and execute a code
755 // fragment to evaluate the expression. Instead, we just make sure 755 // fragment to evaluate the expression. Instead, we just make sure
756 // the static const field initializer is a constant expression and 756 // the static const field initializer is a constant expression and
757 // leave the evaluation to the getter function. 757 // leave the evaluation to the getter function.
758 const intptr_t expr_pos = TokenPos(); 758 const intptr_t expr_pos = TokenPos();
759 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); 759 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
760 if (field.is_const()) { 760 // TODO(hausner): Remove is_final check below once we support
761 // non-const finals.
762 if (field.is_const() || field.is_final()) {
761 // This getter will only be called once at compile time. 763 // This getter will only be called once at compile time.
762 if (expr->EvalConstExpr() == NULL) { 764 if (expr->EvalConstExpr() == NULL) {
763 ErrorMsg(expr_pos, "initializer must be a compile time constant"); 765 ErrorMsg(expr_pos, "initializer must be a compile time constant");
764 } 766 }
765 ReturnNode* return_node = new ReturnNode(TokenPos(), expr); 767 ReturnNode* return_node = new ReturnNode(TokenPos(), expr);
766 current_block_->statements->Add(return_node); 768 current_block_->statements->Add(return_node);
767 } else { 769 } else {
768 // This getter may be called each time the static field is accessed. 770 // This getter may be called each time the static field is accessed.
769 // The following generated code lazily initializes the field: 771 // The following generated code lazily initializes the field:
770 // if (field.value === transition_sentinel) { 772 // if (field.value === transition_sentinel) {
(...skipping 1702 matching lines...) Expand 10 before | Expand all | Expand 10 after
2473 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) { 2475 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
2474 TRACE_PARSER("ParseFieldDefinition"); 2476 TRACE_PARSER("ParseFieldDefinition");
2475 // The parser has read the first field name and is now at the token 2477 // The parser has read the first field name and is now at the token
2476 // after the field name. 2478 // after the field name.
2477 ASSERT(CurrentToken() == Token::kSEMICOLON || 2479 ASSERT(CurrentToken() == Token::kSEMICOLON ||
2478 CurrentToken() == Token::kCOMMA || 2480 CurrentToken() == Token::kCOMMA ||
2479 CurrentToken() == Token::kASSIGN); 2481 CurrentToken() == Token::kASSIGN);
2480 ASSERT(field->type != NULL); 2482 ASSERT(field->type != NULL);
2481 ASSERT(field->name_pos > 0); 2483 ASSERT(field->name_pos > 0);
2482 ASSERT(current_member_ == field); 2484 ASSERT(current_member_ == field);
2485 ASSERT(!field->has_const || field->has_final);
2483 2486
2484 if (field->has_const) {
2485 ErrorMsg("keyword 'const' not allowed in field declaration");
2486 }
2487 if (field->has_abstract) { 2487 if (field->has_abstract) {
2488 ErrorMsg("keyword 'abstract' not allowed in field declaration"); 2488 ErrorMsg("keyword 'abstract' not allowed in field declaration");
2489 } 2489 }
2490 if (field->has_factory) { 2490 if (field->has_factory) {
2491 ErrorMsg("keyword 'factory' not allowed in field declaration"); 2491 ErrorMsg("keyword 'factory' not allowed in field declaration");
2492 } 2492 }
2493 if (members->FieldNameExists(*field->name)) { 2493 if (members->FieldNameExists(*field->name)) {
2494 ErrorMsg(field->name_pos, 2494 ErrorMsg(field->name_pos,
2495 "'%s' field/method already defined\n", field->name->ToCString()); 2495 "'%s' field/method already defined\n", field->name->ToCString());
2496 } 2496 }
2497 Function& getter = Function::Handle(); 2497 Function& getter = Function::Handle();
2498 Function& setter = Function::Handle(); 2498 Function& setter = Function::Handle();
2499 Field& class_field = Field::Handle(); 2499 Field& class_field = Field::Handle();
2500 while (true) { 2500 while (true) {
2501 bool has_initializer = CurrentToken() == Token::kASSIGN; 2501 bool has_initializer = CurrentToken() == Token::kASSIGN;
2502 if (has_initializer) { 2502 if (has_initializer) {
2503 ConsumeToken(); 2503 ConsumeToken();
2504 // For static final fields, the initialization expression 2504 // For static final fields, the initialization expression
2505 // will be parsed through the kConstImplicitGetter method 2505 // will be parsed through the kConstImplicitGetter method
2506 // invocation/compilation. 2506 // invocation/compilation.
2507 // For instance fields, the expression is parsed when a constructor 2507 // For instance fields, the expression is parsed when a constructor
2508 // is compiled. 2508 // is compiled.
2509 SkipExpr(); 2509 SkipExpr();
2510 } else { 2510 } else {
2511 if (field->has_static && field->has_final) { 2511 if (field->has_const || (field->has_static && field->has_final)) {
2512 ErrorMsg(field->name_pos, 2512 ErrorMsg(field->name_pos,
2513 "static final field '%s' must have an initializer expression", 2513 "%s%s field '%s' must have an initializer expression",
2514 field->has_static ? "static " : "",
2515 field->has_const ? "const" : "final",
2514 field->name->ToCString()); 2516 field->name->ToCString());
2515 } 2517 }
2516 } 2518 }
2517 2519
2518 // Create the field object. 2520 // Create the field object.
2521 // TODO(hausner): For now, all static final fields are constant. Remove
2522 // this when lazy init of static variables is implemented.
2519 class_field = Field::New(*field->name, 2523 class_field = Field::New(*field->name,
2520 field->has_static, 2524 field->has_static,
2521 field->has_final, 2525 field->has_final,
2526 field->has_const || field->has_final,
2522 field->name_pos); 2527 field->name_pos);
2523 class_field.set_type(*field->type); 2528 class_field.set_type(*field->type);
2524 class_field.set_has_initializer(has_initializer); 2529 class_field.set_has_initializer(has_initializer);
2525 members->AddField(class_field); 2530 members->AddField(class_field);
2526 2531
2527 // For static final fields, set value to "uninitialized" and 2532 // For static final fields, set value to "uninitialized" and
2528 // create a kConstImplicitGetter getter method. 2533 // create a kConstImplicitGetter getter method.
2529 if (field->has_static && has_initializer) { 2534 if (field->has_static && has_initializer) {
2530 class_field.set_value(Instance::Handle(Object::sentinel())); 2535 class_field.set_value(Instance::Handle(Object::sentinel()));
2531 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); 2536 String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 member.type = &Type::ZoneHandle(Type::DynamicType()); 2796 member.type = &Type::ZoneHandle(Type::DynamicType());
2792 } 2797 }
2793 ParseMethodOrConstructor(members, &member); 2798 ParseMethodOrConstructor(members, &member);
2794 if (operator_token != Token::kILLEGAL) { 2799 if (operator_token != Token::kILLEGAL) {
2795 CheckOperatorArity(member, operator_token); 2800 CheckOperatorArity(member, operator_token);
2796 } 2801 }
2797 } else if (CurrentToken() == Token::kSEMICOLON || 2802 } else if (CurrentToken() == Token::kSEMICOLON ||
2798 CurrentToken() == Token::kCOMMA || 2803 CurrentToken() == Token::kCOMMA ||
2799 CurrentToken() == Token::kASSIGN) { 2804 CurrentToken() == Token::kASSIGN) {
2800 // Field definition. 2805 // Field definition.
2806 if (member.has_const) {
2807 // const fields are implicitly final.
2808 member.has_final = true;
2809 }
2801 if (member.type == NULL) { 2810 if (member.type == NULL) {
2802 if (member.has_final) { 2811 if (member.has_final) {
2803 member.type = &Type::ZoneHandle(Type::DynamicType()); 2812 member.type = &Type::ZoneHandle(Type::DynamicType());
2804 } else { 2813 } else {
2805 ErrorMsg("missing 'var', 'final' or type in field declaration"); 2814 ErrorMsg("missing 'var', 'final', 'const' or type"
2815 " in field declaration");
2806 } 2816 }
2807 } 2817 }
2808 if (members->is_interface() && member.has_static && !member.has_final) { 2818 if (members->is_interface() && member.has_static && !member.has_final) {
2809 ErrorMsg("static non-final fields are not allowed in interfaces"); 2819 ErrorMsg("static non-final fields are not allowed in interfaces");
2810 } 2820 }
2811 ParseFieldDefinition(members, &member); 2821 ParseFieldDefinition(members, &member);
2812 } else { 2822 } else {
2813 UnexpectedToken(); 2823 UnexpectedToken();
2814 } 2824 }
2815 current_member_ = NULL; 2825 current_member_ = NULL;
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
3425 } 3435 }
3426 } 3436 }
3427 cls_interfaces = Array::MakeArray(all_interfaces); 3437 cls_interfaces = Array::MakeArray(all_interfaces);
3428 cls.set_interfaces(cls_interfaces); 3438 cls.set_interfaces(cls_interfaces);
3429 } 3439 }
3430 3440
3431 3441
3432 void Parser::ParseTopLevelVariable(TopLevel* top_level) { 3442 void Parser::ParseTopLevelVariable(TopLevel* top_level) {
3433 TRACE_PARSER("ParseTopLevelVariable"); 3443 TRACE_PARSER("ParseTopLevelVariable");
3434 const bool is_final = (CurrentToken() == Token::kFINAL); 3444 const bool is_final = (CurrentToken() == Token::kFINAL);
3445 const bool is_const = (CurrentToken() == Token::kCONST);
3435 const bool is_static = true; 3446 const bool is_static = true;
3436 const AbstractType& type = AbstractType::ZoneHandle(ParseFinalVarOrType( 3447 const AbstractType& type =
3437 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve : 3448 AbstractType::ZoneHandle(ParseConstFinalVarOrType(
3438 ClassFinalizer::kIgnore)); 3449 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve :
3450 ClassFinalizer::kIgnore));
3439 Field& field = Field::Handle(); 3451 Field& field = Field::Handle();
3440 Function& getter = Function::Handle(); 3452 Function& getter = Function::Handle();
3441 while (true) { 3453 while (true) {
3442 const intptr_t name_pos = TokenPos(); 3454 const intptr_t name_pos = TokenPos();
3443 String& var_name = *ExpectIdentifier("variable name expected"); 3455 String& var_name = *ExpectIdentifier("variable name expected");
3444 3456
3445 if (library_.LookupObject(var_name) != Object::null()) { 3457 if (library_.LookupObject(var_name) != Object::null()) {
3446 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); 3458 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString());
3447 } 3459 }
3448 String& accessor_name = String::Handle(Field::GetterName(var_name)); 3460 String& accessor_name = String::Handle(Field::GetterName(var_name));
3449 if (library_.LookupObject(accessor_name) != Object::null()) { 3461 if (library_.LookupObject(accessor_name) != Object::null()) {
3450 ErrorMsg(name_pos, "getter for '%s' is already defined", 3462 ErrorMsg(name_pos, "getter for '%s' is already defined",
3451 var_name.ToCString()); 3463 var_name.ToCString());
3452 } 3464 }
3453 accessor_name = Field::SetterName(var_name); 3465 accessor_name = Field::SetterName(var_name);
3454 if (library_.LookupObject(accessor_name) != Object::null()) { 3466 if (library_.LookupObject(accessor_name) != Object::null()) {
3455 ErrorMsg(name_pos, "setter for '%s' is already defined", 3467 ErrorMsg(name_pos, "setter for '%s' is already defined",
3456 var_name.ToCString()); 3468 var_name.ToCString());
3457 } 3469 }
3458 3470
3459 field = Field::New(var_name, is_static, is_final, name_pos); 3471 field = Field::New(var_name, is_static, is_final, is_const, name_pos);
3460 field.set_type(type); 3472 field.set_type(type);
3461 field.set_value(Instance::Handle(Instance::null())); 3473 field.set_value(Instance::Handle(Instance::null()));
3462 top_level->fields.Add(field); 3474 top_level->fields.Add(field);
3463 library_.AddObject(field, var_name); 3475 library_.AddObject(field, var_name);
3464 if (CurrentToken() == Token::kASSIGN) { 3476 if (CurrentToken() == Token::kASSIGN) {
3465 ConsumeToken(); 3477 ConsumeToken();
3466 SkipExpr(); 3478 SkipExpr();
3467 field.set_value(Instance::Handle(Object::sentinel())); 3479 field.set_value(Instance::Handle(Object::sentinel()));
3468 // Create a static const getter. 3480 // Create a static const getter.
3469 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); 3481 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name));
3470 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, 3482 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter,
3471 is_static, is_final, name_pos); 3483 is_static, is_final, name_pos);
3472 getter.set_result_type(type); 3484 getter.set_result_type(type);
3473 top_level->functions.Add(getter); 3485 top_level->functions.Add(getter);
3474 } else if (is_final) { 3486 } else if (is_final || is_const) {
3475 ErrorMsg(name_pos, "missing initializer for final variable"); 3487 ErrorMsg(name_pos, "missing initializer for final or const variable");
3476 } 3488 }
3477 3489
3478 if (CurrentToken() == Token::kCOMMA) { 3490 if (CurrentToken() == Token::kCOMMA) {
3479 ConsumeToken(); 3491 ConsumeToken();
3480 } else if (CurrentToken() == Token::kSEMICOLON) { 3492 } else if (CurrentToken() == Token::kSEMICOLON) {
3481 ConsumeToken(); 3493 ConsumeToken();
3482 break; 3494 break;
3483 } else { 3495 } else {
3484 ExpectSemicolon(); // Reports error. 3496 ExpectSemicolon(); // Reports error.
3485 } 3497 }
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
4058 4070
4059 4071
4060 AstNode* Parser::CallGetter(intptr_t token_pos, 4072 AstNode* Parser::CallGetter(intptr_t token_pos,
4061 AstNode* object, 4073 AstNode* object,
4062 const String& name) { 4074 const String& name) {
4063 return new InstanceGetterNode(TokenPos(), object, name); 4075 return new InstanceGetterNode(TokenPos(), object, name);
4064 } 4076 }
4065 4077
4066 4078
4067 // Returns ast nodes of the variable initialization. 4079 // Returns ast nodes of the variable initialization.
4068 AstNode* Parser::ParseVariableDeclaration( 4080 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
4069 const AbstractType& type, bool is_final) { 4081 bool is_final,
4082 bool is_const) {
4070 TRACE_PARSER("ParseVariableDeclaration"); 4083 TRACE_PARSER("ParseVariableDeclaration");
4071 ASSERT(IsIdentifier()); 4084 ASSERT(IsIdentifier());
4072 const intptr_t ident_pos = TokenPos(); 4085 const intptr_t ident_pos = TokenPos();
4073 LocalVariable* variable = 4086 LocalVariable* variable =
4074 new LocalVariable(ident_pos, *CurrentLiteral(), type); 4087 new LocalVariable(ident_pos, *CurrentLiteral(), type);
4075 ASSERT(current_block_ != NULL); 4088 ASSERT(current_block_ != NULL);
4076 ASSERT(current_block_->scope != NULL); 4089 ASSERT(current_block_->scope != NULL);
4077 ConsumeToken(); // Variable identifier. 4090 ConsumeToken(); // Variable identifier.
4078 AstNode* initialization = NULL; 4091 AstNode* initialization = NULL;
4079 if (CurrentToken() == Token::kASSIGN) { 4092 if (CurrentToken() == Token::kASSIGN) {
4080 // Variable initialization. 4093 // Variable initialization.
4081 const intptr_t assign_pos = TokenPos(); 4094 const intptr_t assign_pos = TokenPos();
4082 ConsumeToken(); 4095 ConsumeToken();
4083 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); 4096 AstNode* expr = ParseExpr(is_const, kConsumeCascades);
4084 initialization = new StoreLocalNode(assign_pos, *variable, expr); 4097 initialization = new StoreLocalNode(assign_pos, *variable, expr);
4085 } else if (is_final) { 4098 } else if (is_final || is_const) {
4086 ErrorMsg(ident_pos, "missing initialization of 'final' variable"); 4099 ErrorMsg(ident_pos,
4100 "missing initialization of 'final' or 'const' variable");
4087 } else { 4101 } else {
4088 // Initialize variable with null. 4102 // Initialize variable with null.
4089 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); 4103 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle());
4090 initialization = new StoreLocalNode(ident_pos, *variable, null_expr); 4104 initialization = new StoreLocalNode(ident_pos, *variable, null_expr);
4091 } 4105 }
4092 // Add variable to cope after parsing the initalizer expression. 4106 // Add variable to scope after parsing the initalizer expression.
4093 // The expression must not be able to refer to the variable. 4107 // The expression must not be able to refer to the variable.
4094 if (!current_block_->scope->AddVariable(variable)) { 4108 if (!current_block_->scope->AddVariable(variable)) {
4095 ErrorMsg(ident_pos, "identifier '%s' already defined", 4109 ErrorMsg(ident_pos, "identifier '%s' already defined",
4096 variable->name().ToCString()); 4110 variable->name().ToCString());
4097 } 4111 }
4098 if (is_final) { 4112 if (is_final || is_const) {
4099 variable->set_is_final(); 4113 variable->set_is_final();
4100 } 4114 }
4101 return initialization; 4115 return initialization;
4102 } 4116 }
4103 4117
4104 4118
4105 // Parses ('var' | 'final' [type] | type). 4119 // Parses ('var' | 'final' [type] | 'const' [type] | type).
4106 // The presence of 'final' must be detected and remembered before the call. 4120 // The presence of 'final' or 'const' must be detected and remembered
4107 // If a type is parsed, it may be resolved and finalized according to the given 4121 // before the call. If a type is parsed, it may be resolved and finalized
4108 // type finalization mode. 4122 // according to the given type finalization mode.
4109 RawAbstractType* Parser::ParseFinalVarOrType( 4123 RawAbstractType* Parser::ParseConstFinalVarOrType(
4110 ClassFinalizer::FinalizationKind finalization) { 4124 ClassFinalizer::FinalizationKind finalization) {
4111 TRACE_PARSER("ParseFinalVarOrType"); 4125 TRACE_PARSER("ParseConstFinalVarOrType");
4112 if (CurrentToken() == Token::kVAR) { 4126 if (CurrentToken() == Token::kVAR) {
4113 ConsumeToken(); 4127 ConsumeToken();
4114 return Type::DynamicType(); 4128 return Type::DynamicType();
4115 } 4129 }
4116 bool type_is_optional = false; 4130 bool type_is_optional = false;
4117 if (CurrentToken() == Token::kFINAL) { 4131 if ((CurrentToken() == Token::kFINAL) || (CurrentToken() == Token::kCONST)) {
4118 ConsumeToken(); 4132 ConsumeToken();
4119 type_is_optional = true; 4133 type_is_optional = true;
4120 } 4134 }
4121 if (CurrentToken() != Token::kIDENT) { 4135 if (CurrentToken() != Token::kIDENT) {
4122 if (type_is_optional) { 4136 if (type_is_optional) {
4123 return Type::DynamicType(); 4137 return Type::DynamicType();
4124 } else { 4138 } else {
4125 ErrorMsg("type name expected"); 4139 ErrorMsg("type name expected");
4126 } 4140 }
4127 } 4141 }
(...skipping 11 matching lines...) Expand all
4139 return ParseType(finalization); 4153 return ParseType(finalization);
4140 } 4154 }
4141 4155
4142 4156
4143 // Returns ast nodes of the variable initialization. Variables without an 4157 // Returns ast nodes of the variable initialization. Variables without an
4144 // explicit initializer are initialized to null. If several variables are 4158 // explicit initializer are initialized to null. If several variables are
4145 // declared, the individual initializers are collected in a sequence node. 4159 // declared, the individual initializers are collected in a sequence node.
4146 AstNode* Parser::ParseVariableDeclarationList() { 4160 AstNode* Parser::ParseVariableDeclarationList() {
4147 TRACE_PARSER("ParseVariableDeclarationList"); 4161 TRACE_PARSER("ParseVariableDeclarationList");
4148 bool is_final = (CurrentToken() == Token::kFINAL); 4162 bool is_final = (CurrentToken() == Token::kFINAL);
4149 const AbstractType& type = AbstractType::ZoneHandle(ParseFinalVarOrType( 4163 bool is_const = (CurrentToken() == Token::kCONST);
4164 const AbstractType& type = AbstractType::ZoneHandle(ParseConstFinalVarOrType(
4150 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize : 4165 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
4151 ClassFinalizer::kIgnore)); 4166 ClassFinalizer::kIgnore));
4152 if (!IsIdentifier()) { 4167 if (!IsIdentifier()) {
4153 ErrorMsg("identifier expected"); 4168 ErrorMsg("identifier expected");
4154 } 4169 }
4155 4170
4156 AstNode* initializers = ParseVariableDeclaration(type, is_final); 4171 AstNode* initializers = ParseVariableDeclaration(type, is_final, is_const);
4157 ASSERT(initializers != NULL); 4172 ASSERT(initializers != NULL);
4158 while (CurrentToken() == Token::kCOMMA) { 4173 while (CurrentToken() == Token::kCOMMA) {
4159 ConsumeToken(); 4174 ConsumeToken();
4160 if (!IsIdentifier()) { 4175 if (!IsIdentifier()) {
4161 ErrorMsg("identifier expected after comma"); 4176 ErrorMsg("identifier expected after comma");
4162 } 4177 }
4163 // We have a second initializer. Allocate a sequence node now. 4178 // We have a second initializer. Allocate a sequence node now.
4164 // The sequence does not own the current scope. Set its own scope to NULL. 4179 // The sequence does not own the current scope. Set its own scope to NULL.
4165 SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(), 4180 SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(),
4166 initializers, 4181 initializers,
4167 NULL); 4182 NULL);
4168 sequence->Add(ParseVariableDeclaration(type, is_final)); 4183 sequence->Add(ParseVariableDeclaration(type, is_final, is_const));
4169 initializers = sequence; 4184 initializers = sequence;
4170 } 4185 }
4171 return initializers; 4186 return initializers;
4172 } 4187 }
4173 4188
4174 4189
4175 AstNode* Parser::ParseFunctionStatement(bool is_literal) { 4190 AstNode* Parser::ParseFunctionStatement(bool is_literal) {
4176 TRACE_PARSER("ParseFunctionStatement"); 4191 TRACE_PARSER("ParseFunctionStatement");
4177 AbstractType& result_type = AbstractType::Handle(); 4192 AbstractType& result_type = AbstractType::Handle();
4178 const String* variable_name = NULL; 4193 const String* variable_name = NULL;
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
4431 return true; 4446 return true;
4432 } else if (CurrentToken() == Token::kIDENT) { 4447 } else if (CurrentToken() == Token::kIDENT) {
4433 return TryParseOptionalType(); 4448 return TryParseOptionalType();
4434 } 4449 }
4435 return false; 4450 return false;
4436 } 4451 }
4437 4452
4438 4453
4439 // Look ahead to detect whether the next tokens should be parsed as 4454 // Look ahead to detect whether the next tokens should be parsed as
4440 // a variable declaration. Returns true if we detect the token pattern: 4455 // a variable declaration. Returns true if we detect the token pattern:
4441 // ('var' | 'final' | type ident (';' | '=' | ',')) 4456 // 'var'
4457 // | 'final'
4458 // | const [type] ident (';' | '=' | ',')
4459 // | type ident (';' | '=' | ',')
4442 // Token position remains unchanged. 4460 // Token position remains unchanged.
4443 bool Parser::IsVariableDeclaration() { 4461 bool Parser::IsVariableDeclaration() {
4444 if ((CurrentToken() == Token::kVAR) || 4462 if ((CurrentToken() == Token::kVAR) ||
4445 (CurrentToken() == Token::kFINAL)) { 4463 (CurrentToken() == Token::kFINAL)) {
4446 return true; 4464 return true;
4447 } 4465 }
4448 if (CurrentToken() != Token::kIDENT) { 4466 if ((CurrentToken() != Token::kIDENT) && (CurrentToken() != Token::kCONST)) {
4449 // Not a legal type identifier. 4467 // Not a legal type identifier or const keyword
4450 return false; 4468 return false;
4451 } 4469 }
4452 const intptr_t saved_pos = TokenPos(); 4470 const intptr_t saved_pos = TokenPos();
4453 bool is_var_decl = false; 4471 bool is_var_decl = false;
4454 if (TryParseOptionalType()) { 4472 bool have_type = false;
4455 if (IsIdentifier()) { 4473 if (CurrentToken() == Token::kCONST) {
4474 ConsumeToken();
4475 have_type = true; // Type is Dynamic.
4476 }
4477 if (IsIdentifier()) { // Type or variable name.
4478 Token::Kind follower = LookaheadToken(1);
4479 if ((follower == Token::kLT) || // Parameterized type.
4480 (follower == Token::kPERIOD) || // Qualified class name of type.
4481 Token::IsIdentifier(follower)) { // Variable name following a type.
4482 // We see the beginning of something that could be a type.
4483 const intptr_t type_pos = TokenPos();
4484 if (TryParseOptionalType()) {
4485 have_type = true;
4486 } else {
4487 SetPosition(type_pos);
4488 }
4489 }
4490 if (have_type && IsIdentifier()) {
4456 ConsumeToken(); 4491 ConsumeToken();
4457 if ((CurrentToken() == Token::kSEMICOLON) || 4492 if ((CurrentToken() == Token::kSEMICOLON) ||
4458 (CurrentToken() == Token::kCOMMA) || 4493 (CurrentToken() == Token::kCOMMA) ||
4459 (CurrentToken() == Token::kASSIGN)) { 4494 (CurrentToken() == Token::kASSIGN)) {
4460 is_var_decl = true; 4495 is_var_decl = true;
4461 } 4496 }
4462 } 4497 }
4463 } 4498 }
4464 SetPosition(saved_pos); 4499 SetPosition(saved_pos);
4465 return is_var_decl; 4500 return is_var_decl;
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
4869 ExpectToken(Token::kRPAREN); 4904 ExpectToken(Token::kRPAREN);
4870 ExpectSemicolon(); 4905 ExpectSemicolon();
4871 return new DoWhileNode(do_pos, label, cond_expr, dowhile_body); 4906 return new DoWhileNode(do_pos, label, cond_expr, dowhile_body);
4872 } 4907 }
4873 4908
4874 4909
4875 AstNode* Parser::ParseForInStatement(intptr_t forin_pos, 4910 AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
4876 SourceLabel* label) { 4911 SourceLabel* label) {
4877 TRACE_PARSER("ParseForInStatement"); 4912 TRACE_PARSER("ParseForInStatement");
4878 bool is_final = (CurrentToken() == Token::kFINAL); 4913 bool is_final = (CurrentToken() == Token::kFINAL);
4914 if (CurrentToken() == Token::kCONST) {
4915 ErrorMsg("Loop variable cannot be 'const'");
4916 }
4879 const String* loop_var_name = NULL; 4917 const String* loop_var_name = NULL;
4880 LocalVariable* loop_var = NULL; 4918 LocalVariable* loop_var = NULL;
4881 intptr_t loop_var_pos = 0; 4919 intptr_t loop_var_pos = 0;
4882 if (LookaheadToken(1) == Token::kIN) { 4920 if (LookaheadToken(1) == Token::kIN) {
4883 loop_var_pos = TokenPos(); 4921 loop_var_pos = TokenPos();
4884 loop_var_name = ExpectIdentifier("variable name expected"); 4922 loop_var_name = ExpectIdentifier("variable name expected");
4885 } else { 4923 } else {
4886 // The case without a type is handled above, so require a type here. 4924 // The case without a type is handled above, so require a type here.
4887 const AbstractType& type = AbstractType::ZoneHandle(ParseFinalVarOrType( 4925 const AbstractType& type =
4888 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize : 4926 AbstractType::ZoneHandle(ParseConstFinalVarOrType(
4889 ClassFinalizer::kIgnore)); 4927 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
4928 ClassFinalizer::kIgnore));
4890 loop_var_pos = TokenPos(); 4929 loop_var_pos = TokenPos();
4891 loop_var_name = ExpectIdentifier("variable name expected"); 4930 loop_var_name = ExpectIdentifier("variable name expected");
4892 loop_var = new LocalVariable(loop_var_pos, *loop_var_name, type); 4931 loop_var = new LocalVariable(loop_var_pos, *loop_var_name, type);
4893 if (is_final) { 4932 if (is_final) {
4894 loop_var->set_is_final(); 4933 loop_var->set_is_final();
4895 } 4934 }
4896 } 4935 }
4897 ExpectToken(Token::kIN); 4936 ExpectToken(Token::kIN);
4898 const intptr_t collection_pos = TokenPos(); 4937 const intptr_t collection_pos = TokenPos();
4899 AstNode* collection_expr = ParseExpr(kAllowConst, kConsumeCascades); 4938 AstNode* collection_expr = ParseExpr(kAllowConst, kConsumeCascades);
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
5130 }; 5169 };
5131 5170
5132 5171
5133 // Parse the parameter specified in the catch clause. 5172 // Parse the parameter specified in the catch clause.
5134 void Parser::ParseCatchParameter(CatchParamDesc* catch_param) { 5173 void Parser::ParseCatchParameter(CatchParamDesc* catch_param) {
5135 TRACE_PARSER("ParseCatchParameter"); 5174 TRACE_PARSER("ParseCatchParameter");
5136 ASSERT(catch_param != NULL); 5175 ASSERT(catch_param != NULL);
5137 catch_param->is_final = (CurrentToken() == Token::kFINAL); 5176 catch_param->is_final = (CurrentToken() == Token::kFINAL);
5138 // The type of the catch parameter must always be resolved, even in unchecked 5177 // The type of the catch parameter must always be resolved, even in unchecked
5139 // mode. 5178 // mode.
5179 if (CurrentToken() == Token::kCONST) {
5180 ErrorMsg("Catch parameter cannot be 'const'");
5181 }
5140 catch_param->type = &AbstractType::ZoneHandle( 5182 catch_param->type = &AbstractType::ZoneHandle(
5141 ParseFinalVarOrType(ClassFinalizer::kCanonicalizeWellFormed)); 5183 ParseConstFinalVarOrType(ClassFinalizer::kCanonicalizeWellFormed));
5142 catch_param->token_pos = TokenPos(); 5184 catch_param->token_pos = TokenPos();
5143 catch_param->var = ExpectIdentifier("identifier expected"); 5185 catch_param->var = ExpectIdentifier("identifier expected");
5144 } 5186 }
5145 5187
5146 5188
5147 // Populate local scope of the catch block with the catch parameters. 5189 // Populate local scope of the catch block with the catch parameters.
5148 void Parser::AddCatchParamsToScope(const CatchParamDesc& exception_param, 5190 void Parser::AddCatchParamsToScope(const CatchParamDesc& exception_param,
5149 const CatchParamDesc& stack_trace_param, 5191 const CatchParamDesc& stack_trace_param,
5150 LocalScope* scope) { 5192 LocalScope* scope) {
5151 ASSERT(exception_param.var != NULL); 5193 ASSERT(exception_param.var != NULL);
(...skipping 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after
6527 intptr_t ident_pos) { 6569 intptr_t ident_pos) {
6528 // If the static field has an initializer, initialize the field at compile 6570 // If the static field has an initializer, initialize the field at compile
6529 // time, which is only possible if the field is const. 6571 // time, which is only possible if the field is const.
6530 AstNode* initializing_getter = RunStaticFieldInitializer(field); 6572 AstNode* initializing_getter = RunStaticFieldInitializer(field);
6531 if (initializing_getter != NULL) { 6573 if (initializing_getter != NULL) {
6532 // The field is not yet initialized and could not be initialized at compile 6574 // The field is not yet initialized and could not be initialized at compile
6533 // time. The getter will initialize the field. 6575 // time. The getter will initialize the field.
6534 return initializing_getter; 6576 return initializing_getter;
6535 } 6577 }
6536 // The field is initialized. 6578 // The field is initialized.
6537 if (field.is_const()) { 6579 // TODO(hausner): Remove the is_final check when we support non-const
6580 // final static variables.
6581 if (field.is_const() || field.is_final()) {
6538 ASSERT(field.value() != Object::sentinel()); 6582 ASSERT(field.value() != Object::sentinel());
6539 ASSERT(field.value() != Object::transition_sentinel()); 6583 ASSERT(field.value() != Object::transition_sentinel());
6540 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); 6584 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value()));
6541 } 6585 }
6542 // Access the field directly. 6586 // Access the field directly.
6543 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); 6587 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
6544 } 6588 }
6545 6589
6546 6590
6547 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, 6591 AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
6985 } 7029 }
6986 7030
6987 7031
6988 // If the field is already initialized, return no ast (NULL). 7032 // If the field is already initialized, return no ast (NULL).
6989 // Otherwise, if the field is constant, initialize the field and return no ast. 7033 // Otherwise, if the field is constant, initialize the field and return no ast.
6990 // If the field is not initialized and not const, return the ast for the getter. 7034 // If the field is not initialized and not const, return the ast for the getter.
6991 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { 7035 AstNode* Parser::RunStaticFieldInitializer(const Field& field) {
6992 ASSERT(field.is_static()); 7036 ASSERT(field.is_static());
6993 const Instance& value = Instance::Handle(field.value()); 7037 const Instance& value = Instance::Handle(field.value());
6994 if (value.raw() == Object::transition_sentinel()) { 7038 if (value.raw() == Object::transition_sentinel()) {
6995 if (field.is_const()) { 7039 // TODO(hausner): Remove the check for is_final() once we support
7040 // non-const final fields.
7041 if (field.is_const() || field.is_final()) {
6996 ErrorMsg("circular dependency while initializing static field '%s'", 7042 ErrorMsg("circular dependency while initializing static field '%s'",
6997 String::Handle(field.name()).ToCString()); 7043 String::Handle(field.name()).ToCString());
6998 } else { 7044 } else {
6999 // The implicit static getter will throw the exception if necessary. 7045 // The implicit static getter will throw the exception if necessary.
7000 return new StaticGetterNode(TokenPos(), 7046 return new StaticGetterNode(TokenPos(),
7001 NULL, 7047 NULL,
7002 Class::ZoneHandle(field.owner()), 7048 Class::ZoneHandle(field.owner()),
7003 String::ZoneHandle(field.name())); 7049 String::ZoneHandle(field.name()));
7004 } 7050 }
7005 } else if (value.raw() == Object::sentinel()) { 7051 } else if (value.raw() == Object::sentinel()) {
7006 // This field has not been referenced yet and thus the value has 7052 // This field has not been referenced yet and thus the value has
7007 // not been evaluated. If the field is const, call the static getter method 7053 // not been evaluated. If the field is const, call the static getter method
7008 // to evaluate the expression and canonicalize the value. 7054 // to evaluate the expression and canonicalize the value.
7009 if (field.is_const()) { 7055 // TODO(hausner): Remove the check for is_final() once we support
7056 // non-const final fields.
7057 if (field.is_const() || field.is_final()) {
7010 field.set_value(Instance::Handle(Object::transition_sentinel())); 7058 field.set_value(Instance::Handle(Object::transition_sentinel()));
7011 const String& field_name = String::Handle(field.name()); 7059 const String& field_name = String::Handle(field.name());
7012 const String& getter_name = 7060 const String& getter_name =
7013 String::Handle(Field::GetterName(field_name)); 7061 String::Handle(Field::GetterName(field_name));
7014 const Class& cls = Class::Handle(field.owner()); 7062 const Class& cls = Class::Handle(field.owner());
7015 GrowableArray<const Object*> arguments; // no arguments. 7063 GrowableArray<const Object*> arguments; // no arguments.
7016 const int kNumArguments = 0; // no arguments. 7064 const int kNumArguments = 0; // no arguments.
7017 const Array& kNoArgumentNames = Array::Handle(); 7065 const Array& kNoArgumentNames = Array::Handle();
7018 const Function& func = 7066 const Function& func =
7019 Function::Handle(Resolver::ResolveStatic(cls, 7067 Function::Handle(Resolver::ResolveStatic(cls,
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after
8179 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true); 8227 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true);
8180 ConsumeToken(); 8228 ConsumeToken();
8181 } else { 8229 } else {
8182 ASSERT(CurrentToken() == Token::kINTERPOL_START); 8230 ASSERT(CurrentToken() == Token::kINTERPOL_START);
8183 ConsumeToken(); 8231 ConsumeToken();
8184 expr = ParseExpr(kAllowConst, kConsumeCascades); 8232 expr = ParseExpr(kAllowConst, kConsumeCascades);
8185 ExpectToken(Token::kINTERPOL_END); 8233 ExpectToken(Token::kINTERPOL_END);
8186 } 8234 }
8187 // Check if this interpolated string is still considered a compile time 8235 // Check if this interpolated string is still considered a compile time
8188 // constant. If it is we need to evaluate if the current string part is 8236 // constant. If it is we need to evaluate if the current string part is
8189 // a constant or not. 8237 // a constant or not. Only stings, numbers, booleans and null values
8238 // are allowed in compile time const interpolations.
8190 if (is_compiletime_const) { 8239 if (is_compiletime_const) {
8191 const Object* const_expr = expr->EvalConstExpr(); 8240 const Object* const_expr = expr->EvalConstExpr();
8192 if (const_expr != NULL) { 8241 if ((const_expr != NULL) &&
8242 (const_expr->IsNumber() ||
8243 const_expr->IsString() ||
8244 const_expr->IsBool() ||
8245 const_expr->IsNull())) {
8193 // Change expr into a literal. 8246 // Change expr into a literal.
8194 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 8247 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr));
8195 } else { 8248 } else {
8196 is_compiletime_const = false; 8249 is_compiletime_const = false;
8197 } 8250 }
8198 } 8251 }
8199 values->AddElement(expr); 8252 values->AddElement(expr);
8200 } 8253 }
8201 } 8254 }
8202 if (is_compiletime_const) { 8255 if (is_compiletime_const) {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
8678 void Parser::SkipQualIdent() { 8731 void Parser::SkipQualIdent() {
8679 ASSERT(IsIdentifier()); 8732 ASSERT(IsIdentifier());
8680 ConsumeToken(); 8733 ConsumeToken();
8681 if (CurrentToken() == Token::kPERIOD) { 8734 if (CurrentToken() == Token::kPERIOD) {
8682 ConsumeToken(); // Consume the kPERIOD token. 8735 ConsumeToken(); // Consume the kPERIOD token.
8683 ExpectIdentifier("identifier expected after '.'"); 8736 ExpectIdentifier("identifier expected after '.'");
8684 } 8737 }
8685 } 8738 }
8686 8739
8687 } // namespace dart 8740 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698