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