| 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/log.h" | 9 #include "vm/log.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 11 #include "vm/resolver.h" | 11 #include "vm/resolver.h" |
| 12 | 12 |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 #define DEFINE_VISIT_FUNCTION(BaseName) \ | 16 #define DEFINE_VISIT_FUNCTION(BaseName) \ |
| 17 void BaseName##Node::Visit(AstNodeVisitor* visitor) { \ | 17 void BaseName##Node::Visit(AstNodeVisitor* visitor) { \ |
| 18 visitor->Visit##BaseName##Node(this); \ | 18 visitor->Visit##BaseName##Node(this); \ |
| 19 } | 19 } |
| 20 | 20 |
| 21 FOR_EACH_NODE(DEFINE_VISIT_FUNCTION) | 21 FOR_EACH_NODE(DEFINE_VISIT_FUNCTION) |
| 22 #undef DEFINE_VISIT_FUNCTION | 22 #undef DEFINE_VISIT_FUNCTION |
| 23 | 23 |
| 24 | 24 |
| 25 #define DEFINE_NAME_FUNCTION(BaseName) \ | 25 #define DEFINE_NAME_FUNCTION(BaseName) \ |
| 26 const char* BaseName##Node::Name() const { \ | 26 const char* BaseName##Node::Name() const { return #BaseName; } |
| 27 return #BaseName; \ | |
| 28 } | |
| 29 | 27 |
| 30 FOR_EACH_NODE(DEFINE_NAME_FUNCTION) | 28 FOR_EACH_NODE(DEFINE_NAME_FUNCTION) |
| 31 #undef DEFINE_NAME_FUNCTION | 29 #undef DEFINE_NAME_FUNCTION |
| 32 | 30 |
| 33 | 31 |
| 34 const Field* AstNode::MayCloneField(const Field& value) { | 32 const Field* AstNode::MayCloneField(const Field& value) { |
| 35 if (Compiler::IsBackgroundCompilation() || | 33 if (Compiler::IsBackgroundCompilation() || |
| 36 FLAG_force_clone_compiler_objects) { | 34 FLAG_force_clone_compiler_objects) { |
| 37 return &Field::ZoneHandle(value.CloneFromOriginal()); | 35 return &Field::ZoneHandle(value.CloneFromOriginal()); |
| 38 } else { | 36 } else { |
| 39 ASSERT(value.IsZoneHandle()); | 37 ASSERT(value.IsZoneHandle()); |
| 40 return &value; | 38 return &value; |
| 41 } | 39 } |
| 42 } | 40 } |
| 43 | 41 |
| 44 | 42 |
| 45 // A visitor class to collect all the nodes (including children) into an | 43 // A visitor class to collect all the nodes (including children) into an |
| 46 // array. | 44 // array. |
| 47 class AstNodeCollector : public AstNodeVisitor { | 45 class AstNodeCollector : public AstNodeVisitor { |
| 48 public: | 46 public: |
| 49 explicit AstNodeCollector(GrowableArray<AstNode*>* nodes) | 47 explicit AstNodeCollector(GrowableArray<AstNode*>* nodes) : nodes_(nodes) {} |
| 50 : nodes_(nodes) { } | |
| 51 | 48 |
| 52 #define DEFINE_VISITOR_FUNCTION(BaseName) \ | 49 #define DEFINE_VISITOR_FUNCTION(BaseName) \ |
| 53 virtual void Visit##BaseName##Node(BaseName##Node* node) { \ | 50 virtual void Visit##BaseName##Node(BaseName##Node* node) { \ |
| 54 nodes_->Add(node); \ | 51 nodes_->Add(node); \ |
| 55 node->VisitChildren(this); \ | 52 node->VisitChildren(this); \ |
| 56 } | 53 } |
| 57 | 54 |
| 58 FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION) | 55 FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION) |
| 59 #undef DEFINE_VISITOR_FUNCTION | 56 #undef DEFINE_VISITOR_FUNCTION |
| 60 | 57 |
| 61 private: | 58 private: |
| 62 GrowableArray<AstNode*>* nodes_; | 59 GrowableArray<AstNode*>* nodes_; |
| 63 DISALLOW_COPY_AND_ASSIGN(AstNodeCollector); | 60 DISALLOW_COPY_AND_ASSIGN(AstNodeCollector); |
| 64 }; | 61 }; |
| 65 | 62 |
| 66 | 63 |
| 67 void SequenceNode::CollectAllNodes(GrowableArray<AstNode*>* nodes) { | 64 void SequenceNode::CollectAllNodes(GrowableArray<AstNode*>* nodes) { |
| 68 AstNodeCollector node_collector(nodes); | 65 AstNodeCollector node_collector(nodes); |
| 69 this->Visit(&node_collector); | 66 this->Visit(&node_collector); |
| 70 } | 67 } |
| 71 | 68 |
| 72 | 69 |
| 73 void SequenceNode::VisitChildren(AstNodeVisitor* visitor) const { | 70 void SequenceNode::VisitChildren(AstNodeVisitor* visitor) const { |
| 74 for (intptr_t i = 0; i < this->length(); i++) { | 71 for (intptr_t i = 0; i < this->length(); i++) { |
| 75 NodeAt(i)->Visit(visitor); | 72 NodeAt(i)->Visit(visitor); |
| 76 } | 73 } |
| 77 } | 74 } |
| 78 | 75 |
| 79 | 76 |
| 80 void SequenceNode::Add(AstNode* node) { | 77 void SequenceNode::Add(AstNode* node) { |
| 81 if (node->IsReturnNode()) { | 78 if (node->IsReturnNode()) { |
| 82 node->AsReturnNode()->set_scope(scope()); | 79 node->AsReturnNode()->set_scope(scope()); |
| 83 } | 80 } |
| 84 nodes_.Add(node); | 81 nodes_.Add(node); |
| 85 } | 82 } |
| 86 | 83 |
| 87 | 84 |
| 88 void PrimaryNode::VisitChildren(AstNodeVisitor* visitor) const { | 85 void PrimaryNode::VisitChildren(AstNodeVisitor* visitor) const {} |
| 89 } | |
| 90 | 86 |
| 91 | 87 |
| 92 void ArgumentListNode::VisitChildren(AstNodeVisitor* visitor) const { | 88 void ArgumentListNode::VisitChildren(AstNodeVisitor* visitor) const { |
| 93 for (intptr_t i = 0; i < this->length(); i++) { | 89 for (intptr_t i = 0; i < this->length(); i++) { |
| 94 NodeAt(i)->Visit(visitor); | 90 NodeAt(i)->Visit(visitor); |
| 95 } | 91 } |
| 96 } | 92 } |
| 97 | 93 |
| 98 | 94 |
| 99 LetNode::LetNode(TokenPosition token_pos) | 95 LetNode::LetNode(TokenPosition token_pos) |
| 100 : AstNode(token_pos), | 96 : AstNode(token_pos), vars_(1), initializers_(1), nodes_(1) {} |
| 101 vars_(1), | |
| 102 initializers_(1), | |
| 103 nodes_(1) { } | |
| 104 | 97 |
| 105 | 98 |
| 106 LocalVariable* LetNode::AddInitializer(AstNode* node) { | 99 LocalVariable* LetNode::AddInitializer(AstNode* node) { |
| 107 Thread* thread = Thread::Current(); | 100 Thread* thread = Thread::Current(); |
| 108 Zone* zone = thread->zone(); | 101 Zone* zone = thread->zone(); |
| 109 initializers_.Add(node); | 102 initializers_.Add(node); |
| 110 char name[64]; | 103 char name[64]; |
| 111 OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", | 104 OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(), |
| 112 token_pos().ToCString(), vars_.length()); | 105 vars_.length()); |
| 113 LocalVariable* temp_var = | 106 LocalVariable* temp_var = |
| 114 new LocalVariable(TokenPosition::kNoSource, | 107 new LocalVariable(TokenPosition::kNoSource, token_pos(), |
| 115 token_pos(), | |
| 116 String::ZoneHandle(zone, Symbols::New(thread, name)), | 108 String::ZoneHandle(zone, Symbols::New(thread, name)), |
| 117 Object::dynamic_type()); | 109 Object::dynamic_type()); |
| 118 vars_.Add(temp_var); | 110 vars_.Add(temp_var); |
| 119 return temp_var; | 111 return temp_var; |
| 120 } | 112 } |
| 121 | 113 |
| 122 | 114 |
| 123 void LetNode::VisitChildren(AstNodeVisitor* visitor) const { | 115 void LetNode::VisitChildren(AstNodeVisitor* visitor) const { |
| 124 for (intptr_t i = 0; i < num_temps(); ++i) { | 116 for (intptr_t i = 0; i < num_temps(); ++i) { |
| 125 initializers_[i]->Visit(visitor); | 117 initializers_[i]->Visit(visitor); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 return NULL; | 218 return NULL; |
| 227 } | 219 } |
| 228 | 220 |
| 229 | 221 |
| 230 const char* TypeNode::TypeName() const { | 222 const char* TypeNode::TypeName() const { |
| 231 return String::Handle(type().UserVisibleName()).ToCString(); | 223 return String::Handle(type().UserVisibleName()).ToCString(); |
| 232 } | 224 } |
| 233 | 225 |
| 234 | 226 |
| 235 bool ComparisonNode::IsKindValid() const { | 227 bool ComparisonNode::IsKindValid() const { |
| 236 return Token::IsRelationalOperator(kind_) | 228 return Token::IsRelationalOperator(kind_) || |
| 237 || Token::IsEqualityOperator(kind_) | 229 Token::IsEqualityOperator(kind_) || Token::IsTypeTestOperator(kind_) || |
| 238 || Token::IsTypeTestOperator(kind_) | 230 Token::IsTypeCastOperator(kind_); |
| 239 || Token::IsTypeCastOperator(kind_); | |
| 240 } | 231 } |
| 241 | 232 |
| 242 | 233 |
| 243 const char* ComparisonNode::TokenName() const { | 234 const char* ComparisonNode::TokenName() const { |
| 244 return (kind_ == Token::kAS) ? "as" : Token::Str(kind_); | 235 return (kind_ == Token::kAS) ? "as" : Token::Str(kind_); |
| 245 } | 236 } |
| 246 | 237 |
| 247 | 238 |
| 248 bool ComparisonNode::IsPotentiallyConst() const { | 239 bool ComparisonNode::IsPotentiallyConst() const { |
| 249 switch (kind_) { | 240 switch (kind_) { |
| 250 case Token::kLT: | 241 case Token::kLT: |
| 251 case Token::kGT: | 242 case Token::kGT: |
| 252 case Token::kLTE: | 243 case Token::kLTE: |
| 253 case Token::kGTE: | 244 case Token::kGTE: |
| 254 case Token::kEQ: | 245 case Token::kEQ: |
| 255 case Token::kNE: | 246 case Token::kNE: |
| 256 case Token::kEQ_STRICT: | 247 case Token::kEQ_STRICT: |
| 257 case Token::kNE_STRICT: | 248 case Token::kNE_STRICT: |
| 258 return this->left()->IsPotentiallyConst() && | 249 return this->left()->IsPotentiallyConst() && |
| 259 this->right()->IsPotentiallyConst(); | 250 this->right()->IsPotentiallyConst(); |
| 260 default: | 251 default: |
| 261 return false; | 252 return false; |
| 262 } | 253 } |
| 263 } | 254 } |
| 264 | 255 |
| 265 | 256 |
| 266 const Instance* ComparisonNode::EvalConstExpr() const { | 257 const Instance* ComparisonNode::EvalConstExpr() const { |
| 267 const Instance* left_val = this->left()->EvalConstExpr(); | 258 const Instance* left_val = this->left()->EvalConstExpr(); |
| 268 if (left_val == NULL) { | 259 if (left_val == NULL) { |
| 269 return NULL; | 260 return NULL; |
| 270 } | 261 } |
| 271 const Instance* right_val = this->right()->EvalConstExpr(); | 262 const Instance* right_val = this->right()->EvalConstExpr(); |
| 272 if (right_val == NULL) { | 263 if (right_val == NULL) { |
| 273 return NULL; | 264 return NULL; |
| 274 } | 265 } |
| 275 switch (kind_) { | 266 switch (kind_) { |
| 276 case Token::kLT: | 267 case Token::kLT: |
| 277 case Token::kGT: | 268 case Token::kGT: |
| 278 case Token::kLTE: | 269 case Token::kLTE: |
| 279 case Token::kGTE: | 270 case Token::kGTE: |
| 280 if ((left_val->IsNumber() || left_val->IsNull()) && | 271 if ((left_val->IsNumber() || left_val->IsNull()) && |
| 281 (right_val->IsNumber() || right_val->IsNull())) { | 272 (right_val->IsNumber() || right_val->IsNull())) { |
| 282 return &Bool::False(); | 273 return &Bool::False(); |
| 283 } | 274 } |
| 284 return NULL; | 275 return NULL; |
| 285 case Token::kEQ: | 276 case Token::kEQ: |
| 286 case Token::kNE: | 277 case Token::kNE: |
| 287 // The comparison is a compile time const if both operands are either a | 278 // The comparison is a compile time const if both operands are either a |
| 288 // number, string, or boolean value (but not necessarily the same type). | 279 // number, string, or boolean value (but not necessarily the same type). |
| 289 if ((left_val->IsNumber() || | 280 if ((left_val->IsNumber() || left_val->IsString() || left_val->IsBool() || |
| 290 left_val->IsString() || | 281 left_val->IsNull()) && |
| 291 left_val->IsBool() || | 282 (right_val->IsNumber() || right_val->IsString() || |
| 292 left_val->IsNull()) && | 283 right_val->IsBool() || right_val->IsNull())) { |
| 293 (right_val->IsNumber() || | |
| 294 right_val->IsString() || | |
| 295 right_val->IsBool() || | |
| 296 right_val->IsNull())) { | |
| 297 return &Bool::False(); | 284 return &Bool::False(); |
| 298 } | 285 } |
| 299 return NULL; | 286 return NULL; |
| 300 case Token::kEQ_STRICT: | 287 case Token::kEQ_STRICT: |
| 301 case Token::kNE_STRICT: | 288 case Token::kNE_STRICT: |
| 302 // identical(a, b) is a compile time const if both operands are | 289 // identical(a, b) is a compile time const if both operands are |
| 303 // compile time constants, regardless of their type. | 290 // compile time constants, regardless of their type. |
| 304 return &Bool::True(); | 291 return &Bool::True(); |
| 305 default: | 292 default: |
| 306 return NULL; | 293 return NULL; |
| 307 } | 294 } |
| 308 return NULL; | 295 return NULL; |
| 309 } | 296 } |
| 310 | 297 |
| 311 | 298 |
| 312 | |
| 313 bool BinaryOpNode::IsKindValid() const { | 299 bool BinaryOpNode::IsKindValid() const { |
| 314 switch (kind_) { | 300 switch (kind_) { |
| 315 case Token::kADD: | 301 case Token::kADD: |
| 316 case Token::kSUB: | 302 case Token::kSUB: |
| 317 case Token::kMUL: | 303 case Token::kMUL: |
| 318 case Token::kDIV: | 304 case Token::kDIV: |
| 319 case Token::kTRUNCDIV: | 305 case Token::kTRUNCDIV: |
| 320 case Token::kMOD: | 306 case Token::kMOD: |
| 321 case Token::kOR: | 307 case Token::kOR: |
| 322 case Token::kAND: | 308 case Token::kAND: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 343 case Token::kOR: | 329 case Token::kOR: |
| 344 case Token::kAND: | 330 case Token::kAND: |
| 345 if (this->left()->IsLiteralNode() && | 331 if (this->left()->IsLiteralNode() && |
| 346 this->left()->AsLiteralNode()->literal().IsNull()) { | 332 this->left()->AsLiteralNode()->literal().IsNull()) { |
| 347 return false; | 333 return false; |
| 348 } | 334 } |
| 349 if (this->right()->IsLiteralNode() && | 335 if (this->right()->IsLiteralNode() && |
| 350 this->right()->AsLiteralNode()->literal().IsNull()) { | 336 this->right()->AsLiteralNode()->literal().IsNull()) { |
| 351 return false; | 337 return false; |
| 352 } | 338 } |
| 353 // Fall-through intentional. | 339 // Fall-through intentional. |
| 354 case Token::kADD: | 340 case Token::kADD: |
| 355 case Token::kSUB: | 341 case Token::kSUB: |
| 356 case Token::kMUL: | 342 case Token::kMUL: |
| 357 case Token::kDIV: | 343 case Token::kDIV: |
| 358 case Token::kMOD: | 344 case Token::kMOD: |
| 359 case Token::kTRUNCDIV: | 345 case Token::kTRUNCDIV: |
| 360 case Token::kBIT_OR: | 346 case Token::kBIT_OR: |
| 361 case Token::kBIT_XOR: | 347 case Token::kBIT_XOR: |
| 362 case Token::kBIT_AND: | 348 case Token::kBIT_AND: |
| 363 case Token::kSHL: | 349 case Token::kSHL: |
| 364 case Token::kSHR: | 350 case Token::kSHR: |
| 365 case Token::kIFNULL: | 351 case Token::kIFNULL: |
| 366 return this->left()->IsPotentiallyConst() && | 352 return this->left()->IsPotentiallyConst() && |
| 367 this->right()->IsPotentiallyConst(); | 353 this->right()->IsPotentiallyConst(); |
| 368 default: | 354 default: |
| 369 UNREACHABLE(); | 355 UNREACHABLE(); |
| 370 return false; | 356 return false; |
| 371 } | 357 } |
| 372 } | 358 } |
| 373 | 359 |
| 374 | 360 |
| 375 const Instance* BinaryOpNode::EvalConstExpr() const { | 361 const Instance* BinaryOpNode::EvalConstExpr() const { |
| 376 const Instance* left_val = this->left()->EvalConstExpr(); | 362 const Instance* left_val = this->left()->EvalConstExpr(); |
| 377 if (left_val == NULL) { | 363 if (left_val == NULL) { |
| 378 return NULL; | 364 return NULL; |
| 379 } | 365 } |
| 380 if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() && | 366 if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() && |
| 381 kind_ != Token::kIFNULL) { | 367 kind_ != Token::kIFNULL) { |
| 382 return NULL; | 368 return NULL; |
| 383 } | 369 } |
| 384 const Instance* right_val = this->right()->EvalConstExpr(); | 370 const Instance* right_val = this->right()->EvalConstExpr(); |
| 385 if (right_val == NULL) { | 371 if (right_val == NULL) { |
| 386 return NULL; | 372 return NULL; |
| 387 } | 373 } |
| 388 switch (kind_) { | 374 switch (kind_) { |
| 389 case Token::kADD: | 375 case Token::kADD: |
| 390 if (left_val->IsString()) { | 376 if (left_val->IsString()) { |
| 391 return right_val->IsString() ? left_val : NULL; | 377 return right_val->IsString() ? left_val : NULL; |
| 392 } | 378 } |
| 393 // Fall-through intentional. | 379 // Fall-through intentional. |
| 394 case Token::kSUB: | 380 case Token::kSUB: |
| 395 case Token::kMUL: | 381 case Token::kMUL: |
| 396 case Token::kDIV: | 382 case Token::kDIV: |
| 397 case Token::kMOD: | 383 case Token::kMOD: |
| 398 case Token::kTRUNCDIV: | 384 case Token::kTRUNCDIV: |
| 399 if (left_val->IsInteger()) { | 385 if (left_val->IsInteger()) { |
| 400 if (right_val->IsInteger()) { | 386 if (right_val->IsInteger()) { |
| 401 return left_val; | 387 return left_val; |
| 402 } else if (right_val->IsNumber()) { | 388 } else if (right_val->IsNumber()) { |
| 403 return right_val; | 389 return right_val; |
| 404 } | 390 } |
| 405 } else if (left_val->IsNumber() && | 391 } else if (left_val->IsNumber() && right_val->IsNumber()) { |
| 406 right_val->IsNumber()) { | |
| 407 return left_val; | 392 return left_val; |
| 408 } | 393 } |
| 409 return NULL; | 394 return NULL; |
| 410 case Token::kBIT_OR: | 395 case Token::kBIT_OR: |
| 411 case Token::kBIT_XOR: | 396 case Token::kBIT_XOR: |
| 412 case Token::kBIT_AND: | 397 case Token::kBIT_AND: |
| 413 case Token::kSHL: | 398 case Token::kSHL: |
| 414 case Token::kSHR: | 399 case Token::kSHR: |
| 415 if (left_val->IsInteger() && | 400 if (left_val->IsInteger() && right_val->IsInteger()) { |
| 416 right_val->IsInteger()) { | |
| 417 return right_val; | 401 return right_val; |
| 418 } | 402 } |
| 419 return NULL; | 403 return NULL; |
| 420 case Token::kOR: | 404 case Token::kOR: |
| 421 case Token::kAND: | 405 case Token::kAND: |
| 422 if (left_val->IsBool() && right_val->IsBool()) { | 406 if (left_val->IsBool() && right_val->IsBool()) { |
| 423 return left_val; | 407 return left_val; |
| 424 } | 408 } |
| 425 return NULL; | 409 return NULL; |
| 426 case Token::kIFNULL: | 410 case Token::kIFNULL: |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 case Token::kBIT_NOT: | 465 case Token::kBIT_NOT: |
| 482 return val->IsInteger() ? val : NULL; | 466 return val->IsInteger() ? val : NULL; |
| 483 default: | 467 default: |
| 484 return NULL; | 468 return NULL; |
| 485 } | 469 } |
| 486 } | 470 } |
| 487 | 471 |
| 488 | 472 |
| 489 bool ConditionalExprNode::IsPotentiallyConst() const { | 473 bool ConditionalExprNode::IsPotentiallyConst() const { |
| 490 return this->condition()->IsPotentiallyConst() && | 474 return this->condition()->IsPotentiallyConst() && |
| 491 this->true_expr()->IsPotentiallyConst() && | 475 this->true_expr()->IsPotentiallyConst() && |
| 492 this->false_expr()->IsPotentiallyConst(); | 476 this->false_expr()->IsPotentiallyConst(); |
| 493 } | 477 } |
| 494 | 478 |
| 495 | 479 |
| 496 const Instance* ConditionalExprNode::EvalConstExpr() const { | 480 const Instance* ConditionalExprNode::EvalConstExpr() const { |
| 497 const Instance* cond = this->condition()->EvalConstExpr(); | 481 const Instance* cond = this->condition()->EvalConstExpr(); |
| 498 if ((cond != NULL) && | 482 if ((cond != NULL) && cond->IsBool() && |
| 499 cond->IsBool() && | |
| 500 (this->true_expr()->EvalConstExpr() != NULL) && | 483 (this->true_expr()->EvalConstExpr() != NULL) && |
| 501 (this->false_expr()->EvalConstExpr() != NULL)) { | 484 (this->false_expr()->EvalConstExpr() != NULL)) { |
| 502 return cond; | 485 return cond; |
| 503 } | 486 } |
| 504 return NULL; | 487 return NULL; |
| 505 } | 488 } |
| 506 | 489 |
| 507 | 490 |
| 508 bool ClosureNode::IsPotentiallyConst() const { | 491 bool ClosureNode::IsPotentiallyConst() const { |
| 509 if (function().IsImplicitStaticClosureFunction()) { | 492 if (function().IsImplicitStaticClosureFunction()) { |
| 510 return true; | 493 return true; |
| 511 } | 494 } |
| 512 return false; | 495 return false; |
| 513 } | 496 } |
| 514 | 497 |
| 515 | 498 |
| 516 const Instance* ClosureNode::EvalConstExpr() const { | 499 const Instance* ClosureNode::EvalConstExpr() const { |
| 517 if (!is_deferred_reference_ && | 500 if (!is_deferred_reference_ && function().IsImplicitStaticClosureFunction()) { |
| 518 function().IsImplicitStaticClosureFunction()) { | |
| 519 // Return a value that represents an instance. Only the type is relevant. | 501 // Return a value that represents an instance. Only the type is relevant. |
| 520 return &Instance::Handle(); | 502 return &Instance::Handle(); |
| 521 } | 503 } |
| 522 return NULL; | 504 return NULL; |
| 523 } | 505 } |
| 524 | 506 |
| 525 | 507 |
| 526 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { | 508 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { |
| 527 if (scope() == NULL) { | 509 if (scope() == NULL) { |
| 528 // This is an implicit closure node created because a static getter was not | 510 // This is an implicit closure node created because a static getter was not |
| 529 // found. Change the getter into a setter. If it does not exist, | 511 // found. Change the getter into a setter. If it does not exist, |
| 530 // noSuchMethod will be called. | 512 // noSuchMethod will be called. |
| 531 return new StaticSetterNode(token_pos(), | 513 return new StaticSetterNode(token_pos(), receiver(), |
| 532 receiver(), | |
| 533 Class::ZoneHandle(function().Owner()), | 514 Class::ZoneHandle(function().Owner()), |
| 534 String::ZoneHandle(function().name()), | 515 String::ZoneHandle(function().name()), rhs); |
| 535 rhs); | |
| 536 } | 516 } |
| 537 return NULL; | 517 return NULL; |
| 538 } | 518 } |
| 539 | 519 |
| 540 | 520 |
| 541 const char* UnaryOpNode::TokenName() const { | 521 const char* UnaryOpNode::TokenName() const { |
| 542 return Token::Str(kind_); | 522 return Token::Str(kind_); |
| 543 } | 523 } |
| 544 | 524 |
| 545 | 525 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 572 } | 552 } |
| 573 return new StoreLocalNode(token_pos(), &local(), rhs); | 553 return new StoreLocalNode(token_pos(), &local(), rhs); |
| 574 } | 554 } |
| 575 | 555 |
| 576 | 556 |
| 577 AstNode* LoadStaticFieldNode::MakeAssignmentNode(AstNode* rhs) { | 557 AstNode* LoadStaticFieldNode::MakeAssignmentNode(AstNode* rhs) { |
| 578 if (field().is_final()) { | 558 if (field().is_final()) { |
| 579 return NULL; | 559 return NULL; |
| 580 } | 560 } |
| 581 if (Isolate::Current()->type_checks()) { | 561 if (Isolate::Current()->type_checks()) { |
| 582 rhs = new AssignableNode( | 562 rhs = new AssignableNode(field().token_pos(), rhs, |
| 583 field().token_pos(), | 563 AbstractType::ZoneHandle(field().type()), |
| 584 rhs, | 564 String::ZoneHandle(field().name())); |
| 585 AbstractType::ZoneHandle(field().type()), | |
| 586 String::ZoneHandle(field().name())); | |
| 587 } | 565 } |
| 588 return new StoreStaticFieldNode( | 566 return new StoreStaticFieldNode(token_pos(), |
| 589 token_pos(), Field::ZoneHandle(field().Original()), rhs); | 567 Field::ZoneHandle(field().Original()), rhs); |
| 590 } | 568 } |
| 591 | 569 |
| 592 | 570 |
| 593 AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) { | 571 AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) { |
| 594 return new InstanceSetterNode(token_pos(), | 572 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs, |
| 595 receiver(), | |
| 596 field_name(), | |
| 597 rhs, | |
| 598 is_conditional()); | 573 is_conditional()); |
| 599 } | 574 } |
| 600 | 575 |
| 601 | 576 |
| 602 bool InstanceGetterNode::IsPotentiallyConst() const { | 577 bool InstanceGetterNode::IsPotentiallyConst() const { |
| 603 return field_name().Equals(Symbols::Length()) && | 578 return field_name().Equals(Symbols::Length()) && !is_conditional() && |
| 604 !is_conditional() && | 579 receiver()->IsPotentiallyConst(); |
| 605 receiver()->IsPotentiallyConst(); | |
| 606 } | 580 } |
| 607 | 581 |
| 608 | 582 |
| 609 const Instance* InstanceGetterNode::EvalConstExpr() const { | 583 const Instance* InstanceGetterNode::EvalConstExpr() const { |
| 610 if (field_name().Equals(Symbols::Length()) && !is_conditional()) { | 584 if (field_name().Equals(Symbols::Length()) && !is_conditional()) { |
| 611 const Instance* receiver_val = receiver()->EvalConstExpr(); | 585 const Instance* receiver_val = receiver()->EvalConstExpr(); |
| 612 if ((receiver_val != NULL) && receiver_val->IsString()) { | 586 if ((receiver_val != NULL) && receiver_val->IsString()) { |
| 613 return &Instance::ZoneHandle(Smi::New(1)); | 587 return &Instance::ZoneHandle(Smi::New(1)); |
| 614 } | 588 } |
| 615 } | 589 } |
| 616 return NULL; | 590 return NULL; |
| 617 } | 591 } |
| 618 | 592 |
| 619 | 593 |
| 620 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { | 594 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { |
| 621 return new StoreIndexedNode(token_pos(), array(), index_expr(), | 595 return new StoreIndexedNode(token_pos(), array(), index_expr(), rhs, |
| 622 rhs, super_class()); | 596 super_class()); |
| 623 } | 597 } |
| 624 | 598 |
| 625 | 599 |
| 626 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { | 600 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { |
| 627 Thread* thread = Thread::Current(); | 601 Thread* thread = Thread::Current(); |
| 628 Zone* zone = thread->zone(); | 602 Zone* zone = thread->zone(); |
| 629 Isolate* isolate = thread->isolate(); | 603 Isolate* isolate = thread->isolate(); |
| 630 if (is_super_getter()) { | 604 if (is_super_getter()) { |
| 631 ASSERT(receiver() != NULL); | 605 ASSERT(receiver() != NULL); |
| 632 const String& setter_name = | 606 const String& setter_name = |
| 633 String::ZoneHandle(zone, Field::LookupSetterSymbol(field_name_)); | 607 String::ZoneHandle(zone, Field::LookupSetterSymbol(field_name_)); |
| 634 Function& setter = Function::ZoneHandle(zone); | 608 Function& setter = Function::ZoneHandle(zone); |
| 635 if (!setter_name.IsNull()) { | 609 if (!setter_name.IsNull()) { |
| 636 setter = Resolver::ResolveDynamicAnyArgs(zone, cls(), setter_name); | 610 setter = Resolver::ResolveDynamicAnyArgs(zone, cls(), setter_name); |
| 637 } | 611 } |
| 638 if (setter.IsNull() || setter.is_abstract()) { | 612 if (setter.IsNull() || setter.is_abstract()) { |
| 639 // No instance setter found in super class chain, | 613 // No instance setter found in super class chain, |
| 640 // noSuchMethod will be called at runtime. | 614 // noSuchMethod will be called at runtime. |
| 641 return new StaticSetterNode(token_pos(), | 615 return new StaticSetterNode(token_pos(), receiver(), cls(), field_name_, |
| 642 receiver(), | |
| 643 cls(), | |
| 644 field_name_, | |
| 645 rhs); | 616 rhs); |
| 646 } | 617 } |
| 647 return new StaticSetterNode(token_pos(), | 618 return new StaticSetterNode(token_pos(), receiver(), field_name_, setter, |
| 648 receiver(), | |
| 649 field_name_, | |
| 650 setter, | |
| 651 rhs); | 619 rhs); |
| 652 } | 620 } |
| 653 | 621 |
| 654 if (owner().IsLibraryPrefix()) { | 622 if (owner().IsLibraryPrefix()) { |
| 655 const LibraryPrefix& prefix = LibraryPrefix::Cast(owner_); | 623 const LibraryPrefix& prefix = LibraryPrefix::Cast(owner_); |
| 656 // The parser has already dealt with the pathological case where a | 624 // The parser has already dealt with the pathological case where a |
| 657 // library imports itself. See Parser::ResolveIdentInPrefixScope() | 625 // library imports itself. See Parser::ResolveIdentInPrefixScope() |
| 658 ASSERT(field_name_.CharAt(0) != Library::kPrivateIdentifierStart); | 626 ASSERT(field_name_.CharAt(0) != Library::kPrivateIdentifierStart); |
| 659 | 627 |
| 660 // If the prefix is not yet loaded, the getter doesn't exist. Return a | 628 // If the prefix is not yet loaded, the getter doesn't exist. Return a |
| 661 // setter that will throw a NSME at runtime. | 629 // setter that will throw a NSME at runtime. |
| 662 if (!prefix.is_loaded()) { | 630 if (!prefix.is_loaded()) { |
| 663 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 631 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| 664 } | 632 } |
| 665 | 633 |
| 666 Object& obj = Object::Handle(zone, prefix.LookupObject(field_name_)); | 634 Object& obj = Object::Handle(zone, prefix.LookupObject(field_name_)); |
| 667 if (obj.IsField()) { | 635 if (obj.IsField()) { |
| 668 const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw()); | 636 const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw()); |
| 669 if (!field.is_final()) { | 637 if (!field.is_final()) { |
| 670 if (isolate->type_checks()) { | 638 if (isolate->type_checks()) { |
| 671 rhs = new AssignableNode(field.token_pos(), | 639 rhs = new AssignableNode(field.token_pos(), rhs, |
| 672 rhs, | |
| 673 AbstractType::ZoneHandle(zone, field.type()), | 640 AbstractType::ZoneHandle(zone, field.type()), |
| 674 field_name_); | 641 field_name_); |
| 675 } | 642 } |
| 676 return new StoreStaticFieldNode(token_pos(), field, rhs); | 643 return new StoreStaticFieldNode(token_pos(), field, rhs); |
| 677 } | 644 } |
| 678 } | 645 } |
| 679 | 646 |
| 680 // No field found in prefix. Look for a setter function. | 647 // No field found in prefix. Look for a setter function. |
| 681 const String& setter_name = | 648 const String& setter_name = |
| 682 String::Handle(zone, Field::LookupSetterSymbol(field_name_)); | 649 String::Handle(zone, Field::LookupSetterSymbol(field_name_)); |
| 683 if (!setter_name.IsNull()) { | 650 if (!setter_name.IsNull()) { |
| 684 obj = prefix.LookupObject(setter_name); | 651 obj = prefix.LookupObject(setter_name); |
| 685 if (obj.IsFunction()) { | 652 if (obj.IsFunction()) { |
| 686 const Function& setter = | 653 const Function& setter = |
| 687 Function::ZoneHandle(zone, Function::Cast(obj).raw()); | 654 Function::ZoneHandle(zone, Function::Cast(obj).raw()); |
| 688 ASSERT(setter.is_static() && setter.IsSetterFunction()); | 655 ASSERT(setter.is_static() && setter.IsSetterFunction()); |
| 689 return new StaticSetterNode( | 656 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, |
| 690 token_pos(), NULL, field_name_, setter, rhs); | 657 rhs); |
| 691 } | 658 } |
| 692 } | 659 } |
| 693 | 660 |
| 694 // No writeable field and no setter found in the prefix. Return a | 661 // No writeable field and no setter found in the prefix. Return a |
| 695 // non-existing setter that will throw an NSM error. | 662 // non-existing setter that will throw an NSM error. |
| 696 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 663 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| 697 } | 664 } |
| 698 | 665 |
| 699 if (owner().IsLibrary()) { | 666 if (owner().IsLibrary()) { |
| 700 const Library& library = Library::Cast(owner()); | 667 const Library& library = Library::Cast(owner()); |
| 701 Object& obj = Object::Handle(zone, library.ResolveName(field_name_)); | 668 Object& obj = Object::Handle(zone, library.ResolveName(field_name_)); |
| 702 if (obj.IsField()) { | 669 if (obj.IsField()) { |
| 703 const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw()); | 670 const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw()); |
| 704 if (!field.is_final()) { | 671 if (!field.is_final()) { |
| 705 if (isolate->type_checks()) { | 672 if (isolate->type_checks()) { |
| 706 rhs = new AssignableNode(field.token_pos(), | 673 rhs = new AssignableNode(field.token_pos(), rhs, |
| 707 rhs, | |
| 708 AbstractType::ZoneHandle(zone, field.type()), | 674 AbstractType::ZoneHandle(zone, field.type()), |
| 709 field_name_); | 675 field_name_); |
| 710 } | 676 } |
| 711 return new StoreStaticFieldNode(token_pos(), field, rhs); | 677 return new StoreStaticFieldNode(token_pos(), field, rhs); |
| 712 } | 678 } |
| 713 } | 679 } |
| 714 | 680 |
| 715 // No field found in library. Look for a setter function. | 681 // No field found in library. Look for a setter function. |
| 716 const String& setter_name = | 682 const String& setter_name = |
| 717 String::Handle(zone, Field::LookupSetterSymbol(field_name_)); | 683 String::Handle(zone, Field::LookupSetterSymbol(field_name_)); |
| 718 if (!setter_name.IsNull()) { | 684 if (!setter_name.IsNull()) { |
| 719 obj = library.ResolveName(setter_name); | 685 obj = library.ResolveName(setter_name); |
| 720 if (obj.IsFunction()) { | 686 if (obj.IsFunction()) { |
| 721 const Function& setter = | 687 const Function& setter = |
| 722 Function::ZoneHandle(zone, Function::Cast(obj).raw()); | 688 Function::ZoneHandle(zone, Function::Cast(obj).raw()); |
| 723 ASSERT(setter.is_static() && setter.IsSetterFunction()); | 689 ASSERT(setter.is_static() && setter.IsSetterFunction()); |
| 724 return | 690 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, |
| 725 new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs); | 691 rhs); |
| 726 } | 692 } |
| 727 } | 693 } |
| 728 | 694 |
| 729 // No writeable field and no setter found in the library. Return a | 695 // No writeable field and no setter found in the library. Return a |
| 730 // non-existing setter that will throw an NSM error. | 696 // non-existing setter that will throw an NSM error. |
| 731 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 697 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| 732 } | 698 } |
| 733 | 699 |
| 734 const Function& setter = | 700 const Function& setter = |
| 735 Function::ZoneHandle(zone, cls().LookupSetterFunction(field_name_)); | 701 Function::ZoneHandle(zone, cls().LookupSetterFunction(field_name_)); |
| 736 if (!setter.IsNull() && setter.IsStaticFunction()) { | 702 if (!setter.IsNull() && setter.IsStaticFunction()) { |
| 737 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs); | 703 return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs); |
| 738 } | 704 } |
| 739 // Could not find a static setter. Look for a field. | 705 // Could not find a static setter. Look for a field. |
| 740 // Access to a lazily initialized static field that has not yet been | 706 // Access to a lazily initialized static field that has not yet been |
| 741 // initialized is compiled to a static implicit getter. | 707 // initialized is compiled to a static implicit getter. |
| 742 // A setter may not exist for such a field. | 708 // A setter may not exist for such a field. |
| 743 const Field& field = Field::ZoneHandle(zone, | 709 const Field& field = |
| 744 cls().LookupStaticField(field_name_)); | 710 Field::ZoneHandle(zone, cls().LookupStaticField(field_name_)); |
| 745 if (!field.IsNull()) { | 711 if (!field.IsNull()) { |
| 746 if (field.is_final()) { | 712 if (field.is_final()) { |
| 747 // Attempting to assign to a final variable will cause a NoSuchMethodError | 713 // Attempting to assign to a final variable will cause a NoSuchMethodError |
| 748 // to be thrown. Change static getter to non-existent static setter in | 714 // to be thrown. Change static getter to non-existent static setter in |
| 749 // order to trigger the throw at runtime. | 715 // order to trigger the throw at runtime. |
| 750 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 716 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| 751 } | 717 } |
| 752 #if defined(DEBUG) | 718 #if defined(DEBUG) |
| 753 const String& getter_name = | 719 const String& getter_name = |
| 754 String::Handle(zone, Field::LookupGetterSymbol(field_name_)); | 720 String::Handle(zone, Field::LookupGetterSymbol(field_name_)); |
| 755 ASSERT(!getter_name.IsNull()); | 721 ASSERT(!getter_name.IsNull()); |
| 756 const Function& getter = | 722 const Function& getter = |
| 757 Function::Handle(zone, cls().LookupStaticFunction(getter_name)); | 723 Function::Handle(zone, cls().LookupStaticFunction(getter_name)); |
| 758 ASSERT(!getter.IsNull() && | 724 ASSERT(!getter.IsNull() && |
| 759 (getter.kind() == RawFunction::kImplicitStaticFinalGetter)); | 725 (getter.kind() == RawFunction::kImplicitStaticFinalGetter)); |
| 760 #endif | 726 #endif |
| 761 if (isolate->type_checks()) { | 727 if (isolate->type_checks()) { |
| 762 rhs = new AssignableNode( | 728 rhs = new AssignableNode(field.token_pos(), rhs, |
| 763 field.token_pos(), | 729 AbstractType::ZoneHandle(zone, field.type()), |
| 764 rhs, | 730 String::ZoneHandle(zone, field.name())); |
| 765 AbstractType::ZoneHandle(zone, field.type()), | |
| 766 String::ZoneHandle(zone, field.name())); | |
| 767 } | 731 } |
| 768 return new StoreStaticFieldNode(token_pos(), field, rhs); | 732 return new StoreStaticFieldNode(token_pos(), field, rhs); |
| 769 } | 733 } |
| 770 // Didn't find a static setter or a static field. Make a call to | 734 // Didn't find a static setter or a static field. Make a call to |
| 771 // the non-existent setter to trigger a NoSuchMethodError at runtime. | 735 // the non-existent setter to trigger a NoSuchMethodError at runtime. |
| 772 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 736 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| 773 } | 737 } |
| 774 | 738 |
| 775 | 739 |
| 776 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { | 740 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 if (result.IsError() || result.IsNull()) { | 785 if (result.IsError() || result.IsNull()) { |
| 822 // TODO(turnidge): We could get better error messages by returning | 786 // TODO(turnidge): We could get better error messages by returning |
| 823 // the Error object directly to the parser. This will involve | 787 // the Error object directly to the parser. This will involve |
| 824 // replumbing all of the EvalConstExpr methods. | 788 // replumbing all of the EvalConstExpr methods. |
| 825 return NULL; | 789 return NULL; |
| 826 } | 790 } |
| 827 return &Instance::ZoneHandle(Instance::Cast(result).raw()); | 791 return &Instance::ZoneHandle(Instance::Cast(result).raw()); |
| 828 } | 792 } |
| 829 | 793 |
| 830 } // namespace dart | 794 } // namespace dart |
| OLD | NEW |