Index: runtime/vm/ast.cc |
=================================================================== |
--- runtime/vm/ast.cc (revision 10409) |
+++ runtime/vm/ast.cc (working copy) |
@@ -7,6 +7,7 @@ |
#include "vm/dart_entry.h" |
#include "vm/isolate.h" |
#include "vm/object_store.h" |
+#include "vm/resolver.h" |
namespace dart { |
@@ -320,36 +321,59 @@ |
AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { |
- // If no setter exist, set the field directly. |
const String& setter_name = String::Handle(Field::SetterName(field_name())); |
- const Function& setter = |
- Function::ZoneHandle(cls().LookupStaticFunction(setter_name)); |
- if (setter.IsNull()) { |
- const Field& field = Field::ZoneHandle( |
- cls().LookupStaticField(field_name())); |
- if (field.IsNull()) { |
- // A static getter is declared, but no setter and no field. |
- if (receiver() != NULL) { |
- return new InstanceSetterNode(token_pos(), |
- receiver(), |
- field_name(), |
- rhs); |
- } |
- return NULL; |
+ |
+ if (is_super_getter_) { |
+ // Resolve the (dynamic) setter method. |
+ ASSERT(receiver() != NULL); |
+ const Function& super_setter = Function::ZoneHandle( |
+ Resolver::ResolveDynamicAnyArgs(cls(), setter_name)); |
+ if (!super_setter.IsNull()) { |
+ return new StaticSetterNode(token_pos(), |
+ receiver(), |
+ cls(), |
+ field_name(), |
+ rhs); |
} |
+ // If setter is found in the superclass, do not turn this into an |
+ // instance setter resolved at runtime, since a super getter/setter |
+ // explicitly refers to the static superclass of the enclosing function. |
+ return NULL; |
+ } else { |
+ const Function& setter = |
+ Function::ZoneHandle(cls().LookupStaticFunction(setter_name)); |
+ if (!setter.IsNull()) { |
+ return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
+ } |
+ // Could not find a static setter. Look for a field. |
// Access to a lazily initialized static field that has not yet been |
// initialized is compiled to a static implicit getter. |
// A setter may not exist for such a field. |
+ const Field& field = |
+ Field::ZoneHandle(cls().LookupStaticField(field_name())); |
+ if (!field.IsNull()) { |
#if defined(DEBUG) |
- const String& getter_name = String::Handle(Field::GetterName(field_name())); |
- const Function& getter = |
- Function::ZoneHandle(cls().LookupStaticFunction(getter_name)); |
- ASSERT(!getter.IsNull() && |
- (getter.kind() == RawFunction::kConstImplicitGetter)); |
+ const String& getter_name = |
+ String::Handle(Field::GetterName(field_name())); |
+ const Function& getter = |
+ Function::ZoneHandle(cls().LookupStaticFunction(getter_name)); |
+ ASSERT(!getter.IsNull() && |
+ (getter.kind() == RawFunction::kConstImplicitGetter)); |
#endif |
- return new StoreStaticFieldNode(token_pos(), field, rhs); |
- } else { |
- return new StaticSetterNode(token_pos(), cls(), field_name(), rhs); |
+ return new StoreStaticFieldNode(token_pos(), field, rhs); |
+ } |
+ // Didn't find a static setter or a static field. |
+ // If this static getter is in an instance function where |
+ // a receiver is available, we turn this static getter |
+ // into an instance setter (and will get an error at runtime if an |
+ // instance setter cannot be found either). |
+ if (receiver() != NULL) { |
+ return new InstanceSetterNode(token_pos(), |
+ receiver(), |
+ field_name(), |
+ rhs); |
+ } |
+ return NULL; |
} |
} |