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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 3348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3359 // value is not assignable (assuming checked mode and disregarding actual | 3359 // value is not assignable (assuming checked mode and disregarding actual |
| 3360 // mode), the field value is reset and a kImplicitStaticFinalGetter is | 3360 // mode), the field value is reset and a kImplicitStaticFinalGetter is |
| 3361 // created at finalization time. | 3361 // created at finalization time. |
| 3362 | 3362 |
| 3363 if (field->has_static && (field->has_const || field->has_final) && | 3363 if (field->has_static && (field->has_const || field->has_final) && |
| 3364 (LookaheadToken(1) == Token::kSEMICOLON)) { | 3364 (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 3365 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); | 3365 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); |
| 3366 } | 3366 } |
| 3367 SkipExpr(); | 3367 SkipExpr(); |
| 3368 } else { | 3368 } else { |
| 3369 if (field->has_const || (field->has_static && field->has_final)) { | 3369 // Static const and static final fields must have an initializer. |
|
srdjan
2013/10/09 17:07:39
Please add comment that static const fields are im
hausner
2013/10/09 17:15:19
Done.
| |
| 3370 if (field->has_static && field->has_final) { | |
| 3370 ErrorMsg(field->name_pos, | 3371 ErrorMsg(field->name_pos, |
| 3371 "%s%s field '%s' must have an initializer expression", | 3372 "static %s field '%s' must have an initializer expression", |
| 3372 field->has_static ? "static " : "", | |
| 3373 field->has_const ? "const" : "final", | 3373 field->has_const ? "const" : "final", |
| 3374 field->name->ToCString()); | 3374 field->name->ToCString()); |
| 3375 } | 3375 } |
| 3376 } | 3376 } |
| 3377 | 3377 |
| 3378 // Create the field object. | 3378 // Create the field object. |
| 3379 class_field = Field::New(*field->name, | 3379 class_field = Field::New(*field->name, |
| 3380 field->has_static, | 3380 field->has_static, |
| 3381 field->has_final, | 3381 field->has_final, |
| 3382 field->has_const, | 3382 field->has_const, |
| (...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4473 ClassFinalizer::kResolveTypeParameters)); | 4473 ClassFinalizer::kResolveTypeParameters)); |
| 4474 Field& field = Field::Handle(); | 4474 Field& field = Field::Handle(); |
| 4475 Function& getter = Function::Handle(); | 4475 Function& getter = Function::Handle(); |
| 4476 while (true) { | 4476 while (true) { |
| 4477 const intptr_t name_pos = TokenPos(); | 4477 const intptr_t name_pos = TokenPos(); |
| 4478 String& var_name = *ExpectIdentifier("variable name expected"); | 4478 String& var_name = *ExpectIdentifier("variable name expected"); |
| 4479 | 4479 |
| 4480 if (library_.LookupLocalObject(var_name) != Object::null()) { | 4480 if (library_.LookupLocalObject(var_name) != Object::null()) { |
| 4481 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); | 4481 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); |
| 4482 } | 4482 } |
| 4483 | |
| 4484 // Check whether a getter or setter for this name exists. A const | |
| 4485 // or final field implies a setter which throws a NoSuchMethodError, | |
| 4486 // thus we need to check for conflicts with existing setters and | |
| 4487 // getters. | |
| 4483 String& accessor_name = String::Handle(Field::GetterName(var_name)); | 4488 String& accessor_name = String::Handle(Field::GetterName(var_name)); |
| 4484 if (library_.LookupLocalObject(accessor_name) != Object::null()) { | 4489 if (library_.LookupLocalObject(accessor_name) != Object::null()) { |
| 4485 ErrorMsg(name_pos, "getter for '%s' is already defined", | 4490 ErrorMsg(name_pos, "getter for '%s' is already defined", |
| 4486 var_name.ToCString()); | 4491 var_name.ToCString()); |
| 4487 } | 4492 } |
| 4488 // A const or final variable does not define an implicit setter, | 4493 accessor_name = Field::SetterName(var_name); |
| 4489 // so we only check setters for non-final variables. | 4494 if (library_.LookupLocalObject(accessor_name) != Object::null()) { |
| 4490 if (!is_final) { | 4495 ErrorMsg(name_pos, "setter for '%s' is already defined", |
| 4491 accessor_name = Field::SetterName(var_name); | 4496 var_name.ToCString()); |
| 4492 if (library_.LookupLocalObject(accessor_name) != Object::null()) { | |
| 4493 ErrorMsg(name_pos, "setter for '%s' is already defined", | |
| 4494 var_name.ToCString()); | |
| 4495 } | |
| 4496 } | 4497 } |
| 4497 | 4498 |
| 4498 field = Field::New(var_name, is_static, is_final, is_const, | 4499 field = Field::New(var_name, is_static, is_final, is_const, |
| 4499 current_class(), name_pos); | 4500 current_class(), name_pos); |
| 4500 field.set_type(type); | 4501 field.set_type(type); |
| 4501 field.set_value(Instance::Handle(Instance::null())); | 4502 field.set_value(Instance::Handle(Instance::null())); |
| 4502 top_level->fields.Add(field); | 4503 top_level->fields.Add(field); |
| 4503 library_.AddObject(field, var_name); | 4504 library_.AddObject(field, var_name); |
| 4504 if (metadata_pos >= 0) { | 4505 if (metadata_pos >= 0) { |
| 4505 library_.AddFieldMetadata(field, metadata_pos); | 4506 library_.AddFieldMetadata(field, metadata_pos); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4694 } else { | 4695 } else { |
| 4695 expected_num_parameters = 1; | 4696 expected_num_parameters = 1; |
| 4696 accessor_name = Field::SetterSymbol(*field_name); | 4697 accessor_name = Field::SetterSymbol(*field_name); |
| 4697 } | 4698 } |
| 4698 if ((params.num_fixed_parameters != expected_num_parameters) || | 4699 if ((params.num_fixed_parameters != expected_num_parameters) || |
| 4699 (params.num_optional_parameters != 0)) { | 4700 (params.num_optional_parameters != 0)) { |
| 4700 ErrorMsg(name_pos, "illegal %s parameters", | 4701 ErrorMsg(name_pos, "illegal %s parameters", |
| 4701 is_getter ? "getter" : "setter"); | 4702 is_getter ? "getter" : "setter"); |
| 4702 } | 4703 } |
| 4703 | 4704 |
| 4705 // Check whether this getter conflicts with a function or top-level variable | |
| 4706 // with the same name. | |
| 4704 if (is_getter && library_.LookupLocalObject(*field_name) != Object::null()) { | 4707 if (is_getter && library_.LookupLocalObject(*field_name) != Object::null()) { |
| 4705 ErrorMsg(name_pos, "'%s' is already defined in this library", | 4708 ErrorMsg(name_pos, "'%s' is already defined in this library", |
| 4706 field_name->ToCString()); | 4709 field_name->ToCString()); |
| 4707 } | 4710 } |
| 4708 if (!is_getter) { | 4711 // Check whether this setter conflicts with the implicit setter |
| 4709 // Check whether there is a field with the same name that has an implicit | 4712 // of a top-level variable with the same name. |
| 4710 // setter. | 4713 if (!is_getter && library_.LookupLocalField(*field_name) != Object::null()) { |
|
srdjan
2013/10/09 17:07:39
Add parentheses
hausner
2013/10/09 17:15:19
Done.
| |
| 4711 const Field& field = Field::Handle(library_.LookupLocalField(*field_name)); | 4714 ErrorMsg(name_pos, "Variable '%s' is already defined in this library", |
| 4712 if (!field.IsNull() && !field.is_final()) { | 4715 field_name->ToCString()); |
| 4713 ErrorMsg(name_pos, "Variable '%s' is already defined in this library", | |
| 4714 field_name->ToCString()); | |
| 4715 } | |
| 4716 } | 4716 } |
| 4717 bool found = library_.LookupLocalObject(accessor_name) != Object::null(); | 4717 bool found = library_.LookupLocalObject(accessor_name) != Object::null(); |
| 4718 if (found && !is_patch) { | 4718 if (found && !is_patch) { |
| 4719 ErrorMsg(name_pos, "%s for '%s' is already defined", | 4719 ErrorMsg(name_pos, "%s for '%s' is already defined", |
| 4720 is_getter ? "getter" : "setter", | 4720 is_getter ? "getter" : "setter", |
| 4721 field_name->ToCString()); | 4721 field_name->ToCString()); |
| 4722 } else if (!found && is_patch) { | 4722 } else if (!found && is_patch) { |
| 4723 ErrorMsg(name_pos, "missing %s for '%s' cannot be patched", | 4723 ErrorMsg(name_pos, "missing %s for '%s' cannot be patched", |
| 4724 is_getter ? "getter" : "setter", | 4724 is_getter ? "getter" : "setter", |
| 4725 field_name->ToCString()); | 4725 field_name->ToCString()); |
| (...skipping 2992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7718 } | 7718 } |
| 7719 | 7719 |
| 7720 | 7720 |
| 7721 AstNode* Parser::CreateAssignmentNode(AstNode* original, | 7721 AstNode* Parser::CreateAssignmentNode(AstNode* original, |
| 7722 AstNode* rhs, | 7722 AstNode* rhs, |
| 7723 const String* left_ident, | 7723 const String* left_ident, |
| 7724 intptr_t left_pos) { | 7724 intptr_t left_pos) { |
| 7725 AstNode* result = original->MakeAssignmentNode(rhs); | 7725 AstNode* result = original->MakeAssignmentNode(rhs); |
| 7726 if (result == NULL) { | 7726 if (result == NULL) { |
| 7727 String& name = String::ZoneHandle(); | 7727 String& name = String::ZoneHandle(); |
| 7728 const Class* target_cls = ¤t_class(); | |
| 7728 if (original->IsTypeNode()) { | 7729 if (original->IsTypeNode()) { |
| 7729 name = Symbols::New(original->AsTypeNode()->TypeName()); | 7730 name = Symbols::New(original->AsTypeNode()->TypeName()); |
| 7731 } else if (original->IsLoadStaticFieldNode()) { | |
| 7732 name = original->AsLoadStaticFieldNode()->field().name(); | |
| 7733 target_cls = | |
| 7734 &Class::Handle(original->AsLoadStaticFieldNode()->field().owner()); | |
| 7730 } else if ((left_ident != NULL) && | 7735 } else if ((left_ident != NULL) && |
| 7731 (original->IsLiteralNode() || | 7736 (original->IsLiteralNode() || |
| 7732 original->IsLoadLocalNode() || | 7737 original->IsLoadLocalNode())) { |
| 7733 original->IsLoadStaticFieldNode())) { | |
| 7734 name = left_ident->raw(); | 7738 name = left_ident->raw(); |
| 7735 } | 7739 } |
| 7736 if (name.IsNull()) { | 7740 if (name.IsNull()) { |
| 7737 ErrorMsg(left_pos, "expression is not assignable"); | 7741 ErrorMsg(left_pos, "expression is not assignable"); |
| 7738 } | 7742 } |
| 7739 result = ThrowNoSuchMethodError(original->token_pos(), | 7743 result = ThrowNoSuchMethodError(original->token_pos(), |
| 7740 current_class(), | 7744 *target_cls, |
| 7741 name, | 7745 name, |
| 7742 NULL, // No arguments. | 7746 NULL, // No arguments. |
| 7743 InvocationMirror::kStatic, | 7747 InvocationMirror::kStatic, |
| 7744 InvocationMirror::kSetter, | 7748 InvocationMirror::kSetter, |
| 7745 NULL); // No existing function. | 7749 NULL); // No existing function. |
| 7746 } else if (result->IsStoreIndexedNode() || | 7750 } else if (result->IsStoreIndexedNode() || |
| 7747 result->IsInstanceSetterNode() || | 7751 result->IsInstanceSetterNode() || |
| 7748 result->IsStaticSetterNode() || | 7752 result->IsStaticSetterNode() || |
| 7749 result->IsStoreStaticFieldNode() || | 7753 result->IsStoreStaticFieldNode() || |
| 7750 result->IsStoreLocalNode()) { | 7754 result->IsStoreLocalNode()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7782 Token::Kind assignment_op = CurrentToken(); | 7786 Token::Kind assignment_op = CurrentToken(); |
| 7783 const intptr_t assignment_pos = TokenPos(); | 7787 const intptr_t assignment_pos = TokenPos(); |
| 7784 ConsumeToken(); | 7788 ConsumeToken(); |
| 7785 AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades); | 7789 AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades); |
| 7786 if (assignment_op != Token::kASSIGN) { | 7790 if (assignment_op != Token::kASSIGN) { |
| 7787 // Compound assignment: store inputs with side effects into | 7791 // Compound assignment: store inputs with side effects into |
| 7788 // temporary locals. | 7792 // temporary locals. |
| 7789 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); | 7793 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); |
| 7790 right_expr = | 7794 right_expr = |
| 7791 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 7795 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); |
| 7792 AstNode* assign_expr = CreateAssignmentNode( | 7796 AstNode* assign_expr = |
| 7793 expr, right_expr, expr_ident, expr_pos); | 7797 CreateAssignmentNode(expr, right_expr, expr_ident, expr_pos); |
| 7794 ASSERT(assign_expr != NULL); | 7798 ASSERT(assign_expr != NULL); |
| 7795 let_expr->AddNode(assign_expr); | 7799 let_expr->AddNode(assign_expr); |
| 7796 expr = let_expr; | 7800 expr = let_expr; |
| 7797 } else { | 7801 } else { |
| 7798 right_expr = | 7802 right_expr = |
| 7799 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 7803 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); |
| 7800 AstNode* assign_expr = CreateAssignmentNode( | 7804 AstNode* assign_expr = |
| 7801 expr, right_expr, expr_ident, expr_pos); | 7805 CreateAssignmentNode(expr, right_expr, expr_ident, expr_pos); |
| 7802 ASSERT(assign_expr != NULL); | 7806 ASSERT(assign_expr != NULL); |
| 7803 expr = assign_expr; | 7807 expr = assign_expr; |
| 7804 } | 7808 } |
| 7805 } | 7809 } |
| 7806 cascade->AddNode(expr); | 7810 cascade->AddNode(expr); |
| 7807 } | 7811 } |
| 7808 // The result is an expression with the (side effects of the) cascade | 7812 // The result is an expression with the (side effects of the) cascade |
| 7809 // sequence followed by the (value of the) receiver temp variable load. | 7813 // sequence followed by the (value of the) receiver temp variable load. |
| 7810 cascade->AddNode(new LoadLocalNode(cascade_pos, cascade_receiver_var)); | 7814 cascade->AddNode(new LoadLocalNode(cascade_pos, cascade_receiver_var)); |
| 7811 return cascade; | 7815 return cascade; |
| 7812 } | 7816 } |
| 7813 | 7817 |
| 7814 | 7818 |
| 7819 static AstNode* LoadIfStaticConst(AstNode* expr) { | |
|
srdjan
2013/10/09 17:07:39
IMO, name is not quite clear (there is no load inv
hausner
2013/10/09 17:15:19
Done.
| |
| 7820 if (expr->IsLoadStaticFieldNode()) { | |
| 7821 const Field& field = expr->AsLoadStaticFieldNode()->field(); | |
| 7822 if (field.is_const()) { | |
| 7823 ASSERT(field.value() != Object::sentinel().raw()); | |
| 7824 ASSERT(field.value() != Object::transition_sentinel().raw()); | |
| 7825 return new LiteralNode(expr->token_pos(), | |
| 7826 Instance::ZoneHandle(field.value())); | |
| 7827 } | |
| 7828 } | |
| 7829 return expr; | |
| 7830 } | |
| 7831 | |
| 7832 | |
| 7815 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 7833 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 7816 bool consume_cascades) { | 7834 bool consume_cascades) { |
| 7817 TRACE_PARSER("ParseExpr"); | 7835 TRACE_PARSER("ParseExpr"); |
| 7818 String* expr_ident = | 7836 String* expr_ident = |
| 7819 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; | 7837 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; |
| 7820 const intptr_t expr_pos = TokenPos(); | 7838 const intptr_t expr_pos = TokenPos(); |
| 7821 | 7839 |
| 7822 if (CurrentToken() == Token::kTHROW) { | 7840 if (CurrentToken() == Token::kTHROW) { |
| 7823 ConsumeToken(); | 7841 ConsumeToken(); |
| 7824 if (CurrentToken() == Token::kSEMICOLON) { | 7842 if (CurrentToken() == Token::kSEMICOLON) { |
| 7825 ErrorMsg("expression expected after throw"); | 7843 ErrorMsg("expression expected after throw"); |
| 7826 } | 7844 } |
| 7827 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); | 7845 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 7828 return new ThrowNode(expr_pos, expr, NULL); | 7846 return new ThrowNode(expr_pos, expr, NULL); |
| 7829 } | 7847 } |
| 7830 AstNode* expr = ParseConditionalExpr(); | 7848 AstNode* expr = ParseConditionalExpr(); |
| 7831 if (!Token::IsAssignmentOperator(CurrentToken())) { | 7849 if (!Token::IsAssignmentOperator(CurrentToken())) { |
| 7832 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { | 7850 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { |
| 7833 return ParseCascades(expr); | 7851 return ParseCascades(expr); |
| 7834 } | 7852 } |
| 7853 expr = LoadIfStaticConst(expr); | |
| 7835 if (require_compiletime_const) { | 7854 if (require_compiletime_const) { |
| 7836 expr = FoldConstExpr(expr_pos, expr); | 7855 expr = FoldConstExpr(expr_pos, expr); |
| 7837 } | 7856 } |
| 7838 return expr; | 7857 return expr; |
| 7839 } | 7858 } |
| 7840 // Assignment expressions. | 7859 // Assignment expressions. |
| 7841 const Token::Kind assignment_op = CurrentToken(); | 7860 const Token::Kind assignment_op = CurrentToken(); |
| 7842 const intptr_t assignment_pos = TokenPos(); | 7861 const intptr_t assignment_pos = TokenPos(); |
| 7843 ConsumeToken(); | 7862 ConsumeToken(); |
| 7844 const intptr_t right_expr_pos = TokenPos(); | 7863 const intptr_t right_expr_pos = TokenPos(); |
| 7845 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { | 7864 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { |
| 7846 ErrorMsg(right_expr_pos, "expression is not a valid compile-time constant"); | 7865 ErrorMsg(right_expr_pos, "expression is not a valid compile-time constant"); |
| 7847 } | 7866 } |
| 7848 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); | 7867 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 7849 if (assignment_op != Token::kASSIGN) { | 7868 if (assignment_op != Token::kASSIGN) { |
| 7850 // Compound assignment: store inputs with side effects into temp. locals. | 7869 // Compound assignment: store inputs with side effects into temp. locals. |
| 7851 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); | 7870 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); |
| 7852 AstNode* assigned_value = | 7871 AstNode* assigned_value = |
| 7853 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 7872 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); |
| 7854 AstNode* assign_expr = CreateAssignmentNode( | 7873 AstNode* assign_expr = |
| 7855 expr, assigned_value, expr_ident, expr_pos); | 7874 CreateAssignmentNode(expr, assigned_value, expr_ident, expr_pos); |
| 7856 ASSERT(assign_expr != NULL); | 7875 ASSERT(assign_expr != NULL); |
| 7857 let_expr->AddNode(assign_expr); | 7876 let_expr->AddNode(assign_expr); |
| 7858 return let_expr; | 7877 return let_expr; |
| 7859 } else { | 7878 } else { |
| 7860 AstNode* assigned_value = | 7879 AstNode* assigned_value = LoadIfStaticConst(right_expr); |
| 7861 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 7880 AstNode* assign_expr = |
| 7862 AstNode* assign_expr = CreateAssignmentNode( | 7881 CreateAssignmentNode(expr, assigned_value, expr_ident, expr_pos); |
| 7863 expr, assigned_value, expr_ident, expr_pos); | |
| 7864 ASSERT(assign_expr != NULL); | 7882 ASSERT(assign_expr != NULL); |
| 7865 return assign_expr; | 7883 return assign_expr; |
| 7866 } | 7884 } |
| 7867 } | 7885 } |
| 7868 | 7886 |
| 7869 | 7887 |
| 7870 LiteralNode* Parser::ParseConstExpr() { | 7888 LiteralNode* Parser::ParseConstExpr() { |
| 7871 TRACE_PARSER("ParseConstExpr"); | 7889 TRACE_PARSER("ParseConstExpr"); |
| 7872 AstNode* expr = ParseExpr(kRequireConst, kNoCascades); | 7890 AstNode* expr = ParseExpr(kRequireConst, kNoCascades); |
| 7873 ASSERT(expr->IsLiteralNode()); | 7891 ASSERT(expr->IsLiteralNode()); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8080 intptr_t ident_pos) { | 8098 intptr_t ident_pos) { |
| 8081 // If the static field has an initializer, initialize the field at compile | 8099 // If the static field has an initializer, initialize the field at compile |
| 8082 // time, which is only possible if the field is const. | 8100 // time, which is only possible if the field is const. |
| 8083 AstNode* initializing_getter = RunStaticFieldInitializer(field); | 8101 AstNode* initializing_getter = RunStaticFieldInitializer(field); |
| 8084 if (initializing_getter != NULL) { | 8102 if (initializing_getter != NULL) { |
| 8085 // The field is not yet initialized and could not be initialized at compile | 8103 // The field is not yet initialized and could not be initialized at compile |
| 8086 // time. The getter will initialize the field. | 8104 // time. The getter will initialize the field. |
| 8087 return initializing_getter; | 8105 return initializing_getter; |
| 8088 } | 8106 } |
| 8089 // The field is initialized. | 8107 // The field is initialized. |
| 8090 if (field.is_const()) { | |
| 8091 ASSERT(field.value() != Object::sentinel().raw()); | |
| 8092 ASSERT(field.value() != Object::transition_sentinel().raw()); | |
| 8093 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); | |
| 8094 } | |
| 8095 ASSERT(field.is_static()); | 8108 ASSERT(field.is_static()); |
| 8096 const Class& field_owner = Class::ZoneHandle(field.owner()); | 8109 const Class& field_owner = Class::ZoneHandle(field.owner()); |
| 8097 const String& field_name = String::ZoneHandle(field.name()); | 8110 const String& field_name = String::ZoneHandle(field.name()); |
| 8098 const String& getter_name = String::Handle(Field::GetterName(field_name)); | 8111 const String& getter_name = String::Handle(Field::GetterName(field_name)); |
| 8099 const Function& getter = | 8112 const Function& getter = |
| 8100 Function::Handle(field_owner.LookupStaticFunction(getter_name)); | 8113 Function::Handle(field_owner.LookupStaticFunction(getter_name)); |
| 8101 // Never load field directly if there is a getter (deterministic AST). | 8114 // Never load field directly if there is a getter (deterministic AST). |
| 8102 if (getter.IsNull()) { | 8115 if (getter.IsNull()) { |
| 8103 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); | 8116 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); |
| 8104 } else { | 8117 } else { |
| 8105 ASSERT(getter.kind() == RawFunction::kImplicitStaticFinalGetter); | 8118 ASSERT(getter.kind() == RawFunction::kImplicitStaticFinalGetter); |
| 8106 return new StaticGetterNode(ident_pos, | 8119 return new StaticGetterNode(ident_pos, |
| 8107 NULL, // Receiver. | 8120 NULL, // Receiver. |
| 8108 false, // is_super_getter. | 8121 false, // is_super_getter. |
| 8109 field_owner, | 8122 field_owner, |
| 8110 field_name); | 8123 field_name); |
| 8111 } | 8124 } |
| 8112 } | 8125 } |
| 8113 | 8126 |
| 8114 | 8127 |
| 8115 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, | 8128 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, |
| 8116 const String& field_name, | 8129 const String& field_name, |
| 8117 intptr_t ident_pos, | 8130 intptr_t ident_pos, |
| 8118 bool consume_cascades) { | 8131 bool consume_cascades) { |
| 8119 TRACE_PARSER("ParseStaticFieldAccess"); | 8132 TRACE_PARSER("ParseStaticFieldAccess"); |
| 8120 AstNode* access = NULL; | 8133 AstNode* access = NULL; |
| 8121 const intptr_t call_pos = TokenPos(); | 8134 const intptr_t call_pos = TokenPos(); |
| 8122 const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name)); | 8135 const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name)); |
| 8123 Function& func = Function::ZoneHandle(); | 8136 Function& func = Function::ZoneHandle(); |
| 8124 if (Token::IsAssignmentOperator(CurrentToken())) { | 8137 if (field.IsNull()) { |
| 8125 // Make sure an assignment is legal. | 8138 // No field, check if we have an explicit getter function. |
| 8126 if (field.IsNull()) { | 8139 const String& getter_name = |
| 8127 // No field, check if we have an explicit setter function. | 8140 String::ZoneHandle(Field::GetterName(field_name)); |
| 8128 const String& setter_name = | 8141 const int kNumArguments = 0; // no arguments. |
| 8129 String::ZoneHandle(Field::SetterName(field_name)); | 8142 func = Resolver::ResolveStatic(cls, |
| 8130 const int kNumArguments = 1; // value. | 8143 getter_name, |
| 8131 func = Resolver::ResolveStatic(cls, | 8144 kNumArguments, |
| 8132 setter_name, | 8145 Object::empty_array(), |
| 8133 kNumArguments, | 8146 Resolver::kIsQualified); |
| 8134 Object::empty_array(), | 8147 if (func.IsNull()) { |
| 8135 Resolver::kIsQualified); | 8148 // We might be referring to an implicit closure, check to see if |
| 8136 if (func.IsNull()) { | 8149 // there is a function of the same name. |
| 8137 // No field or explicit setter function, throw a NoSuchMethodError. | 8150 func = cls.LookupStaticFunction(field_name); |
| 8138 return ThrowNoSuchMethodError(ident_pos, | 8151 if (!func.IsNull()) { |
| 8139 cls, | |
| 8140 field_name, | |
| 8141 NULL, // No arguments. | |
| 8142 InvocationMirror::kStatic, | |
| 8143 InvocationMirror::kField, | |
| 8144 NULL); // No existing function. | |
| 8145 } | |
| 8146 | |
| 8147 // Explicit setter function for the field found, field does not exist. | |
| 8148 // Create a getter node first in case it is needed. If getter node | |
| 8149 // is used as part of, e.g., "+=", and the explicit getter does not | |
| 8150 // exist, and error will be reported by the code generator. | |
| 8151 access = new StaticGetterNode(call_pos, | |
| 8152 NULL, | |
| 8153 false, | |
| 8154 Class::ZoneHandle(cls.raw()), | |
| 8155 String::ZoneHandle(field_name.raw())); | |
| 8156 } else { | |
| 8157 // Field exists. | |
| 8158 if (field.is_final()) { | |
| 8159 // Field has been marked as final, report an error as the field | |
| 8160 // is not settable. | |
| 8161 ErrorMsg(ident_pos, | |
| 8162 "field '%s' is const static, cannot assign to it", | |
| 8163 field_name.ToCString()); | |
| 8164 } | |
| 8165 access = GenerateStaticFieldLookup(field, TokenPos()); | |
| 8166 } | |
| 8167 } else { // Not Token::IsAssignmentOperator(CurrentToken()). | |
| 8168 if (field.IsNull()) { | |
| 8169 // No field, check if we have an explicit getter function. | |
| 8170 const String& getter_name = | |
| 8171 String::ZoneHandle(Field::GetterName(field_name)); | |
| 8172 const int kNumArguments = 0; // no arguments. | |
| 8173 func = Resolver::ResolveStatic(cls, | |
| 8174 getter_name, | |
| 8175 kNumArguments, | |
| 8176 Object::empty_array(), | |
| 8177 Resolver::kIsQualified); | |
| 8178 if (func.IsNull()) { | |
| 8179 // We might be referring to an implicit closure, check to see if | |
| 8180 // there is a function of the same name. | |
| 8181 func = cls.LookupStaticFunction(field_name); | |
| 8182 if (func.IsNull()) { | |
| 8183 // No field or explicit getter function, throw a NoSuchMethodError. | |
| 8184 return ThrowNoSuchMethodError(ident_pos, | |
| 8185 cls, | |
| 8186 field_name, | |
| 8187 NULL, // No arguments. | |
| 8188 InvocationMirror::kStatic, | |
| 8189 InvocationMirror::kGetter, | |
| 8190 NULL); // No existing function. | |
| 8191 } | |
| 8192 access = CreateImplicitClosureNode(func, call_pos, NULL); | 8152 access = CreateImplicitClosureNode(func, call_pos, NULL); |
| 8193 } else { | 8153 } else { |
| 8194 ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter); | 8154 // No function to closureize found found. |
|
srdjan
2013/10/09 17:07:39
s/closureize/closurize/
hausner
2013/10/09 17:15:19
Done.
| |
| 8155 // This field access may turn out to be a call to the setter. | |
| 8156 // Create a getter call, which may later be turned into | |
| 8157 // a setter call, or else the backend will generate | |
| 8158 // a throw NoSuchMethodError(). | |
| 8195 access = new StaticGetterNode(call_pos, | 8159 access = new StaticGetterNode(call_pos, |
| 8196 NULL, | 8160 NULL, |
| 8197 false, | 8161 false, |
| 8198 Class::ZoneHandle(cls.raw()), | 8162 Class::ZoneHandle(cls.raw()), |
| 8199 field_name); | 8163 field_name); |
| 8200 } | 8164 } |
| 8201 } else { | 8165 } else { |
| 8202 access = GenerateStaticFieldLookup(field, TokenPos()); | 8166 ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter); |
| 8167 access = new StaticGetterNode(call_pos, | |
| 8168 NULL, | |
| 8169 false, | |
| 8170 Class::ZoneHandle(cls.raw()), | |
| 8171 field_name); | |
| 8203 } | 8172 } |
| 8173 } else { | |
| 8174 access = GenerateStaticFieldLookup(field, TokenPos()); | |
| 8204 } | 8175 } |
| 8205 return access; | 8176 return access; |
| 8206 } | 8177 } |
| 8207 | 8178 |
| 8208 | 8179 |
| 8209 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) { | 8180 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) { |
| 8210 if (!node->IsPrimaryNode()) { | 8181 if (!node->IsPrimaryNode()) { |
| 8211 return node; | 8182 return node; |
| 8212 } | 8183 } |
| 8213 PrimaryNode* primary = node->AsPrimaryNode(); | 8184 PrimaryNode* primary = node->AsPrimaryNode(); |
| (...skipping 2422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10636 void Parser::SkipQualIdent() { | 10607 void Parser::SkipQualIdent() { |
| 10637 ASSERT(IsIdentifier()); | 10608 ASSERT(IsIdentifier()); |
| 10638 ConsumeToken(); | 10609 ConsumeToken(); |
| 10639 if (CurrentToken() == Token::kPERIOD) { | 10610 if (CurrentToken() == Token::kPERIOD) { |
| 10640 ConsumeToken(); // Consume the kPERIOD token. | 10611 ConsumeToken(); // Consume the kPERIOD token. |
| 10641 ExpectIdentifier("identifier expected after '.'"); | 10612 ExpectIdentifier("identifier expected after '.'"); |
| 10642 } | 10613 } |
| 10643 } | 10614 } |
| 10644 | 10615 |
| 10645 } // namespace dart | 10616 } // namespace dart |
| OLD | NEW |