| 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()));
|
|
|