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 | |
14 namespace dart { | 13 namespace dart { |
15 | 14 |
16 #define DEFINE_VISIT_FUNCTION(BaseName) \ | 15 #define DEFINE_VISIT_FUNCTION(BaseName) \ |
17 void BaseName##Node::Visit(AstNodeVisitor* visitor) { \ | 16 void BaseName##Node::Visit(AstNodeVisitor* visitor) { \ |
18 visitor->Visit##BaseName##Node(this); \ | 17 visitor->Visit##BaseName##Node(this); \ |
19 } | 18 } |
20 | 19 |
21 FOR_EACH_NODE(DEFINE_VISIT_FUNCTION) | 20 FOR_EACH_NODE(DEFINE_VISIT_FUNCTION) |
22 #undef DEFINE_VISIT_FUNCTION | 21 #undef DEFINE_VISIT_FUNCTION |
23 | 22 |
24 | |
25 #define DEFINE_NAME_FUNCTION(BaseName) \ | 23 #define DEFINE_NAME_FUNCTION(BaseName) \ |
26 const char* BaseName##Node::Name() const { return #BaseName; } | 24 const char* BaseName##Node::Name() const { return #BaseName; } |
27 | 25 |
28 FOR_EACH_NODE(DEFINE_NAME_FUNCTION) | 26 FOR_EACH_NODE(DEFINE_NAME_FUNCTION) |
29 #undef DEFINE_NAME_FUNCTION | 27 #undef DEFINE_NAME_FUNCTION |
30 | 28 |
31 | |
32 const Field* AstNode::MayCloneField(const Field& value) { | 29 const Field* AstNode::MayCloneField(const Field& value) { |
33 if (Compiler::IsBackgroundCompilation() || | 30 if (Compiler::IsBackgroundCompilation() || |
34 FLAG_force_clone_compiler_objects) { | 31 FLAG_force_clone_compiler_objects) { |
35 return &Field::ZoneHandle(value.CloneFromOriginal()); | 32 return &Field::ZoneHandle(value.CloneFromOriginal()); |
36 } else { | 33 } else { |
37 ASSERT(value.IsZoneHandle()); | 34 ASSERT(value.IsZoneHandle()); |
38 return &value; | 35 return &value; |
39 } | 36 } |
40 } | 37 } |
41 | 38 |
42 | |
43 // A visitor class to collect all the nodes (including children) into an | 39 // A visitor class to collect all the nodes (including children) into an |
44 // array. | 40 // array. |
45 class AstNodeCollector : public AstNodeVisitor { | 41 class AstNodeCollector : public AstNodeVisitor { |
46 public: | 42 public: |
47 explicit AstNodeCollector(GrowableArray<AstNode*>* nodes) : nodes_(nodes) {} | 43 explicit AstNodeCollector(GrowableArray<AstNode*>* nodes) : nodes_(nodes) {} |
48 | 44 |
49 #define DEFINE_VISITOR_FUNCTION(BaseName) \ | 45 #define DEFINE_VISITOR_FUNCTION(BaseName) \ |
50 virtual void Visit##BaseName##Node(BaseName##Node* node) { \ | 46 virtual void Visit##BaseName##Node(BaseName##Node* node) { \ |
51 nodes_->Add(node); \ | 47 nodes_->Add(node); \ |
52 node->VisitChildren(this); \ | 48 node->VisitChildren(this); \ |
53 } | 49 } |
54 | 50 |
55 FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION) | 51 FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION) |
56 #undef DEFINE_VISITOR_FUNCTION | 52 #undef DEFINE_VISITOR_FUNCTION |
57 | 53 |
58 private: | 54 private: |
59 GrowableArray<AstNode*>* nodes_; | 55 GrowableArray<AstNode*>* nodes_; |
60 DISALLOW_COPY_AND_ASSIGN(AstNodeCollector); | 56 DISALLOW_COPY_AND_ASSIGN(AstNodeCollector); |
61 }; | 57 }; |
62 | 58 |
63 | |
64 void SequenceNode::CollectAllNodes(GrowableArray<AstNode*>* nodes) { | 59 void SequenceNode::CollectAllNodes(GrowableArray<AstNode*>* nodes) { |
65 AstNodeCollector node_collector(nodes); | 60 AstNodeCollector node_collector(nodes); |
66 this->Visit(&node_collector); | 61 this->Visit(&node_collector); |
67 } | 62 } |
68 | 63 |
69 | |
70 void SequenceNode::VisitChildren(AstNodeVisitor* visitor) const { | 64 void SequenceNode::VisitChildren(AstNodeVisitor* visitor) const { |
71 for (intptr_t i = 0; i < this->length(); i++) { | 65 for (intptr_t i = 0; i < this->length(); i++) { |
72 NodeAt(i)->Visit(visitor); | 66 NodeAt(i)->Visit(visitor); |
73 } | 67 } |
74 } | 68 } |
75 | 69 |
76 | |
77 void SequenceNode::Add(AstNode* node) { | 70 void SequenceNode::Add(AstNode* node) { |
78 if (node->IsReturnNode()) { | 71 if (node->IsReturnNode()) { |
79 node->AsReturnNode()->set_scope(scope()); | 72 node->AsReturnNode()->set_scope(scope()); |
80 } | 73 } |
81 nodes_.Add(node); | 74 nodes_.Add(node); |
82 } | 75 } |
83 | 76 |
84 | |
85 void PrimaryNode::VisitChildren(AstNodeVisitor* visitor) const {} | 77 void PrimaryNode::VisitChildren(AstNodeVisitor* visitor) const {} |
86 | 78 |
87 | |
88 void ArgumentListNode::VisitChildren(AstNodeVisitor* visitor) const { | 79 void ArgumentListNode::VisitChildren(AstNodeVisitor* visitor) const { |
89 for (intptr_t i = 0; i < this->length(); i++) { | 80 for (intptr_t i = 0; i < this->length(); i++) { |
90 NodeAt(i)->Visit(visitor); | 81 NodeAt(i)->Visit(visitor); |
91 } | 82 } |
92 } | 83 } |
93 | 84 |
94 | |
95 LetNode::LetNode(TokenPosition token_pos) | 85 LetNode::LetNode(TokenPosition token_pos) |
96 : AstNode(token_pos), vars_(1), initializers_(1), nodes_(1) {} | 86 : AstNode(token_pos), vars_(1), initializers_(1), nodes_(1) {} |
97 | 87 |
98 | |
99 LocalVariable* LetNode::AddInitializer(AstNode* node) { | 88 LocalVariable* LetNode::AddInitializer(AstNode* node) { |
100 Thread* thread = Thread::Current(); | 89 Thread* thread = Thread::Current(); |
101 Zone* zone = thread->zone(); | 90 Zone* zone = thread->zone(); |
102 initializers_.Add(node); | 91 initializers_.Add(node); |
103 char name[64]; | 92 char name[64]; |
104 OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(), | 93 OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(), |
105 vars_.length()); | 94 vars_.length()); |
106 LocalVariable* temp_var = | 95 LocalVariable* temp_var = |
107 new LocalVariable(TokenPosition::kNoSource, token_pos(), | 96 new LocalVariable(TokenPosition::kNoSource, token_pos(), |
108 String::ZoneHandle(zone, Symbols::New(thread, name)), | 97 String::ZoneHandle(zone, Symbols::New(thread, name)), |
109 Object::dynamic_type()); | 98 Object::dynamic_type()); |
110 vars_.Add(temp_var); | 99 vars_.Add(temp_var); |
111 return temp_var; | 100 return temp_var; |
112 } | 101 } |
113 | 102 |
114 | |
115 void LetNode::VisitChildren(AstNodeVisitor* visitor) const { | 103 void LetNode::VisitChildren(AstNodeVisitor* visitor) const { |
116 for (intptr_t i = 0; i < num_temps(); ++i) { | 104 for (intptr_t i = 0; i < num_temps(); ++i) { |
117 initializers_[i]->Visit(visitor); | 105 initializers_[i]->Visit(visitor); |
118 } | 106 } |
119 for (intptr_t i = 0; i < nodes_.length(); ++i) { | 107 for (intptr_t i = 0; i < nodes_.length(); ++i) { |
120 nodes_[i]->Visit(visitor); | 108 nodes_[i]->Visit(visitor); |
121 } | 109 } |
122 } | 110 } |
123 | 111 |
124 bool LetNode::IsPotentiallyConst() const { | 112 bool LetNode::IsPotentiallyConst() const { |
(...skipping 19 matching lines...) Expand all Loading... |
144 const Instance* last = NULL; | 132 const Instance* last = NULL; |
145 for (intptr_t i = 0; i < nodes_.length(); i++) { | 133 for (intptr_t i = 0; i < nodes_.length(); i++) { |
146 last = nodes_[i]->EvalConstExpr(); | 134 last = nodes_[i]->EvalConstExpr(); |
147 if (last == NULL) { | 135 if (last == NULL) { |
148 return NULL; | 136 return NULL; |
149 } | 137 } |
150 } | 138 } |
151 return last; | 139 return last; |
152 } | 140 } |
153 | 141 |
154 | |
155 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const { | 142 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const { |
156 for (intptr_t i = 0; i < this->length(); i++) { | 143 for (intptr_t i = 0; i < this->length(); i++) { |
157 ElementAt(i)->Visit(visitor); | 144 ElementAt(i)->Visit(visitor); |
158 } | 145 } |
159 } | 146 } |
160 | 147 |
161 | |
162 bool StringInterpolateNode::IsPotentiallyConst() const { | 148 bool StringInterpolateNode::IsPotentiallyConst() const { |
163 for (int i = 0; i < value_->length(); i++) { | 149 for (int i = 0; i < value_->length(); i++) { |
164 if (!value_->ElementAt(i)->IsPotentiallyConst()) { | 150 if (!value_->ElementAt(i)->IsPotentiallyConst()) { |
165 return false; | 151 return false; |
166 } | 152 } |
167 } | 153 } |
168 return true; | 154 return true; |
169 } | 155 } |
170 | 156 |
171 | |
172 bool LiteralNode::IsPotentiallyConst() const { | 157 bool LiteralNode::IsPotentiallyConst() const { |
173 return true; | 158 return true; |
174 } | 159 } |
175 | 160 |
176 | |
177 AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) { | 161 AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) { |
178 if (unary_op_kind == Token::kNEGATE) { | 162 if (unary_op_kind == Token::kNEGATE) { |
179 if (literal().IsSmi()) { | 163 if (literal().IsSmi()) { |
180 const Smi& smi = Smi::Cast(literal()); | 164 const Smi& smi = Smi::Cast(literal()); |
181 const Instance& literal = | 165 const Instance& literal = |
182 Instance::ZoneHandle(Integer::New(-smi.Value(), Heap::kOld)); | 166 Instance::ZoneHandle(Integer::New(-smi.Value(), Heap::kOld)); |
183 return new LiteralNode(this->token_pos(), literal); | 167 return new LiteralNode(this->token_pos(), literal); |
184 } | 168 } |
185 if (literal().IsMint()) { | 169 if (literal().IsMint()) { |
186 const Mint& mint = Mint::Cast(literal()); | 170 const Mint& mint = Mint::Cast(literal()); |
(...skipping 24 matching lines...) Expand all Loading... |
211 } | 195 } |
212 } else if (unary_op_kind == Token::kNOT) { | 196 } else if (unary_op_kind == Token::kNOT) { |
213 if (literal().IsBool()) { | 197 if (literal().IsBool()) { |
214 const Bool& boolean = Bool::Cast(literal()); | 198 const Bool& boolean = Bool::Cast(literal()); |
215 return new LiteralNode(this->token_pos(), Bool::Get(!boolean.value())); | 199 return new LiteralNode(this->token_pos(), Bool::Get(!boolean.value())); |
216 } | 200 } |
217 } | 201 } |
218 return NULL; | 202 return NULL; |
219 } | 203 } |
220 | 204 |
221 | |
222 const char* TypeNode::TypeName() const { | 205 const char* TypeNode::TypeName() const { |
223 return String::Handle(type().UserVisibleName()).ToCString(); | 206 return String::Handle(type().UserVisibleName()).ToCString(); |
224 } | 207 } |
225 | 208 |
226 | |
227 bool ComparisonNode::IsKindValid() const { | 209 bool ComparisonNode::IsKindValid() const { |
228 return Token::IsRelationalOperator(kind_) || | 210 return Token::IsRelationalOperator(kind_) || |
229 Token::IsEqualityOperator(kind_) || Token::IsTypeTestOperator(kind_) || | 211 Token::IsEqualityOperator(kind_) || Token::IsTypeTestOperator(kind_) || |
230 Token::IsTypeCastOperator(kind_); | 212 Token::IsTypeCastOperator(kind_); |
231 } | 213 } |
232 | 214 |
233 | |
234 const char* ComparisonNode::TokenName() const { | 215 const char* ComparisonNode::TokenName() const { |
235 return (kind_ == Token::kAS) ? "as" : Token::Str(kind_); | 216 return (kind_ == Token::kAS) ? "as" : Token::Str(kind_); |
236 } | 217 } |
237 | 218 |
238 | |
239 bool ComparisonNode::IsPotentiallyConst() const { | 219 bool ComparisonNode::IsPotentiallyConst() const { |
240 switch (kind_) { | 220 switch (kind_) { |
241 case Token::kLT: | 221 case Token::kLT: |
242 case Token::kGT: | 222 case Token::kGT: |
243 case Token::kLTE: | 223 case Token::kLTE: |
244 case Token::kGTE: | 224 case Token::kGTE: |
245 case Token::kEQ: | 225 case Token::kEQ: |
246 case Token::kNE: | 226 case Token::kNE: |
247 case Token::kEQ_STRICT: | 227 case Token::kEQ_STRICT: |
248 case Token::kNE_STRICT: | 228 case Token::kNE_STRICT: |
249 return this->left()->IsPotentiallyConst() && | 229 return this->left()->IsPotentiallyConst() && |
250 this->right()->IsPotentiallyConst(); | 230 this->right()->IsPotentiallyConst(); |
251 default: | 231 default: |
252 return false; | 232 return false; |
253 } | 233 } |
254 } | 234 } |
255 | 235 |
256 | |
257 const Instance* ComparisonNode::EvalConstExpr() const { | 236 const Instance* ComparisonNode::EvalConstExpr() const { |
258 const Instance* left_val = this->left()->EvalConstExpr(); | 237 const Instance* left_val = this->left()->EvalConstExpr(); |
259 if (left_val == NULL) { | 238 if (left_val == NULL) { |
260 return NULL; | 239 return NULL; |
261 } | 240 } |
262 const Instance* right_val = this->right()->EvalConstExpr(); | 241 const Instance* right_val = this->right()->EvalConstExpr(); |
263 if (right_val == NULL) { | 242 if (right_val == NULL) { |
264 return NULL; | 243 return NULL; |
265 } | 244 } |
266 switch (kind_) { | 245 switch (kind_) { |
(...skipping 21 matching lines...) Expand all Loading... |
288 case Token::kNE_STRICT: | 267 case Token::kNE_STRICT: |
289 // identical(a, b) is a compile time const if both operands are | 268 // identical(a, b) is a compile time const if both operands are |
290 // compile time constants, regardless of their type. | 269 // compile time constants, regardless of their type. |
291 return &Bool::True(); | 270 return &Bool::True(); |
292 default: | 271 default: |
293 return NULL; | 272 return NULL; |
294 } | 273 } |
295 return NULL; | 274 return NULL; |
296 } | 275 } |
297 | 276 |
298 | |
299 bool BinaryOpNode::IsKindValid() const { | 277 bool BinaryOpNode::IsKindValid() const { |
300 switch (kind_) { | 278 switch (kind_) { |
301 case Token::kADD: | 279 case Token::kADD: |
302 case Token::kSUB: | 280 case Token::kSUB: |
303 case Token::kMUL: | 281 case Token::kMUL: |
304 case Token::kDIV: | 282 case Token::kDIV: |
305 case Token::kTRUNCDIV: | 283 case Token::kTRUNCDIV: |
306 case Token::kMOD: | 284 case Token::kMOD: |
307 case Token::kOR: | 285 case Token::kOR: |
308 case Token::kAND: | 286 case Token::kAND: |
309 case Token::kIFNULL: | 287 case Token::kIFNULL: |
310 case Token::kBIT_OR: | 288 case Token::kBIT_OR: |
311 case Token::kBIT_XOR: | 289 case Token::kBIT_XOR: |
312 case Token::kBIT_AND: | 290 case Token::kBIT_AND: |
313 case Token::kSHL: | 291 case Token::kSHL: |
314 case Token::kSHR: | 292 case Token::kSHR: |
315 return true; | 293 return true; |
316 default: | 294 default: |
317 return false; | 295 return false; |
318 } | 296 } |
319 } | 297 } |
320 | 298 |
321 | |
322 const char* BinaryOpNode::TokenName() const { | 299 const char* BinaryOpNode::TokenName() const { |
323 return Token::Str(kind_); | 300 return Token::Str(kind_); |
324 } | 301 } |
325 | 302 |
326 | |
327 bool BinaryOpNode::IsPotentiallyConst() const { | 303 bool BinaryOpNode::IsPotentiallyConst() const { |
328 switch (kind_) { | 304 switch (kind_) { |
329 case Token::kOR: | 305 case Token::kOR: |
330 case Token::kAND: | 306 case Token::kAND: |
331 if (this->left()->IsLiteralNode() && | 307 if (this->left()->IsLiteralNode() && |
332 this->left()->AsLiteralNode()->literal().IsNull()) { | 308 this->left()->AsLiteralNode()->literal().IsNull()) { |
333 return false; | 309 return false; |
334 } | 310 } |
335 if (this->right()->IsLiteralNode() && | 311 if (this->right()->IsLiteralNode() && |
336 this->right()->AsLiteralNode()->literal().IsNull()) { | 312 this->right()->AsLiteralNode()->literal().IsNull()) { |
(...skipping 13 matching lines...) Expand all Loading... |
350 case Token::kSHR: | 326 case Token::kSHR: |
351 case Token::kIFNULL: | 327 case Token::kIFNULL: |
352 return this->left()->IsPotentiallyConst() && | 328 return this->left()->IsPotentiallyConst() && |
353 this->right()->IsPotentiallyConst(); | 329 this->right()->IsPotentiallyConst(); |
354 default: | 330 default: |
355 UNREACHABLE(); | 331 UNREACHABLE(); |
356 return false; | 332 return false; |
357 } | 333 } |
358 } | 334 } |
359 | 335 |
360 | |
361 const Instance* BinaryOpNode::EvalConstExpr() const { | 336 const Instance* BinaryOpNode::EvalConstExpr() const { |
362 const Instance* left_val = this->left()->EvalConstExpr(); | 337 const Instance* left_val = this->left()->EvalConstExpr(); |
363 if (left_val == NULL) { | 338 if (left_val == NULL) { |
364 return NULL; | 339 return NULL; |
365 } | 340 } |
366 if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() && | 341 if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() && |
367 kind_ != Token::kIFNULL) { | 342 kind_ != Token::kIFNULL) { |
368 return NULL; | 343 return NULL; |
369 } | 344 } |
370 const Instance* right_val = this->right()->EvalConstExpr(); | 345 const Instance* right_val = this->right()->EvalConstExpr(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 return right_val; | 387 return right_val; |
413 } | 388 } |
414 return left_val; | 389 return left_val; |
415 default: | 390 default: |
416 UNREACHABLE(); | 391 UNREACHABLE(); |
417 return NULL; | 392 return NULL; |
418 } | 393 } |
419 return NULL; | 394 return NULL; |
420 } | 395 } |
421 | 396 |
422 | |
423 AstNode* UnaryOpNode::UnaryOpOrLiteral(TokenPosition token_pos, | 397 AstNode* UnaryOpNode::UnaryOpOrLiteral(TokenPosition token_pos, |
424 Token::Kind kind, | 398 Token::Kind kind, |
425 AstNode* operand) { | 399 AstNode* operand) { |
426 AstNode* new_operand = operand->ApplyUnaryOp(kind); | 400 AstNode* new_operand = operand->ApplyUnaryOp(kind); |
427 if (new_operand != NULL) { | 401 if (new_operand != NULL) { |
428 return new_operand; | 402 return new_operand; |
429 } | 403 } |
430 return new UnaryOpNode(token_pos, kind, operand); | 404 return new UnaryOpNode(token_pos, kind, operand); |
431 } | 405 } |
432 | 406 |
433 | |
434 bool UnaryOpNode::IsKindValid() const { | 407 bool UnaryOpNode::IsKindValid() const { |
435 switch (kind_) { | 408 switch (kind_) { |
436 case Token::kNEGATE: | 409 case Token::kNEGATE: |
437 case Token::kNOT: | 410 case Token::kNOT: |
438 case Token::kBIT_NOT: | 411 case Token::kBIT_NOT: |
439 return true; | 412 return true; |
440 default: | 413 default: |
441 return false; | 414 return false; |
442 } | 415 } |
443 } | 416 } |
444 | 417 |
445 | |
446 bool UnaryOpNode::IsPotentiallyConst() const { | 418 bool UnaryOpNode::IsPotentiallyConst() const { |
447 if (this->operand()->IsLiteralNode() && | 419 if (this->operand()->IsLiteralNode() && |
448 this->operand()->AsLiteralNode()->literal().IsNull()) { | 420 this->operand()->AsLiteralNode()->literal().IsNull()) { |
449 return false; | 421 return false; |
450 } | 422 } |
451 return this->operand()->IsPotentiallyConst(); | 423 return this->operand()->IsPotentiallyConst(); |
452 } | 424 } |
453 | 425 |
454 | |
455 const Instance* UnaryOpNode::EvalConstExpr() const { | 426 const Instance* UnaryOpNode::EvalConstExpr() const { |
456 const Instance* val = this->operand()->EvalConstExpr(); | 427 const Instance* val = this->operand()->EvalConstExpr(); |
457 if (val == NULL) { | 428 if (val == NULL) { |
458 return NULL; | 429 return NULL; |
459 } | 430 } |
460 switch (kind_) { | 431 switch (kind_) { |
461 case Token::kNEGATE: | 432 case Token::kNEGATE: |
462 return val->IsNumber() ? val : NULL; | 433 return val->IsNumber() ? val : NULL; |
463 case Token::kNOT: | 434 case Token::kNOT: |
464 return val->IsBool() ? val : NULL; | 435 return val->IsBool() ? val : NULL; |
465 case Token::kBIT_NOT: | 436 case Token::kBIT_NOT: |
466 return val->IsInteger() ? val : NULL; | 437 return val->IsInteger() ? val : NULL; |
467 default: | 438 default: |
468 return NULL; | 439 return NULL; |
469 } | 440 } |
470 } | 441 } |
471 | 442 |
472 | |
473 bool ConditionalExprNode::IsPotentiallyConst() const { | 443 bool ConditionalExprNode::IsPotentiallyConst() const { |
474 return this->condition()->IsPotentiallyConst() && | 444 return this->condition()->IsPotentiallyConst() && |
475 this->true_expr()->IsPotentiallyConst() && | 445 this->true_expr()->IsPotentiallyConst() && |
476 this->false_expr()->IsPotentiallyConst(); | 446 this->false_expr()->IsPotentiallyConst(); |
477 } | 447 } |
478 | 448 |
479 | |
480 const Instance* ConditionalExprNode::EvalConstExpr() const { | 449 const Instance* ConditionalExprNode::EvalConstExpr() const { |
481 const Instance* cond = this->condition()->EvalConstExpr(); | 450 const Instance* cond = this->condition()->EvalConstExpr(); |
482 if ((cond != NULL) && cond->IsBool() && | 451 if ((cond != NULL) && cond->IsBool() && |
483 (this->true_expr()->EvalConstExpr() != NULL) && | 452 (this->true_expr()->EvalConstExpr() != NULL) && |
484 (this->false_expr()->EvalConstExpr() != NULL)) { | 453 (this->false_expr()->EvalConstExpr() != NULL)) { |
485 return cond; | 454 return cond; |
486 } | 455 } |
487 return NULL; | 456 return NULL; |
488 } | 457 } |
489 | 458 |
490 | |
491 bool ClosureNode::IsPotentiallyConst() const { | 459 bool ClosureNode::IsPotentiallyConst() const { |
492 if (function().IsImplicitStaticClosureFunction()) { | 460 if (function().IsImplicitStaticClosureFunction()) { |
493 return true; | 461 return true; |
494 } | 462 } |
495 return false; | 463 return false; |
496 } | 464 } |
497 | 465 |
498 | |
499 const Instance* ClosureNode::EvalConstExpr() const { | 466 const Instance* ClosureNode::EvalConstExpr() const { |
500 if (!is_deferred_reference_ && function().IsImplicitStaticClosureFunction()) { | 467 if (!is_deferred_reference_ && function().IsImplicitStaticClosureFunction()) { |
501 // Return a value that represents an instance. Only the type is relevant. | 468 // Return a value that represents an instance. Only the type is relevant. |
502 return &Instance::Handle(); | 469 return &Instance::Handle(); |
503 } | 470 } |
504 return NULL; | 471 return NULL; |
505 } | 472 } |
506 | 473 |
507 | |
508 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { | 474 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { |
509 if (scope() == NULL) { | 475 if (scope() == NULL) { |
510 // This is an implicit closure node created because a static getter was not | 476 // This is an implicit closure node created because a static getter was not |
511 // found. Change the getter into a setter. If it does not exist, | 477 // found. Change the getter into a setter. If it does not exist, |
512 // noSuchMethod will be called. | 478 // noSuchMethod will be called. |
513 return new StaticSetterNode(token_pos(), receiver(), | 479 return new StaticSetterNode(token_pos(), receiver(), |
514 Class::ZoneHandle(function().Owner()), | 480 Class::ZoneHandle(function().Owner()), |
515 String::ZoneHandle(function().name()), rhs); | 481 String::ZoneHandle(function().name()), rhs); |
516 } | 482 } |
517 return NULL; | 483 return NULL; |
518 } | 484 } |
519 | 485 |
520 | |
521 const char* UnaryOpNode::TokenName() const { | 486 const char* UnaryOpNode::TokenName() const { |
522 return Token::Str(kind_); | 487 return Token::Str(kind_); |
523 } | 488 } |
524 | 489 |
525 | |
526 const char* JumpNode::TokenName() const { | 490 const char* JumpNode::TokenName() const { |
527 return Token::Str(kind_); | 491 return Token::Str(kind_); |
528 } | 492 } |
529 | 493 |
530 | |
531 bool LoadLocalNode::IsPotentiallyConst() const { | 494 bool LoadLocalNode::IsPotentiallyConst() const { |
532 // Parameters of const constructors are implicitly final and can be | 495 // Parameters of const constructors are implicitly final and can be |
533 // used in initializer expressions. | 496 // used in initializer expressions. |
534 // We can't check here whether the local variable is indeed a parameter, | 497 // We can't check here whether the local variable is indeed a parameter, |
535 // but this code is executed before any other local variables are | 498 // but this code is executed before any other local variables are |
536 // added to the scope. | 499 // added to the scope. |
537 return local().is_final(); | 500 return local().is_final(); |
538 } | 501 } |
539 | 502 |
540 | |
541 const Instance* LoadLocalNode::EvalConstExpr() const { | 503 const Instance* LoadLocalNode::EvalConstExpr() const { |
542 if (local().IsConst()) { | 504 if (local().IsConst()) { |
543 return local().ConstValue(); | 505 return local().ConstValue(); |
544 } | 506 } |
545 return NULL; | 507 return NULL; |
546 } | 508 } |
547 | 509 |
548 | |
549 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { | 510 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { |
550 if (local().is_final()) { | 511 if (local().is_final()) { |
551 return NULL; | 512 return NULL; |
552 } | 513 } |
553 return new StoreLocalNode(token_pos(), &local(), rhs); | 514 return new StoreLocalNode(token_pos(), &local(), rhs); |
554 } | 515 } |
555 | 516 |
556 | |
557 AstNode* LoadStaticFieldNode::MakeAssignmentNode(AstNode* rhs) { | 517 AstNode* LoadStaticFieldNode::MakeAssignmentNode(AstNode* rhs) { |
558 if (field().is_final()) { | 518 if (field().is_final()) { |
559 return NULL; | 519 return NULL; |
560 } | 520 } |
561 if (Isolate::Current()->type_checks()) { | 521 if (Isolate::Current()->type_checks()) { |
562 rhs = new AssignableNode(field().token_pos(), rhs, | 522 rhs = new AssignableNode(field().token_pos(), rhs, |
563 AbstractType::ZoneHandle(field().type()), | 523 AbstractType::ZoneHandle(field().type()), |
564 String::ZoneHandle(field().name())); | 524 String::ZoneHandle(field().name())); |
565 } | 525 } |
566 return new StoreStaticFieldNode(token_pos(), | 526 return new StoreStaticFieldNode(token_pos(), |
567 Field::ZoneHandle(field().Original()), rhs); | 527 Field::ZoneHandle(field().Original()), rhs); |
568 } | 528 } |
569 | 529 |
570 | |
571 AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) { | 530 AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) { |
572 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs, | 531 return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs, |
573 is_conditional()); | 532 is_conditional()); |
574 } | 533 } |
575 | 534 |
576 | |
577 bool InstanceGetterNode::IsPotentiallyConst() const { | 535 bool InstanceGetterNode::IsPotentiallyConst() const { |
578 return field_name().Equals(Symbols::Length()) && !is_conditional() && | 536 return field_name().Equals(Symbols::Length()) && !is_conditional() && |
579 receiver()->IsPotentiallyConst(); | 537 receiver()->IsPotentiallyConst(); |
580 } | 538 } |
581 | 539 |
582 | |
583 const Instance* InstanceGetterNode::EvalConstExpr() const { | 540 const Instance* InstanceGetterNode::EvalConstExpr() const { |
584 if (field_name().Equals(Symbols::Length()) && !is_conditional()) { | 541 if (field_name().Equals(Symbols::Length()) && !is_conditional()) { |
585 const Instance* receiver_val = receiver()->EvalConstExpr(); | 542 const Instance* receiver_val = receiver()->EvalConstExpr(); |
586 if ((receiver_val != NULL) && receiver_val->IsString()) { | 543 if ((receiver_val != NULL) && receiver_val->IsString()) { |
587 return &Instance::ZoneHandle(Smi::New(1)); | 544 return &Instance::ZoneHandle(Smi::New(1)); |
588 } | 545 } |
589 } | 546 } |
590 return NULL; | 547 return NULL; |
591 } | 548 } |
592 | 549 |
593 | |
594 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { | 550 AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) { |
595 return new StoreIndexedNode(token_pos(), array(), index_expr(), rhs, | 551 return new StoreIndexedNode(token_pos(), array(), index_expr(), rhs, |
596 super_class()); | 552 super_class()); |
597 } | 553 } |
598 | 554 |
599 | |
600 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { | 555 AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { |
601 Thread* thread = Thread::Current(); | 556 Thread* thread = Thread::Current(); |
602 Zone* zone = thread->zone(); | 557 Zone* zone = thread->zone(); |
603 Isolate* isolate = thread->isolate(); | 558 Isolate* isolate = thread->isolate(); |
604 if (is_super_getter()) { | 559 if (is_super_getter()) { |
605 ASSERT(receiver() != NULL); | 560 ASSERT(receiver() != NULL); |
606 const String& setter_name = | 561 const String& setter_name = |
607 String::ZoneHandle(zone, Field::LookupSetterSymbol(field_name_)); | 562 String::ZoneHandle(zone, Field::LookupSetterSymbol(field_name_)); |
608 Function& setter = Function::ZoneHandle(zone); | 563 Function& setter = Function::ZoneHandle(zone); |
609 if (!setter_name.IsNull()) { | 564 if (!setter_name.IsNull()) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 AbstractType::ZoneHandle(zone, field.type()), | 684 AbstractType::ZoneHandle(zone, field.type()), |
730 String::ZoneHandle(zone, field.name())); | 685 String::ZoneHandle(zone, field.name())); |
731 } | 686 } |
732 return new StoreStaticFieldNode(token_pos(), field, rhs); | 687 return new StoreStaticFieldNode(token_pos(), field, rhs); |
733 } | 688 } |
734 // Didn't find a static setter or a static field. Make a call to | 689 // Didn't find a static setter or a static field. Make a call to |
735 // the non-existent setter to trigger a NoSuchMethodError at runtime. | 690 // the non-existent setter to trigger a NoSuchMethodError at runtime. |
736 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); | 691 return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
737 } | 692 } |
738 | 693 |
739 | |
740 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { | 694 AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) { |
741 // Return this node if it represents a 'throw NoSuchMethodError' indicating | 695 // Return this node if it represents a 'throw NoSuchMethodError' indicating |
742 // that a getter was not found, otherwise return null. | 696 // that a getter was not found, otherwise return null. |
743 const Class& cls = Class::Handle(function().Owner()); | 697 const Class& cls = Class::Handle(function().Owner()); |
744 const String& cls_name = String::Handle(cls.Name()); | 698 const String& cls_name = String::Handle(cls.Name()); |
745 const String& func_name = String::Handle(function().name()); | 699 const String& func_name = String::Handle(function().name()); |
746 if (cls_name.Equals(Symbols::NoSuchMethodError()) && | 700 if (cls_name.Equals(Symbols::NoSuchMethodError()) && |
747 func_name.StartsWith(Symbols::ThrowNew())) { | 701 func_name.StartsWith(Symbols::ThrowNew())) { |
748 return this; | 702 return this; |
749 } | 703 } |
750 return NULL; | 704 return NULL; |
751 } | 705 } |
752 | 706 |
753 | |
754 bool StaticGetterNode::IsPotentiallyConst() const { | 707 bool StaticGetterNode::IsPotentiallyConst() const { |
755 if (is_deferred_reference_) { | 708 if (is_deferred_reference_) { |
756 return false; | 709 return false; |
757 } | 710 } |
758 const String& getter_name = | 711 const String& getter_name = |
759 String::Handle(Field::GetterName(this->field_name())); | 712 String::Handle(Field::GetterName(this->field_name())); |
760 const Function& getter_func = | 713 const Function& getter_func = |
761 Function::Handle(this->cls().LookupStaticFunction(getter_name)); | 714 Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
762 if (getter_func.IsNull() || !getter_func.is_const()) { | 715 if (getter_func.IsNull() || !getter_func.is_const()) { |
763 return false; | 716 return false; |
764 } | 717 } |
765 return true; | 718 return true; |
766 } | 719 } |
767 | 720 |
768 | |
769 const Instance* StaticGetterNode::EvalConstExpr() const { | 721 const Instance* StaticGetterNode::EvalConstExpr() const { |
770 if (is_deferred_reference_) { | 722 if (is_deferred_reference_) { |
771 return NULL; | 723 return NULL; |
772 } | 724 } |
773 const String& getter_name = | 725 const String& getter_name = |
774 String::Handle(Field::LookupGetterSymbol(this->field_name())); | 726 String::Handle(Field::LookupGetterSymbol(this->field_name())); |
775 if (getter_name.IsNull()) { | 727 if (getter_name.IsNull()) { |
776 return NULL; | 728 return NULL; |
777 } | 729 } |
778 const Function& getter_func = | 730 const Function& getter_func = |
779 Function::Handle(this->cls().LookupStaticFunction(getter_name)); | 731 Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
780 if (getter_func.IsNull() || !getter_func.is_const()) { | 732 if (getter_func.IsNull() || !getter_func.is_const()) { |
781 return NULL; | 733 return NULL; |
782 } | 734 } |
783 const Object& result = Object::Handle( | 735 const Object& result = Object::Handle( |
784 DartEntry::InvokeFunction(getter_func, Object::empty_array())); | 736 DartEntry::InvokeFunction(getter_func, Object::empty_array())); |
785 if (result.IsError() || result.IsNull()) { | 737 if (result.IsError() || result.IsNull()) { |
786 // TODO(turnidge): We could get better error messages by returning | 738 // TODO(turnidge): We could get better error messages by returning |
787 // the Error object directly to the parser. This will involve | 739 // the Error object directly to the parser. This will involve |
788 // replumbing all of the EvalConstExpr methods. | 740 // replumbing all of the EvalConstExpr methods. |
789 return NULL; | 741 return NULL; |
790 } | 742 } |
791 return &Instance::ZoneHandle(Instance::Cast(result).raw()); | 743 return &Instance::ZoneHandle(Instance::Cast(result).raw()); |
792 } | 744 } |
793 | 745 |
794 } // namespace dart | 746 } // namespace dart |
OLD | NEW |