Chromium Code Reviews| 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 |