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 |