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