Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2522 if (field->has_factory) { | 2522 if (field->has_factory) { |
| 2523 ErrorMsg("keyword 'factory' not allowed in field declaration"); | 2523 ErrorMsg("keyword 'factory' not allowed in field declaration"); |
| 2524 } | 2524 } |
| 2525 if (members->FieldNameExists(*field->name)) { | 2525 if (members->FieldNameExists(*field->name)) { |
| 2526 ErrorMsg(field->name_pos, | 2526 ErrorMsg(field->name_pos, |
| 2527 "'%s' field/method already defined\n", field->name->ToCString()); | 2527 "'%s' field/method already defined\n", field->name->ToCString()); |
| 2528 } | 2528 } |
| 2529 Function& getter = Function::Handle(); | 2529 Function& getter = Function::Handle(); |
| 2530 Function& setter = Function::Handle(); | 2530 Function& setter = Function::Handle(); |
| 2531 Field& class_field = Field::Handle(); | 2531 Field& class_field = Field::Handle(); |
| 2532 Instance& init_value = Instance::Handle(); | |
| 2532 while (true) { | 2533 while (true) { |
| 2533 bool has_initializer = CurrentToken() == Token::kASSIGN; | 2534 bool has_initializer = CurrentToken() == Token::kASSIGN; |
| 2535 bool have_simple_literal = false; | |
|
regis
2012/07/31 23:19:54
has_simple_literal?
hausner
2012/07/31 23:34:03
Done.
| |
| 2534 if (has_initializer) { | 2536 if (has_initializer) { |
| 2535 ConsumeToken(); | 2537 ConsumeToken(); |
| 2538 init_value = Object::sentinel(); | |
| 2536 // For static final fields, the initialization expression | 2539 // For static final fields, the initialization expression |
| 2537 // will be parsed through the kConstImplicitGetter method | 2540 // will be parsed through the kConstImplicitGetter method |
| 2538 // invocation/compilation. | 2541 // invocation/compilation. |
| 2539 // For instance fields, the expression is parsed when a constructor | 2542 // For instance fields, the expression is parsed when a constructor |
| 2540 // is compiled. | 2543 // is compiled. |
| 2544 // For static fields with very simple initializer expressions | |
| 2545 // (e.g. a literal number or string) we optimize away the | |
| 2546 // kConstImplicitGetter and initialize the field here. | |
| 2547 | |
| 2548 if (field->has_static && (field->has_final || field->has_const) && | |
| 2549 (LookaheadToken(1) == Token::kSEMICOLON)) { | |
| 2550 have_simple_literal = IsSimpleLiteral(*field->type, &init_value); | |
| 2551 } | |
| 2541 SkipExpr(); | 2552 SkipExpr(); |
| 2542 } else { | 2553 } else { |
| 2543 if (field->has_const || (field->has_static && field->has_final)) { | 2554 if (field->has_const || (field->has_static && field->has_final)) { |
| 2544 ErrorMsg(field->name_pos, | 2555 ErrorMsg(field->name_pos, |
| 2545 "%s%s field '%s' must have an initializer expression", | 2556 "%s%s field '%s' must have an initializer expression", |
| 2546 field->has_static ? "static " : "", | 2557 field->has_static ? "static " : "", |
| 2547 field->has_const ? "const" : "final", | 2558 field->has_const ? "const" : "final", |
| 2548 field->name->ToCString()); | 2559 field->name->ToCString()); |
| 2549 } | 2560 } |
| 2550 } | 2561 } |
| 2551 | 2562 |
| 2552 // Create the field object. | 2563 // Create the field object. |
| 2553 // TODO(hausner): For now, all static final fields are constant. Remove | 2564 // TODO(hausner): For now, all static final fields are constant. Remove |
| 2554 // this when lazy init of static variables is implemented. | 2565 // this when lazy init of static variables is implemented. |
| 2555 class_field = Field::New(*field->name, | 2566 class_field = Field::New(*field->name, |
| 2556 field->has_static, | 2567 field->has_static, |
| 2557 field->has_final, | 2568 field->has_final, |
| 2558 field->has_const || field->has_final, | 2569 field->has_const || field->has_final, |
| 2559 field->name_pos); | 2570 field->name_pos); |
| 2560 class_field.set_type(*field->type); | 2571 class_field.set_type(*field->type); |
| 2561 class_field.set_has_initializer(has_initializer); | 2572 class_field.set_has_initializer(has_initializer); |
| 2562 members->AddField(class_field); | 2573 members->AddField(class_field); |
| 2563 | 2574 |
| 2564 // For static final fields, set value to "uninitialized" and | 2575 // For static final fields, set value to "uninitialized" and |
| 2565 // create a kConstImplicitGetter getter method. | 2576 // create a kConstImplicitGetter getter method. |
| 2566 if (field->has_static && has_initializer) { | 2577 if (field->has_static && has_initializer) { |
| 2567 class_field.set_value(Instance::Handle(Object::sentinel())); | 2578 class_field.set_value(init_value); |
| 2568 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); | 2579 if (!have_simple_literal) { |
| 2569 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, | 2580 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); |
| 2570 field->has_static, field->has_final, false, | 2581 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, |
| 2571 /* is_abstract */ false, | 2582 field->has_static, field->has_final, |
| 2572 field->name_pos); | 2583 /* is_abstract */ false, |
| 2573 getter.set_result_type(*field->type); | 2584 /* is_external */ false, |
| 2574 members->AddFunction(getter); | 2585 field->name_pos); |
| 2586 getter.set_result_type(*field->type); | |
| 2587 members->AddFunction(getter); | |
| 2588 } | |
| 2575 } | 2589 } |
| 2576 | 2590 |
| 2577 // For instance fields, we create implicit getter and setter methods. | 2591 // For instance fields, we create implicit getter and setter methods. |
| 2578 if (!field->has_static) { | 2592 if (!field->has_static) { |
| 2579 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); | 2593 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); |
| 2580 getter = Function::New(getter_name, RawFunction::kImplicitGetter, | 2594 getter = Function::New(getter_name, RawFunction::kImplicitGetter, |
| 2581 field->has_static, field->has_final, false, | 2595 field->has_static, field->has_final, false, |
| 2582 /* is_abstract */ false, | 2596 /* is_abstract */ false, |
| 2583 field->name_pos); | 2597 field->name_pos); |
| 2584 ParamList params; | 2598 ParamList params; |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3512 var_name.ToCString()); | 3526 var_name.ToCString()); |
| 3513 } | 3527 } |
| 3514 | 3528 |
| 3515 field = Field::New(var_name, is_static, is_final, is_const, name_pos); | 3529 field = Field::New(var_name, is_static, is_final, is_const, name_pos); |
| 3516 field.set_type(type); | 3530 field.set_type(type); |
| 3517 field.set_value(Instance::Handle(Instance::null())); | 3531 field.set_value(Instance::Handle(Instance::null())); |
| 3518 top_level->fields.Add(field); | 3532 top_level->fields.Add(field); |
| 3519 library_.AddObject(field, var_name); | 3533 library_.AddObject(field, var_name); |
| 3520 if (CurrentToken() == Token::kASSIGN) { | 3534 if (CurrentToken() == Token::kASSIGN) { |
| 3521 ConsumeToken(); | 3535 ConsumeToken(); |
| 3536 Instance& field_value = Instance::Handle(Object::sentinel()); | |
| 3537 bool have_simple_literal = false; | |
| 3538 if ((is_final || is_const) && (LookaheadToken(1) == Token::kSEMICOLON)) { | |
| 3539 have_simple_literal = IsSimpleLiteral(type, &field_value); | |
| 3540 } | |
| 3522 SkipExpr(); | 3541 SkipExpr(); |
| 3523 field.set_value(Instance::Handle(Object::sentinel())); | 3542 field.set_value(field_value); |
| 3524 // Create a static const getter. | 3543 if (!have_simple_literal) { |
| 3525 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); | 3544 // Create a static const getter. |
| 3526 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, | 3545 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); |
| 3527 is_static, is_final, false, false, name_pos); | 3546 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, |
| 3528 getter.set_result_type(type); | 3547 is_static, is_final, false, false, name_pos); |
| 3529 top_level->functions.Add(getter); | 3548 getter.set_result_type(type); |
| 3549 top_level->functions.Add(getter); | |
| 3550 } | |
| 3551 | |
| 3530 } else if (is_final || is_const) { | 3552 } else if (is_final || is_const) { |
| 3531 ErrorMsg(name_pos, "missing initializer for final or const variable"); | 3553 ErrorMsg(name_pos, "missing initializer for final or const variable"); |
| 3532 } | 3554 } |
| 3533 | 3555 |
| 3534 if (CurrentToken() == Token::kCOMMA) { | 3556 if (CurrentToken() == Token::kCOMMA) { |
| 3535 ConsumeToken(); | 3557 ConsumeToken(); |
| 3536 } else if (CurrentToken() == Token::kSEMICOLON) { | 3558 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 3537 ConsumeToken(); | 3559 ConsumeToken(); |
| 3538 break; | 3560 break; |
| 3539 } else { | 3561 } else { |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4461 ConsumeToken(); | 4483 ConsumeToken(); |
| 4462 } while (nesting_level > 0); | 4484 } while (nesting_level > 0); |
| 4463 if (nesting_level < 0) { | 4485 if (nesting_level < 0) { |
| 4464 return false; | 4486 return false; |
| 4465 } | 4487 } |
| 4466 } | 4488 } |
| 4467 return true; | 4489 return true; |
| 4468 } | 4490 } |
| 4469 | 4491 |
| 4470 | 4492 |
| 4493 bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) { | |
| 4494 bool no_check = type.IsDynamicType(); | |
| 4495 if ((CurrentToken() == Token::kINTEGER) && | |
| 4496 (no_check || type.IsIntInterface() || type.IsNumberInterface())) { | |
| 4497 *value = CurrentIntegerLiteral(); | |
| 4498 return true; | |
| 4499 } else if ((CurrentToken() == Token::kDOUBLE) && | |
| 4500 (no_check || type.IsDoubleInterface() || type.IsNumberInterface())) { | |
| 4501 *value = CurrentDoubleLiteral(); | |
| 4502 return true; | |
| 4503 } else if ((CurrentToken() == Token::kSTRING) && | |
| 4504 (no_check || type.IsStringInterface())) { | |
| 4505 *value = CurrentLiteral()->raw(); | |
|
regis
2012/07/31 23:19:54
Not specific to this change list, but it feels str
hausner
2012/07/31 23:34:03
True. CurrentLiteral used to return a pointer to a
| |
| 4506 return true; | |
| 4507 } else if ((CurrentToken() == Token::kTRUE) && | |
| 4508 (no_check || type.IsBoolInterface())) { | |
| 4509 *value = Bool::True(); | |
| 4510 return true; | |
| 4511 } else if ((CurrentToken() == Token::kFALSE) && | |
| 4512 (no_check || type.IsBoolInterface())) { | |
| 4513 *value = Bool::False(); | |
| 4514 return true; | |
| 4515 } else if (CurrentToken() == Token::kNULL) { | |
| 4516 *value = Instance::null(); | |
| 4517 return true; | |
| 4518 } | |
| 4519 return false; | |
| 4520 } | |
| 4521 | |
| 4522 | |
| 4471 // Returns true if the current token is kIDENT or a pseudo-keyword. | 4523 // Returns true if the current token is kIDENT or a pseudo-keyword. |
| 4472 bool Parser::IsIdentifier() { | 4524 bool Parser::IsIdentifier() { |
| 4473 return Token::IsIdentifier(CurrentToken()); | 4525 return Token::IsIdentifier(CurrentToken()); |
| 4474 } | 4526 } |
| 4475 | 4527 |
| 4476 | 4528 |
| 4477 // Returns true if the next tokens can be parsed as a type with optional | 4529 // Returns true if the next tokens can be parsed as a type with optional |
| 4478 // type parameters. Current token position is not restored. | 4530 // type parameters. Current token position is not restored. |
| 4479 bool Parser::TryParseOptionalType() { | 4531 bool Parser::TryParseOptionalType() { |
| 4480 if (CurrentToken() == Token::kIDENT) { | 4532 if (CurrentToken() == Token::kIDENT) { |
| (...skipping 4308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8789 void Parser::SkipQualIdent() { | 8841 void Parser::SkipQualIdent() { |
| 8790 ASSERT(IsIdentifier()); | 8842 ASSERT(IsIdentifier()); |
| 8791 ConsumeToken(); | 8843 ConsumeToken(); |
| 8792 if (CurrentToken() == Token::kPERIOD) { | 8844 if (CurrentToken() == Token::kPERIOD) { |
| 8793 ConsumeToken(); // Consume the kPERIOD token. | 8845 ConsumeToken(); // Consume the kPERIOD token. |
| 8794 ExpectIdentifier("identifier expected after '.'"); | 8846 ExpectIdentifier("identifier expected after '.'"); |
| 8795 } | 8847 } |
| 8796 } | 8848 } |
| 8797 | 8849 |
| 8798 } // namespace dart | 8850 } // namespace dart |
| OLD | NEW |