src/compiler/ConstantEvaluator.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 14:53:23 2012 -0800 (2012-11-18)
changeset 212 443d24cfdf2d
parent 211 6c1cc50c4808
child 213 a9b8d24967d6
permissions -rw-r--r--
Added array support back.
dvander@212
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@212
     2
 *
dvander@212
     3
 * Copyright (C) 2012 David Anderson
dvander@212
     4
 *
dvander@212
     5
 * This file is part of SourcePawn.
dvander@212
     6
 *
dvander@212
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@212
     8
 * the terms of the GNU General Public License as published by the Free
dvander@212
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@212
    10
 * any later version.
dvander@212
    11
 * 
dvander@212
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@212
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@212
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@212
    15
 *
dvander@212
    16
 * You should have received a copy of the GNU General Public License along with
dvander@212
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@212
    18
 */
dvander@212
    19
#include "AST.h"
dvander@212
    20
#include "ConstantEvaluator.h"
dvander@212
    21
dvander@212
    22
using namespace ke;
dvander@212
    23
dvander@212
    24
static inline bool
dvander@212
    25
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@212
    26
                        BoxedPrimitive *out)
dvander@212
    27
{
dvander@212
    28
    switch (kind) {
dvander@212
    29
      case TOK_PLUS:
dvander@212
    30
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@212
    31
        return true;
dvander@212
    32
dvander@212
    33
      case TOK_SHL:
dvander@212
    34
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@212
    35
        return true;
dvander@212
    36
dvander@212
    37
      default:
dvander@212
    38
        return false;
dvander@212
    39
    }
dvander@212
    40
}
dvander@212
    41
dvander@212
    42
static inline bool
dvander@212
    43
EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
dvander@212
    44
{
dvander@212
    45
  switch (kind) {
dvander@212
    46
    case TOK_MINUS:
dvander@212
    47
      *out = BoxedPrimitive::Int(-inner.toInt());
dvander@212
    48
      return true;
dvander@212
    49
dvander@212
    50
    default:
dvander@212
    51
      return false;
dvander@212
    52
  }
dvander@212
    53
}
dvander@212
    54
dvander@212
    55
bool
dvander@212
    56
ke::EvaluateForConstant(Expression *expr, BoxedPrimitive *out)
dvander@212
    57
{
dvander@212
    58
    switch (expr->kind()) {
dvander@212
    59
      case AstNode::kBinaryExpression:
dvander@212
    60
      {
dvander@212
    61
        BoxedPrimitive left;
dvander@212
    62
        BoxedPrimitive right;
dvander@212
    63
        BinaryExpression *b = expr->toBinaryExpression();
dvander@212
    64
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@212
    65
            !EvaluateForConstant(b->right(), &right))
dvander@212
    66
        {
dvander@212
    67
            return false;
dvander@212
    68
        }
dvander@212
    69
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@212
    70
      }
dvander@212
    71
dvander@212
    72
      case AstNode::kUnaryExpression:
dvander@212
    73
      {
dvander@212
    74
        BoxedPrimitive inner;
dvander@212
    75
        UnaryExpression *u = expr->toUnaryExpression();
dvander@212
    76
        if (!EvaluateForConstant(u->expression(), &inner))
dvander@212
    77
            return false;
dvander@212
    78
        return EvaluateUnaryOperation(u->token(), inner, out);
dvander@212
    79
      }
dvander@212
    80
dvander@212
    81
      case AstNode::kBooleanLiteral:
dvander@212
    82
        *out = BoxedPrimitive::Int(expr->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0);
dvander@212
    83
        return true;
dvander@212
    84
dvander@212
    85
      case AstNode::kIntegerLiteral:
dvander@212
    86
        *out = BoxedPrimitive::Int(expr->toIntegerLiteral()->value());
dvander@212
    87
        return true;
dvander@212
    88
dvander@212
    89
      default:
dvander@212
    90
        return false;
dvander@212
    91
    }
dvander@212
    92
}