diff -r 6c1cc50c4808 -r 443d24cfdf2d src/compiler/ConstantEvaluator.cpp --- a/src/compiler/ConstantEvaluator.cpp Sat Nov 17 23:13:39 2012 -0800 +++ b/src/compiler/ConstantEvaluator.cpp Sun Nov 18 14:53:23 2012 -0800 @@ -0,0 +1,92 @@ +/* vim: set ts=4 sw=4 tw=99 et: + * + * Copyright (C) 2012 David Anderson + * + * This file is part of SourcePawn. + * + * SourcePawn is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * SourcePawn. If not, see http://www.gnu.org/licenses/. + */ +#include "AST.h" +#include "ConstantEvaluator.h" + +using namespace ke; + +static inline bool +EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right, + BoxedPrimitive *out) +{ + switch (kind) { + case TOK_PLUS: + *out = BoxedPrimitive::Int(left.toInt() + right.toInt()); + return true; + + case TOK_SHL: + *out = BoxedPrimitive::Int(left.toInt() << right.toInt()); + return true; + + default: + return false; + } +} + +static inline bool +EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out) +{ + switch (kind) { + case TOK_MINUS: + *out = BoxedPrimitive::Int(-inner.toInt()); + return true; + + default: + return false; + } +} + +bool +ke::EvaluateForConstant(Expression *expr, BoxedPrimitive *out) +{ + switch (expr->kind()) { + case AstNode::kBinaryExpression: + { + BoxedPrimitive left; + BoxedPrimitive right; + BinaryExpression *b = expr->toBinaryExpression(); + if (!EvaluateForConstant(b->left(), &left) || + !EvaluateForConstant(b->right(), &right)) + { + return false; + } + return EvaluateBinaryOperation(b->token(), left, right, out); + } + + case AstNode::kUnaryExpression: + { + BoxedPrimitive inner; + UnaryExpression *u = expr->toUnaryExpression(); + if (!EvaluateForConstant(u->expression(), &inner)) + return false; + return EvaluateUnaryOperation(u->token(), inner, out); + } + + case AstNode::kBooleanLiteral: + *out = BoxedPrimitive::Int(expr->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0); + return true; + + case AstNode::kIntegerLiteral: + *out = BoxedPrimitive::Int(expr->toIntegerLiteral()->value()); + return true; + + default: + return false; + } +}