OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/ast.h" | 5 #include "vm/ast.h" |
6 #include "vm/compiler.h" | 6 #include "vm/compiler.h" |
7 #include "vm/dart_entry.h" | 7 #include "vm/dart_entry.h" |
8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
10 #include "vm/resolver.h" | 10 #include "vm/resolver.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 } | 103 } |
104 | 104 |
105 | 105 |
106 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const { | 106 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const { |
107 for (intptr_t i = 0; i < this->length(); i++) { | 107 for (intptr_t i = 0; i < this->length(); i++) { |
108 ElementAt(i)->Visit(visitor); | 108 ElementAt(i)->Visit(visitor); |
109 } | 109 } |
110 } | 110 } |
111 | 111 |
112 | 112 |
113 bool LiteralNode::IsPotentiallyConst() const { | |
114 return true; | |
115 } | |
116 | |
117 | |
113 // TODO(srdjan): Add code for logical negation. | 118 // TODO(srdjan): Add code for logical negation. |
114 AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) { | 119 AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) { |
115 if (unary_op_kind == Token::kNEGATE) { | 120 if (unary_op_kind == Token::kNEGATE) { |
116 if (literal().IsSmi()) { | 121 if (literal().IsSmi()) { |
117 const Smi& smi = Smi::Cast(literal()); | 122 const Smi& smi = Smi::Cast(literal()); |
118 const Instance& literal = | 123 const Instance& literal = |
119 Instance::ZoneHandle(Integer::New(-smi.Value())); | 124 Instance::ZoneHandle(Integer::New(-smi.Value())); |
120 return new LiteralNode(this->token_pos(), literal); | 125 return new LiteralNode(this->token_pos(), literal); |
121 } | 126 } |
122 if (literal().IsDouble()) { | 127 if (literal().IsDouble()) { |
(...skipping 15 matching lines...) Expand all Loading... | |
138 || Token::IsTypeTestOperator(kind_) | 143 || Token::IsTypeTestOperator(kind_) |
139 || Token::IsTypeCastOperator(kind_); | 144 || Token::IsTypeCastOperator(kind_); |
140 } | 145 } |
141 | 146 |
142 | 147 |
143 const char* ComparisonNode::Name() const { | 148 const char* ComparisonNode::Name() const { |
144 return Token::Str(kind_); | 149 return Token::Str(kind_); |
145 } | 150 } |
146 | 151 |
147 | 152 |
153 bool ComparisonNode::IsPotentiallyConst() const { | |
154 switch (kind_) { | |
155 case Token::kLT: | |
156 case Token::kGT: | |
157 case Token::kLTE: | |
158 case Token::kGTE: | |
159 case Token::kEQ: | |
160 case Token::kNE: | |
161 case Token::kEQ_STRICT: | |
162 case Token::kNE_STRICT: | |
163 return this->left()->IsPotentiallyConst() && | |
164 this->right()->IsPotentiallyConst(); | |
165 default: | |
166 return false; | |
167 } | |
168 } | |
169 | |
170 | |
148 const Instance* ComparisonNode::EvalConstExpr() const { | 171 const Instance* ComparisonNode::EvalConstExpr() const { |
149 const Instance* left_val = this->left()->EvalConstExpr(); | 172 const Instance* left_val = this->left()->EvalConstExpr(); |
150 if (left_val == NULL) { | 173 if (left_val == NULL) { |
151 return NULL; | 174 return NULL; |
152 } | 175 } |
153 const Instance* right_val = this->right()->EvalConstExpr(); | 176 const Instance* right_val = this->right()->EvalConstExpr(); |
154 if (right_val == NULL) { | 177 if (right_val == NULL) { |
155 return NULL; | 178 return NULL; |
156 } | 179 } |
157 switch (kind_) { | 180 switch (kind_) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 return false; | 232 return false; |
210 } | 233 } |
211 } | 234 } |
212 | 235 |
213 | 236 |
214 const char* BinaryOpNode::Name() const { | 237 const char* BinaryOpNode::Name() const { |
215 return Token::Str(kind_); | 238 return Token::Str(kind_); |
216 } | 239 } |
217 | 240 |
218 | 241 |
242 bool BinaryOpNode::IsPotentiallyConst() const { | |
243 switch (kind_) { | |
244 case Token::kADD: | |
245 case Token::kSUB: | |
246 case Token::kMUL: | |
247 case Token::kDIV: | |
248 case Token::kMOD: | |
249 case Token::kTRUNCDIV: | |
250 case Token::kBIT_OR: | |
251 case Token::kBIT_XOR: | |
252 case Token::kBIT_AND: | |
253 case Token::kSHL: | |
254 case Token::kSHR: | |
255 case Token::kOR: | |
256 case Token::kAND: | |
257 return this->left()->IsPotentiallyConst() && | |
258 this->right()->IsPotentiallyConst(); | |
259 default: | |
260 UNREACHABLE(); | |
261 return false; | |
262 } | |
263 } | |
264 | |
265 | |
219 const Instance* BinaryOpNode::EvalConstExpr() const { | 266 const Instance* BinaryOpNode::EvalConstExpr() const { |
220 const Instance* left_val = this->left()->EvalConstExpr(); | 267 const Instance* left_val = this->left()->EvalConstExpr(); |
221 if (left_val == NULL) { | 268 if (left_val == NULL) { |
222 return NULL; | 269 return NULL; |
223 } | 270 } |
224 if (!left_val->IsNumber() && !left_val->IsBool()) { | 271 if (!left_val->IsNumber() && !left_val->IsBool()) { |
225 return NULL; | 272 return NULL; |
226 } | 273 } |
227 const Instance* right_val = this->right()->EvalConstExpr(); | 274 const Instance* right_val = this->right()->EvalConstExpr(); |
228 if (right_val == NULL) { | 275 if (right_val == NULL) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 AstNode* new_operand = operand->ApplyUnaryOp(kind); | 323 AstNode* new_operand = operand->ApplyUnaryOp(kind); |
277 if (new_operand != NULL) { | 324 if (new_operand != NULL) { |
278 return new_operand; | 325 return new_operand; |
279 } | 326 } |
280 return new UnaryOpNode(token_pos, kind, operand); | 327 return new UnaryOpNode(token_pos, kind, operand); |
281 } | 328 } |
282 | 329 |
283 | 330 |
284 bool UnaryOpNode::IsKindValid() const { | 331 bool UnaryOpNode::IsKindValid() const { |
285 switch (kind_) { | 332 switch (kind_) { |
286 case Token::kADD: | 333 case Token::kADD: |
Ivan Posva
2013/07/03 20:23:42
Still legal?
hausner
2013/07/03 21:20:54
Historical artifact that I should have removed wit
| |
287 case Token::kNEGATE: | 334 case Token::kNEGATE: |
288 case Token::kNOT: | 335 case Token::kNOT: |
289 case Token::kBIT_NOT: | 336 case Token::kBIT_NOT: |
290 return true; | 337 return true; |
291 default: | 338 default: |
292 return false; | 339 return false; |
293 } | 340 } |
294 } | 341 } |
295 | 342 |
296 | 343 |
344 bool UnaryOpNode::IsPotentiallyConst() const { | |
345 return true; | |
Ivan Posva
2013/07/03 20:23:42
Shouldn't the operand also be potentially const?
hausner
2013/07/03 21:20:54
Actually, yes. Fixed.
| |
346 } | |
347 | |
348 | |
297 const Instance* UnaryOpNode::EvalConstExpr() const { | 349 const Instance* UnaryOpNode::EvalConstExpr() const { |
298 const Instance* val = this->operand()->EvalConstExpr(); | 350 const Instance* val = this->operand()->EvalConstExpr(); |
299 if (val == NULL) { | 351 if (val == NULL) { |
300 return NULL; | 352 return NULL; |
301 } | 353 } |
302 switch (kind_) { | 354 switch (kind_) { |
303 case Token::kADD: | 355 case Token::kADD: |
304 case Token::kNEGATE: | 356 case Token::kNEGATE: |
305 return val->IsNumber() ? val : NULL; | 357 return val->IsNumber() ? val : NULL; |
306 case Token::kNOT: | 358 case Token::kNOT: |
307 return val->IsBool() ? val : NULL; | 359 return val->IsBool() ? val : NULL; |
308 case Token::kBIT_NOT: | 360 case Token::kBIT_NOT: |
309 return val->IsInteger() ? val : NULL; | 361 return val->IsInteger() ? val : NULL; |
310 default: | 362 default: |
311 return NULL; | 363 return NULL; |
312 } | 364 } |
313 } | 365 } |
314 | 366 |
315 | 367 |
368 bool ClosureNode::IsPotentiallyConst() const { | |
369 if (function().IsImplicitStaticClosureFunction()) { | |
370 return true; | |
371 } | |
372 return false; | |
373 } | |
374 | |
375 | |
316 const Instance* ClosureNode::EvalConstExpr() const { | 376 const Instance* ClosureNode::EvalConstExpr() const { |
317 if (function().IsImplicitStaticClosureFunction()) { | 377 if (function().IsImplicitStaticClosureFunction()) { |
318 // Return a value that represents an instance. Only the type is relevant. | 378 // Return a value that represents an instance. Only the type is relevant. |
319 return &Instance::Handle(); | 379 return &Instance::Handle(); |
320 } | 380 } |
321 return NULL; | 381 return NULL; |
322 } | 382 } |
323 | 383 |
324 | 384 |
325 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { | 385 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { |
(...skipping 14 matching lines...) Expand all Loading... | |
340 const char* UnaryOpNode::Name() const { | 400 const char* UnaryOpNode::Name() const { |
341 return Token::Str(kind_); | 401 return Token::Str(kind_); |
342 } | 402 } |
343 | 403 |
344 | 404 |
345 const char* JumpNode::Name() const { | 405 const char* JumpNode::Name() const { |
346 return Token::Str(kind_); | 406 return Token::Str(kind_); |
347 } | 407 } |
348 | 408 |
349 | 409 |
410 bool LoadLocalNode::IsPotentiallyConst() const { | |
411 return true; | |
Ivan Posva
2013/07/03 20:23:42
Really? Thanks for the offline explanation, it wou
hausner
2013/07/03 21:20:54
Added comment and checked that the local variable/
| |
412 } | |
413 | |
414 | |
350 const Instance* LoadLocalNode::EvalConstExpr() const { | 415 const Instance* LoadLocalNode::EvalConstExpr() const { |
351 if (local().IsConst()) { | 416 if (local().IsConst()) { |
352 return local().ConstValue(); | 417 return local().ConstValue(); |
353 } | 418 } |
354 return NULL; | 419 return NULL; |
355 } | 420 } |
356 | 421 |
357 | 422 |
358 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { | 423 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { |
359 if (local().is_final()) { | 424 if (local().is_final()) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 const String& cls_name = String::Handle(cls.Name()); | 505 const String& cls_name = String::Handle(cls.Name()); |
441 const String& func_name = String::Handle(function().name()); | 506 const String& func_name = String::Handle(function().name()); |
442 if (cls_name.Equals(Symbols::NoSuchMethodError()) && | 507 if (cls_name.Equals(Symbols::NoSuchMethodError()) && |
443 func_name.StartsWith(Symbols::ThrowNew())) { | 508 func_name.StartsWith(Symbols::ThrowNew())) { |
444 return this; | 509 return this; |
445 } | 510 } |
446 return NULL; | 511 return NULL; |
447 } | 512 } |
448 | 513 |
449 | 514 |
515 bool StaticGetterNode::IsPotentiallyConst() const { | |
516 const String& getter_name = | |
517 String::Handle(Field::GetterName(this->field_name())); | |
518 const Function& getter_func = | |
519 Function::Handle(this->cls().LookupStaticFunction(getter_name)); | |
520 if (getter_func.IsNull() || !getter_func.is_const()) { | |
521 return false; | |
522 } | |
523 return true; | |
524 } | |
525 | |
526 | |
450 const Instance* StaticGetterNode::EvalConstExpr() const { | 527 const Instance* StaticGetterNode::EvalConstExpr() const { |
451 const String& getter_name = | 528 const String& getter_name = |
452 String::Handle(Field::GetterName(this->field_name())); | 529 String::Handle(Field::GetterName(this->field_name())); |
453 const Function& getter_func = | 530 const Function& getter_func = |
454 Function::Handle(this->cls().LookupStaticFunction(getter_name)); | 531 Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
455 if (getter_func.IsNull() || !getter_func.is_const()) { | 532 if (getter_func.IsNull() || !getter_func.is_const()) { |
456 return NULL; | 533 return NULL; |
457 } | 534 } |
458 const Object& result = Object::Handle( | 535 const Object& result = Object::Handle( |
459 DartEntry::InvokeFunction(getter_func, Object::empty_array())); | 536 DartEntry::InvokeFunction(getter_func, Object::empty_array())); |
460 if (result.IsError() || result.IsNull()) { | 537 if (result.IsError() || result.IsNull()) { |
461 // TODO(turnidge): We could get better error messages by returning | 538 // TODO(turnidge): We could get better error messages by returning |
462 // the Error object directly to the parser. This will involve | 539 // the Error object directly to the parser. This will involve |
463 // replumbing all of the EvalConstExpr methods. | 540 // replumbing all of the EvalConstExpr methods. |
464 return NULL; | 541 return NULL; |
465 } | 542 } |
466 return &Instance::ZoneHandle(Instance::Cast(result).raw()); | 543 return &Instance::ZoneHandle(Instance::Cast(result).raw()); |
467 } | 544 } |
468 | 545 |
469 } // namespace dart | 546 } // namespace dart |
OLD | NEW |