Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(421)

Side by Side Diff: runtime/vm/ast.cc

Issue 18649003: Partial solution to analyze potentially constant expressions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/parser.cc » ('j') | tests/corelib/corelib.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698