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: | |
287 case Token::kNEGATE: | 333 case Token::kNEGATE: |
288 case Token::kNOT: | 334 case Token::kNOT: |
289 case Token::kBIT_NOT: | 335 case Token::kBIT_NOT: |
290 return true; | 336 return true; |
291 default: | 337 default: |
292 return false; | 338 return false; |
293 } | 339 } |
294 } | 340 } |
295 | 341 |
296 | 342 |
| 343 bool UnaryOpNode::IsPotentiallyConst() const { |
| 344 return this->operand()->IsPotentiallyConst(); |
| 345 } |
| 346 |
| 347 |
297 const Instance* UnaryOpNode::EvalConstExpr() const { | 348 const Instance* UnaryOpNode::EvalConstExpr() const { |
298 const Instance* val = this->operand()->EvalConstExpr(); | 349 const Instance* val = this->operand()->EvalConstExpr(); |
299 if (val == NULL) { | 350 if (val == NULL) { |
300 return NULL; | 351 return NULL; |
301 } | 352 } |
302 switch (kind_) { | 353 switch (kind_) { |
303 case Token::kADD: | |
304 case Token::kNEGATE: | 354 case Token::kNEGATE: |
305 return val->IsNumber() ? val : NULL; | 355 return val->IsNumber() ? val : NULL; |
306 case Token::kNOT: | 356 case Token::kNOT: |
307 return val->IsBool() ? val : NULL; | 357 return val->IsBool() ? val : NULL; |
308 case Token::kBIT_NOT: | 358 case Token::kBIT_NOT: |
309 return val->IsInteger() ? val : NULL; | 359 return val->IsInteger() ? val : NULL; |
310 default: | 360 default: |
311 return NULL; | 361 return NULL; |
312 } | 362 } |
313 } | 363 } |
314 | 364 |
315 | 365 |
| 366 bool ClosureNode::IsPotentiallyConst() const { |
| 367 if (function().IsImplicitStaticClosureFunction()) { |
| 368 return true; |
| 369 } |
| 370 return false; |
| 371 } |
| 372 |
| 373 |
316 const Instance* ClosureNode::EvalConstExpr() const { | 374 const Instance* ClosureNode::EvalConstExpr() const { |
317 if (function().IsImplicitStaticClosureFunction()) { | 375 if (function().IsImplicitStaticClosureFunction()) { |
318 // Return a value that represents an instance. Only the type is relevant. | 376 // Return a value that represents an instance. Only the type is relevant. |
319 return &Instance::Handle(); | 377 return &Instance::Handle(); |
320 } | 378 } |
321 return NULL; | 379 return NULL; |
322 } | 380 } |
323 | 381 |
324 | 382 |
325 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { | 383 AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) { |
(...skipping 14 matching lines...) Expand all Loading... |
340 const char* UnaryOpNode::Name() const { | 398 const char* UnaryOpNode::Name() const { |
341 return Token::Str(kind_); | 399 return Token::Str(kind_); |
342 } | 400 } |
343 | 401 |
344 | 402 |
345 const char* JumpNode::Name() const { | 403 const char* JumpNode::Name() const { |
346 return Token::Str(kind_); | 404 return Token::Str(kind_); |
347 } | 405 } |
348 | 406 |
349 | 407 |
| 408 bool LoadLocalNode::IsPotentiallyConst() const { |
| 409 // Parameters of const constructors are implicitly final and can be |
| 410 // used in initializer expressions. |
| 411 // We can't check here whether the local variable is indeed a parameter, |
| 412 // but this code is executed before any other local variables are |
| 413 // added to the scope. |
| 414 return local().is_final(); |
| 415 } |
| 416 |
| 417 |
350 const Instance* LoadLocalNode::EvalConstExpr() const { | 418 const Instance* LoadLocalNode::EvalConstExpr() const { |
351 if (local().IsConst()) { | 419 if (local().IsConst()) { |
352 return local().ConstValue(); | 420 return local().ConstValue(); |
353 } | 421 } |
354 return NULL; | 422 return NULL; |
355 } | 423 } |
356 | 424 |
357 | 425 |
358 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { | 426 AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) { |
359 if (local().is_final()) { | 427 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()); | 508 const String& cls_name = String::Handle(cls.Name()); |
441 const String& func_name = String::Handle(function().name()); | 509 const String& func_name = String::Handle(function().name()); |
442 if (cls_name.Equals(Symbols::NoSuchMethodError()) && | 510 if (cls_name.Equals(Symbols::NoSuchMethodError()) && |
443 func_name.StartsWith(Symbols::ThrowNew())) { | 511 func_name.StartsWith(Symbols::ThrowNew())) { |
444 return this; | 512 return this; |
445 } | 513 } |
446 return NULL; | 514 return NULL; |
447 } | 515 } |
448 | 516 |
449 | 517 |
| 518 bool StaticGetterNode::IsPotentiallyConst() const { |
| 519 const String& getter_name = |
| 520 String::Handle(Field::GetterName(this->field_name())); |
| 521 const Function& getter_func = |
| 522 Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
| 523 if (getter_func.IsNull() || !getter_func.is_const()) { |
| 524 return false; |
| 525 } |
| 526 return true; |
| 527 } |
| 528 |
| 529 |
450 const Instance* StaticGetterNode::EvalConstExpr() const { | 530 const Instance* StaticGetterNode::EvalConstExpr() const { |
451 const String& getter_name = | 531 const String& getter_name = |
452 String::Handle(Field::GetterName(this->field_name())); | 532 String::Handle(Field::GetterName(this->field_name())); |
453 const Function& getter_func = | 533 const Function& getter_func = |
454 Function::Handle(this->cls().LookupStaticFunction(getter_name)); | 534 Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
455 if (getter_func.IsNull() || !getter_func.is_const()) { | 535 if (getter_func.IsNull() || !getter_func.is_const()) { |
456 return NULL; | 536 return NULL; |
457 } | 537 } |
458 const Object& result = Object::Handle( | 538 const Object& result = Object::Handle( |
459 DartEntry::InvokeFunction(getter_func, Object::empty_array())); | 539 DartEntry::InvokeFunction(getter_func, Object::empty_array())); |
460 if (result.IsError() || result.IsNull()) { | 540 if (result.IsError() || result.IsNull()) { |
461 // TODO(turnidge): We could get better error messages by returning | 541 // TODO(turnidge): We could get better error messages by returning |
462 // the Error object directly to the parser. This will involve | 542 // the Error object directly to the parser. This will involve |
463 // replumbing all of the EvalConstExpr methods. | 543 // replumbing all of the EvalConstExpr methods. |
464 return NULL; | 544 return NULL; |
465 } | 545 } |
466 return &Instance::ZoneHandle(Instance::Cast(result).raw()); | 546 return &Instance::ZoneHandle(Instance::Cast(result).raw()); |
467 } | 547 } |
468 | 548 |
469 } // namespace dart | 549 } // namespace dart |
OLD | NEW |