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

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

Issue 10849004: Fix super getter/setter (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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/ast.h ('k') | runtime/vm/flow_graph_builder.cc » ('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) 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 11
11 12
12 namespace dart { 13 namespace dart {
13 14
14 #define DEFINE_VISIT_FUNCTION(type, name) \ 15 #define DEFINE_VISIT_FUNCTION(type, name) \
15 void type::Visit(AstNodeVisitor* visitor) { \ 16 void type::Visit(AstNodeVisitor* visitor) { \
16 visitor->Visit##type(this); \ 17 visitor->Visit##type(this); \
17 } 18 }
18 NODE_LIST(DEFINE_VISIT_FUNCTION) 19 NODE_LIST(DEFINE_VISIT_FUNCTION)
19 #undef DEFINE_VISIT_FUNCTION 20 #undef DEFINE_VISIT_FUNCTION
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs); 314 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs);
314 } 315 }
315 316
316 317
317 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { 318 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) {
318 return new StoreIndexedNode(token_pos(), array(), index_expr(), rhs); 319 return new StoreIndexedNode(token_pos(), array(), index_expr(), rhs);
319 } 320 }
320 321
321 322
322 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { 323 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) {
323 // If no setter exist, set the field directly.
324 const String& setter_name = String::Handle(Field::SetterName(field_name())); 324 const String& setter_name = String::Handle(Field::SetterName(field_name()));
325 const Function& setter = 325
326 Function::ZoneHandle(cls().LookupStaticFunction(setter_name)); 326 if (is_super_getter_) {
327 if (setter.IsNull()) { 327 // Resolve the (dynamic) setter method.
328 const Field& field = Field::ZoneHandle( 328 ASSERT(receiver() != NULL);
329 cls().LookupStaticField(field_name())); 329 const Function& super_setter = Function::ZoneHandle(
330 if (field.IsNull()) { 330 Resolver::ResolveDynamicAnyArgs(cls(), setter_name));
331 // A static getter is declared, but no setter and no field. 331 if (!super_setter.IsNull()) {
332 if (receiver() != NULL) { 332 return new StaticSetterNode(token_pos(),
333 return new InstanceSetterNode(token_pos(), 333 receiver(),
334 receiver(), 334 cls(),
335 field_name(), 335 field_name(),
336 rhs); 336 rhs);
337 }
338 return NULL;
339 } 337 }
338 // If setter is found in the superclass, do not turn this into an
339 // instance setter resolved at runtime, since a super getter/setter
340 // explicitly refers to the static superclass of the enclosing function.
341 return NULL;
342 } else {
343 const Function& setter =
344 Function::ZoneHandle(cls().LookupStaticFunction(setter_name));
345 if (!setter.IsNull()) {
346 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs);
347 }
348 // Could not find a static setter. Look for a field.
340 // Access to a lazily initialized static field that has not yet been 349 // Access to a lazily initialized static field that has not yet been
341 // initialized is compiled to a static implicit getter. 350 // initialized is compiled to a static implicit getter.
342 // A setter may not exist for such a field. 351 // A setter may not exist for such a field.
352 const Field& field =
353 Field::ZoneHandle(cls().LookupStaticField(field_name()));
354 if (!field.IsNull()) {
343 #if defined(DEBUG) 355 #if defined(DEBUG)
344 const String& getter_name = String::Handle(Field::GetterName(field_name())); 356 const String& getter_name =
345 const Function& getter = 357 String::Handle(Field::GetterName(field_name()));
346 Function::ZoneHandle(cls().LookupStaticFunction(getter_name)); 358 const Function& getter =
347 ASSERT(!getter.IsNull() && 359 Function::ZoneHandle(cls().LookupStaticFunction(getter_name));
348 (getter.kind() == RawFunction::kConstImplicitGetter)); 360 ASSERT(!getter.IsNull() &&
361 (getter.kind() == RawFunction::kConstImplicitGetter));
349 #endif 362 #endif
350 return new StoreStaticFieldNode(token_pos(), field, rhs); 363 return new StoreStaticFieldNode(token_pos(), field, rhs);
351 } else { 364 }
352 return new StaticSetterNode(token_pos(), cls(), field_name(), rhs); 365 // Didn't find a static setter or a static field.
366 // If this static getter is in an instance function where
367 // a receiver is available, we turn this static getter
368 // into an instance setter (and will get an error at runtime if an
369 // instance setter cannot be found either).
370 if (receiver() != NULL) {
371 return new InstanceSetterNode(token_pos(),
372 receiver(),
373 field_name(),
374 rhs);
375 }
376 return NULL;
353 } 377 }
354 } 378 }
355 379
356 380
357 const Instance* StaticGetterNode::EvalConstExpr() const { 381 const Instance* StaticGetterNode::EvalConstExpr() const {
358 const String& getter_name = 382 const String& getter_name =
359 String::Handle(Field::GetterName(this->field_name())); 383 String::Handle(Field::GetterName(this->field_name()));
360 const Function& getter_func = 384 const Function& getter_func =
361 Function::Handle(this->cls().LookupStaticFunction(getter_name)); 385 Function::Handle(this->cls().LookupStaticFunction(getter_name));
362 if (getter_func.IsNull() || !getter_func.is_const()) { 386 if (getter_func.IsNull() || !getter_func.is_const()) {
363 return NULL; 387 return NULL;
364 } 388 }
365 GrowableArray<const Object*> arguments; 389 GrowableArray<const Object*> arguments;
366 const Array& kNoArgumentNames = Array::Handle(); 390 const Array& kNoArgumentNames = Array::Handle();
367 const Object& result = 391 const Object& result =
368 Object::Handle(DartEntry::InvokeStatic(getter_func, 392 Object::Handle(DartEntry::InvokeStatic(getter_func,
369 arguments, 393 arguments,
370 kNoArgumentNames)); 394 kNoArgumentNames));
371 if (result.IsError() || result.IsNull()) { 395 if (result.IsError() || result.IsNull()) {
372 // TODO(turnidge): We could get better error messages by returning 396 // TODO(turnidge): We could get better error messages by returning
373 // the Error object directly to the parser. This will involve 397 // the Error object directly to the parser. This will involve
374 // replumbing all of the EvalConstExpr methods. 398 // replumbing all of the EvalConstExpr methods.
375 return NULL; 399 return NULL;
376 } 400 }
377 return &Instance::ZoneHandle(Instance::Cast(result).raw()); 401 return &Instance::ZoneHandle(Instance::Cast(result).raw());
378 } 402 }
379 403
380 } // namespace dart 404 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698