| 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 | 
|---|