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