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

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

Issue 26703002: Final variables induce a setter that throws NSME (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 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/flow_graph_builder.cc ('k') | tests/co19/co19-runtime.status » ('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 "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
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
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
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
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 = &current_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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698