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

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

Issue 1090373006: Properly resolve top-level setters (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 8 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/ast.h" 5 #include "vm/ast.h"
6 #include "vm/compiler.h" 6 #include "vm/compiler.h"
7 #include "vm/dart_entry.h" 7 #include "vm/dart_entry.h"
8 #include "vm/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 #include "vm/resolver.h" 10 #include "vm/resolver.h"
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 554
555 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { 555 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) {
556 return new StoreIndexedNode(token_pos(), array(), index_expr(), 556 return new StoreIndexedNode(token_pos(), array(), index_expr(),
557 rhs, super_class()); 557 rhs, super_class());
558 } 558 }
559 559
560 560
561 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { 561 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) {
562 if (is_super_getter()) { 562 if (is_super_getter()) {
563 ASSERT(receiver() != NULL); 563 ASSERT(receiver() != NULL);
564 // If the static setter is not found in the superclass, noSuchMethod will be 564 const String& setter_name =
565 // called at runtime. 565 String::ZoneHandle(Field::SetterSymbol(field_name_));
566 Function& setter = Function::ZoneHandle(
567 Resolver::ResolveDynamicAnyArgs(cls(), setter_name));
568 if (setter.IsNull() || setter.is_abstract()) {
569 // No instance setter found in super class chain,
570 // noSuchMethod will be called at runtime.
571 return new StaticSetterNode(token_pos(),
572 receiver(),
573 cls(),
574 field_name_,
575 rhs);
576 }
566 return new StaticSetterNode(token_pos(), 577 return new StaticSetterNode(token_pos(),
567 receiver(), 578 receiver(),
568 cls(), 579 field_name_,
569 field_name(), 580 setter,
570 rhs); 581 rhs);
571 } 582 }
572 583
584 if (owner().IsLibraryPrefix()) {
585 const LibraryPrefix& prefix = LibraryPrefix::Cast(owner_);
586 // The parser has already dealt with the pathological case where a
587 // library imports itself. See Parser::ResolveIdentInPrefixScope()
588 ASSERT(field_name_.CharAt(0) != Library::kPrivateIdentifierStart);
589
590 // If the prefix is not yet loaded, the getter doesn't exist. Return a
591 // setter that will throw a NSME at runtime.
592 if (!prefix.is_loaded()) {
593 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
594 }
595
596 Object& obj = Object::Handle(prefix.LookupObject(field_name_));
597 if (obj.IsField()) {
598 const Field& field = Field::ZoneHandle(Field::Cast(obj).raw());
599 if (!field.is_final()) {
600 if (Isolate::Current()->TypeChecksEnabled()) {
601 rhs = new AssignableNode(field.token_pos(),
602 rhs,
603 AbstractType::ZoneHandle(field.type()),
604 field_name_);
605 }
606 return new StoreStaticFieldNode(token_pos(), field, rhs);
regis 2015/04/21 17:30:30 Indent lines 600-606.
hausner 2015/04/21 17:40:11 Done.
607 }
608 }
609
610 // No field found in prefix. Look for a setter function.
611 const String& setter_name = String::Handle(Field::SetterName(field_name_));
612 obj = prefix.LookupObject(setter_name);
613 if (obj.IsFunction()) {
614 const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw());
615 ASSERT(setter.is_static() && setter.IsSetterFunction());
616 return new StaticSetterNode(
617 token_pos(), NULL, field_name_, setter, rhs);
618 }
619
620 // No writeable field and no setter found in the prefix. Return a
621 // non-existing setter that will throw an NSM error.
622 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
623 }
624
625 if (owner().IsLibrary()) {
626 const Library& library = Library::Cast(owner());
627 Object& obj = Object::Handle(library.ResolveName(field_name_));
628 if (obj.IsField()) {
629 const Field& field = Field::ZoneHandle(Field::Cast(obj).raw());
630 if (!field.is_final()) {
631 if (Isolate::Current()->TypeChecksEnabled()) {
632 rhs = new AssignableNode(field.token_pos(),
633 rhs,
634 AbstractType::ZoneHandle(field.type()),
635 field_name_);
636 }
637 return new StoreStaticFieldNode(token_pos(), field, rhs);
638 }
639 }
640
641 // No field found in library. Look for a setter function.
642 const String& setter_name = String::Handle(Field::SetterName(field_name_));
643 obj = library.ResolveName(setter_name);
644 if (obj.IsFunction()) {
645 const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw());
646 ASSERT(setter.is_static() && setter.IsSetterFunction());
647 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
648 }
649
650 // No writeable field and no setter found in the library. Return a
651 // non-existing setter that will throw an NSM error.
652 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
653 }
654
573 const Function& setter = 655 const Function& setter =
574 Function::Handle(cls().LookupSetterFunction(field_name())); 656 Function::ZoneHandle(cls().LookupSetterFunction(field_name_));
575 if (!setter.IsNull() && setter.IsStaticFunction()) { 657 if (!setter.IsNull() && setter.IsStaticFunction()) {
576 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); 658 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
577 } 659 }
578 // Could not find a static setter. Look for a field. 660 // Could not find a static setter. Look for a field.
579 // Access to a lazily initialized static field that has not yet been 661 // Access to a lazily initialized static field that has not yet been
580 // initialized is compiled to a static implicit getter. 662 // initialized is compiled to a static implicit getter.
581 // A setter may not exist for such a field. 663 // A setter may not exist for such a field.
582 const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name())); 664 const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name_));
583 if (!field.IsNull()) { 665 if (!field.IsNull()) {
584 if (field.is_final()) { 666 if (field.is_final()) {
585 // Attempting to assign to a final variable will cause a NoSuchMethodError 667 // Attempting to assign to a final variable will cause a NoSuchMethodError
586 // to be thrown. Change static getter to non-existent static setter in 668 // to be thrown. Change static getter to non-existent static setter in
587 // order to trigger the throw at runtime. 669 // order to trigger the throw at runtime.
588 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); 670 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
589 } 671 }
590 #if defined(DEBUG) 672 #if defined(DEBUG)
591 const String& getter_name = String::Handle(Field::GetterName(field_name())); 673 const String& getter_name = String::Handle(Field::GetterName(field_name_));
592 const Function& getter = 674 const Function& getter =
593 Function::Handle(cls().LookupStaticFunction(getter_name)); 675 Function::Handle(cls().LookupStaticFunction(getter_name));
594 ASSERT(!getter.IsNull() && 676 ASSERT(!getter.IsNull() &&
595 (getter.kind() == RawFunction::kImplicitStaticFinalGetter)); 677 (getter.kind() == RawFunction::kImplicitStaticFinalGetter));
596 #endif 678 #endif
597 if (Isolate::Current()->TypeChecksEnabled()) { 679 if (Isolate::Current()->TypeChecksEnabled()) {
598 rhs = new AssignableNode( 680 rhs = new AssignableNode(
599 field.token_pos(), 681 field.token_pos(),
600 rhs, 682 rhs,
601 AbstractType::ZoneHandle(field.type()), 683 AbstractType::ZoneHandle(field.type()),
602 String::ZoneHandle(field.name())); 684 String::ZoneHandle(field.name()));
603 } 685 }
604 return new StoreStaticFieldNode(token_pos(), field, rhs); 686 return new StoreStaticFieldNode(token_pos(), field, rhs);
605 } 687 }
606 // Didn't find a static setter or a static field. Make a call to 688 // Didn't find a static setter or a static field. Make a call to
607 // the non-existent setter to trigger a NoSuchMethodError at runtime. 689 // the non-existent setter to trigger a NoSuchMethodError at runtime.
608 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); 690 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
609 } 691 }
610 692
611 693
612 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { 694 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) {
613 // Return this node if it represents a 'throw NoSuchMethodError' indicating 695 // Return this node if it represents a 'throw NoSuchMethodError' indicating
614 // that a getter was not found, otherwise return null. 696 // that a getter was not found, otherwise return null.
615 const Class& cls = Class::Handle(function().Owner()); 697 const Class& cls = Class::Handle(function().Owner());
616 const String& cls_name = String::Handle(cls.Name()); 698 const String& cls_name = String::Handle(cls.Name());
617 const String& func_name = String::Handle(function().name()); 699 const String& func_name = String::Handle(function().name());
618 if (cls_name.Equals(Symbols::NoSuchMethodError()) && 700 if (cls_name.Equals(Symbols::NoSuchMethodError()) &&
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 if (result.IsError() || result.IsNull()) { 736 if (result.IsError() || result.IsNull()) {
655 // TODO(turnidge): We could get better error messages by returning 737 // TODO(turnidge): We could get better error messages by returning
656 // the Error object directly to the parser. This will involve 738 // the Error object directly to the parser. This will involve
657 // replumbing all of the EvalConstExpr methods. 739 // replumbing all of the EvalConstExpr methods.
658 return NULL; 740 return NULL;
659 } 741 }
660 return &Instance::ZoneHandle(Instance::Cast(result).raw()); 742 return &Instance::ZoneHandle(Instance::Cast(result).raw());
661 } 743 }
662 744
663 } // namespace dart 745 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/ast_transformer.cc » ('j') | runtime/vm/ast_transformer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698