| 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 #include "vm/resolver.h" |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 | 286 |
| 287 const Instance* ClosureNode::EvalConstExpr() const { | 287 const Instance* ClosureNode::EvalConstExpr() const { |
| 288 if (function().IsImplicitStaticClosureFunction()) { | 288 if (function().IsImplicitStaticClosureFunction()) { |
| 289 // Return a value that represents an instance. Only the type is relevant. | 289 // Return a value that represents an instance. Only the type is relevant. |
| 290 return &Instance::Handle(); | 290 return &Instance::Handle(); |
| 291 } | 291 } |
| 292 return NULL; | 292 return NULL; |
| 293 } | 293 } |
| 294 | 294 |
| 295 | 295 |
| 296 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { |
| 297 if (scope() == NULL) { |
| 298 // This is an implicit closure node created because a static getter was not |
| 299 // found. Change the getter into a setter. If it does not exist, |
| 300 // noSuchMethod will be called. |
| 301 return new StaticSetterNode(token_pos(), |
| 302 receiver(), |
| 303 Class::ZoneHandle(function().Owner()), |
| 304 String::ZoneHandle(function().name()), |
| 305 rhs); |
| 306 } |
| 307 return NULL; |
| 308 } |
| 309 |
| 310 |
| 296 const char* UnaryOpNode::Name() const { | 311 const char* UnaryOpNode::Name() const { |
| 297 return Token::Str(kind_); | 312 return Token::Str(kind_); |
| 298 } | 313 } |
| 299 | 314 |
| 300 | 315 |
| 301 const char* JumpNode::Name() const { | 316 const char* JumpNode::Name() const { |
| 302 return Token::Str(kind_); | 317 return Token::Str(kind_); |
| 303 } | 318 } |
| 304 | 319 |
| 305 | 320 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { | 353 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { |
| 339 return new StoreIndexedNode(token_pos(), array(), index_expr(), | 354 return new StoreIndexedNode(token_pos(), array(), index_expr(), |
| 340 rhs, super_class()); | 355 rhs, super_class()); |
| 341 } | 356 } |
| 342 | 357 |
| 343 | 358 |
| 344 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { | 359 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { |
| 345 const String& setter_name = String::Handle(Field::SetterName(field_name())); | 360 const String& setter_name = String::Handle(Field::SetterName(field_name())); |
| 346 | 361 |
| 347 if (is_super_getter_) { | 362 if (is_super_getter_) { |
| 348 // Resolve the (dynamic) setter method. | |
| 349 ASSERT(receiver() != NULL); | 363 ASSERT(receiver() != NULL); |
| 350 const Function& super_setter = Function::ZoneHandle( | 364 // If the static setter is not found in the superclass, noSuchMethod will be |
| 351 Resolver::ResolveDynamicAnyArgs(cls(), setter_name)); | 365 // called at runtime. |
| 352 if (!super_setter.IsNull()) { | 366 return new StaticSetterNode(token_pos(), |
| 353 return new StaticSetterNode(token_pos(), | 367 receiver(), |
| 354 receiver(), | 368 cls(), |
| 355 cls(), | 369 field_name(), |
| 356 field_name(), | 370 rhs); |
| 357 rhs); | 371 } |
| 358 } | 372 const Function& setter = |
| 359 // If setter is found in the superclass, do not turn this into an | 373 Function::ZoneHandle(cls().LookupStaticFunction(setter_name)); |
| 360 // instance setter resolved at runtime, since a super getter/setter | 374 if (!setter.IsNull()) { |
| 361 // explicitly refers to the static superclass of the enclosing function. | 375 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| 362 return NULL; | 376 } |
| 363 } else { | 377 // Could not find a static setter. Look for a field. |
| 364 const Function& setter = | 378 // Access to a lazily initialized static field that has not yet been |
| 365 Function::ZoneHandle(cls().LookupStaticFunction(setter_name)); | 379 // initialized is compiled to a static implicit getter. |
| 366 if (!setter.IsNull()) { | 380 // A setter may not exist for such a field. |
| 381 const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name())); |
| 382 if (!field.IsNull()) { |
| 383 if (field.is_final()) { |
| 384 // Attempting to assign to a final variable will cause a NoSuchMethodError |
| 385 // to be thrown. Change static getter to non-existent static setter in |
| 386 // order to trigger the throw at runtime. |
| 367 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); | 387 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| 368 } | 388 } |
| 369 // Could not find a static setter. Look for a field. | |
| 370 // Access to a lazily initialized static field that has not yet been | |
| 371 // initialized is compiled to a static implicit getter. | |
| 372 // A setter may not exist for such a field. | |
| 373 const Field& field = | |
| 374 Field::ZoneHandle(cls().LookupStaticField(field_name())); | |
| 375 if (!field.IsNull()) { | |
| 376 if (field.is_final()) { | |
| 377 return NULL; | |
| 378 } | |
| 379 #if defined(DEBUG) | 389 #if defined(DEBUG) |
| 380 const String& getter_name = | 390 const String& getter_name = String::Handle(Field::GetterName(field_name())); |
| 381 String::Handle(Field::GetterName(field_name())); | 391 const Function& getter = |
| 382 const Function& getter = | 392 Function::Handle(cls().LookupStaticFunction(getter_name)); |
| 383 Function::ZoneHandle(cls().LookupStaticFunction(getter_name)); | 393 ASSERT(!getter.IsNull() && |
| 384 ASSERT(!getter.IsNull() && | 394 (getter.kind() == RawFunction::kConstImplicitGetter)); |
| 385 (getter.kind() == RawFunction::kConstImplicitGetter)); | |
| 386 #endif | 395 #endif |
| 387 return new StoreStaticFieldNode(token_pos(), field, rhs); | 396 return new StoreStaticFieldNode(token_pos(), field, rhs); |
| 388 } | |
| 389 // Didn't find a static setter or a static field. | |
| 390 // If this static getter is in an instance function where | |
| 391 // a receiver is available, we turn this static getter | |
| 392 // into an instance setter (and will get an error at runtime if an | |
| 393 // instance setter cannot be found either). | |
| 394 if (receiver() != NULL) { | |
| 395 return new InstanceSetterNode(token_pos(), | |
| 396 receiver(), | |
| 397 field_name(), | |
| 398 rhs); | |
| 399 } | |
| 400 return NULL; | |
| 401 } | 397 } |
| 398 // Didn't find a static setter or a static field. |
| 399 // If this static getter is in an instance function where |
| 400 // a receiver is available, we turn this static getter |
| 401 // into an instance setter (and will get an error at runtime if an |
| 402 // instance setter cannot be found either). |
| 403 if (receiver() != NULL) { |
| 404 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs); |
| 405 } |
| 406 return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| 402 } | 407 } |
| 403 | 408 |
| 404 | 409 |
| 405 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { | 410 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { |
| 406 // Return this node if it represents a 'throw NoSuchMethodError' indicating | 411 // Return this node if it represents a 'throw NoSuchMethodError' indicating |
| 407 // that a getter was not found, otherwise return null. | 412 // that a getter was not found, otherwise return null. |
| 408 const Class& cls = Class::Handle(function().Owner()); | 413 const Class& cls = Class::Handle(function().Owner()); |
| 409 const String& cls_name = String::Handle(cls.Name()); | 414 const String& cls_name = String::Handle(cls.Name()); |
| 410 const String& func_name = String::Handle(function().name()); | 415 const String& func_name = String::Handle(function().name()); |
| 411 const String& error_cls_name = String::Handle(Symbols::NoSuchMethodError()); | 416 const String& error_cls_name = String::Handle(Symbols::NoSuchMethodError()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 431 if (result.IsError() || result.IsNull()) { | 436 if (result.IsError() || result.IsNull()) { |
| 432 // TODO(turnidge): We could get better error messages by returning | 437 // TODO(turnidge): We could get better error messages by returning |
| 433 // the Error object directly to the parser. This will involve | 438 // the Error object directly to the parser. This will involve |
| 434 // replumbing all of the EvalConstExpr methods. | 439 // replumbing all of the EvalConstExpr methods. |
| 435 return NULL; | 440 return NULL; |
| 436 } | 441 } |
| 437 return &Instance::ZoneHandle(Instance::Cast(result).raw()); | 442 return &Instance::ZoneHandle(Instance::Cast(result).raw()); |
| 438 } | 443 } |
| 439 | 444 |
| 440 } // namespace dart | 445 } // namespace dart |
| OLD | NEW |