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

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.
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
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
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
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 = &current_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
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
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
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
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