OLD | NEW |
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 Loading... |
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 |
OLD | NEW |