Index: runtime/vm/ast.cc |
=================================================================== |
--- runtime/vm/ast.cc (revision 24703) |
+++ runtime/vm/ast.cc (working copy) |
@@ -110,6 +110,11 @@ |
} |
+bool LiteralNode::IsPotentiallyConst() const { |
+ return true; |
+} |
+ |
+ |
// TODO(srdjan): Add code for logical negation. |
AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) { |
if (unary_op_kind == Token::kNEGATE) { |
@@ -145,6 +150,24 @@ |
} |
+bool ComparisonNode::IsPotentiallyConst() const { |
+ switch (kind_) { |
+ case Token::kLT: |
+ case Token::kGT: |
+ case Token::kLTE: |
+ case Token::kGTE: |
+ case Token::kEQ: |
+ case Token::kNE: |
+ case Token::kEQ_STRICT: |
+ case Token::kNE_STRICT: |
+ return this->left()->IsPotentiallyConst() && |
+ this->right()->IsPotentiallyConst(); |
+ default: |
+ return false; |
+ } |
+} |
+ |
+ |
const Instance* ComparisonNode::EvalConstExpr() const { |
const Instance* left_val = this->left()->EvalConstExpr(); |
if (left_val == NULL) { |
@@ -216,6 +239,30 @@ |
} |
+bool BinaryOpNode::IsPotentiallyConst() const { |
+ switch (kind_) { |
+ case Token::kADD: |
+ case Token::kSUB: |
+ case Token::kMUL: |
+ case Token::kDIV: |
+ case Token::kMOD: |
+ case Token::kTRUNCDIV: |
+ case Token::kBIT_OR: |
+ case Token::kBIT_XOR: |
+ case Token::kBIT_AND: |
+ case Token::kSHL: |
+ case Token::kSHR: |
+ case Token::kOR: |
+ case Token::kAND: |
+ return this->left()->IsPotentiallyConst() && |
+ this->right()->IsPotentiallyConst(); |
+ default: |
+ UNREACHABLE(); |
+ return false; |
+ } |
+} |
+ |
+ |
const Instance* BinaryOpNode::EvalConstExpr() const { |
const Instance* left_val = this->left()->EvalConstExpr(); |
if (left_val == NULL) { |
@@ -283,7 +330,6 @@ |
bool UnaryOpNode::IsKindValid() const { |
switch (kind_) { |
- case Token::kADD: |
case Token::kNEGATE: |
case Token::kNOT: |
case Token::kBIT_NOT: |
@@ -294,13 +340,17 @@ |
} |
+bool UnaryOpNode::IsPotentiallyConst() const { |
+ return this->operand()->IsPotentiallyConst(); |
+} |
+ |
+ |
const Instance* UnaryOpNode::EvalConstExpr() const { |
const Instance* val = this->operand()->EvalConstExpr(); |
if (val == NULL) { |
return NULL; |
} |
switch (kind_) { |
- case Token::kADD: |
case Token::kNEGATE: |
return val->IsNumber() ? val : NULL; |
case Token::kNOT: |
@@ -313,6 +363,14 @@ |
} |
+bool ClosureNode::IsPotentiallyConst() const { |
+ if (function().IsImplicitStaticClosureFunction()) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
const Instance* ClosureNode::EvalConstExpr() const { |
if (function().IsImplicitStaticClosureFunction()) { |
// Return a value that represents an instance. Only the type is relevant. |
@@ -347,6 +405,16 @@ |
} |
+bool LoadLocalNode::IsPotentiallyConst() const { |
+ // Parameters of const constructors are implicitly final and can be |
+ // used in initializer expressions. |
+ // We can't check here whether the local variable is indeed a parameter, |
+ // but this code is executed before any other local variables are |
+ // added to the scope. |
+ return local().is_final(); |
+} |
+ |
+ |
const Instance* LoadLocalNode::EvalConstExpr() const { |
if (local().IsConst()) { |
return local().ConstValue(); |
@@ -447,6 +515,18 @@ |
} |
+bool StaticGetterNode::IsPotentiallyConst() const { |
+ const String& getter_name = |
+ String::Handle(Field::GetterName(this->field_name())); |
+ const Function& getter_func = |
+ Function::Handle(this->cls().LookupStaticFunction(getter_name)); |
+ if (getter_func.IsNull() || !getter_func.is_const()) { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+ |
const Instance* StaticGetterNode::EvalConstExpr() const { |
const String& getter_name = |
String::Handle(Field::GetterName(this->field_name())); |