src/compiler/ConstantEvaluator.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 16:28:34 2013 -0800 (2013-01-01)
changeset 252 1dee2330aa78
parent 213 a9b8d24967d6
child 263 ba85a47ee414
permissions -rw-r--r--
Fix linux/mac support.
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@213
    21
#include "../Heap-inl.h"
dvander@213
    22
#include "../Handles-inl.h"
dvander@212
    23
dvander@212
    24
using namespace ke;
dvander@212
    25
dvander@212
    26
static inline bool
dvander@212
    27
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@212
    28
                        BoxedPrimitive *out)
dvander@212
    29
{
dvander@212
    30
    switch (kind) {
dvander@212
    31
      case TOK_PLUS:
dvander@212
    32
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@212
    33
        return true;
dvander@212
    34
dvander@212
    35
      case TOK_SHL:
dvander@212
    36
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@212
    37
        return true;
dvander@212
    38
dvander@212
    39
      default:
dvander@212
    40
        return false;
dvander@212
    41
    }
dvander@212
    42
}
dvander@212
    43
dvander@212
    44
static inline bool
dvander@212
    45
EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
dvander@212
    46
{
dvander@212
    47
  switch (kind) {
dvander@212
    48
    case TOK_MINUS:
dvander@212
    49
      *out = BoxedPrimitive::Int(-inner.toInt());
dvander@212
    50
      return true;
dvander@212
    51
dvander@212
    52
    default:
dvander@212
    53
      return false;
dvander@212
    54
  }
dvander@212
    55
}
dvander@212
    56
dvander@212
    57
bool
dvander@212
    58
ke::EvaluateForConstant(Expression *expr, BoxedPrimitive *out)
dvander@212
    59
{
dvander@212
    60
    switch (expr->kind()) {
dvander@212
    61
      case AstNode::kBinaryExpression:
dvander@212
    62
      {
dvander@212
    63
        BoxedPrimitive left;
dvander@212
    64
        BoxedPrimitive right;
dvander@212
    65
        BinaryExpression *b = expr->toBinaryExpression();
dvander@212
    66
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@212
    67
            !EvaluateForConstant(b->right(), &right))
dvander@212
    68
        {
dvander@212
    69
            return false;
dvander@212
    70
        }
dvander@212
    71
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@212
    72
      }
dvander@212
    73
dvander@212
    74
      case AstNode::kUnaryExpression:
dvander@212
    75
      {
dvander@212
    76
        BoxedPrimitive inner;
dvander@212
    77
        UnaryExpression *u = expr->toUnaryExpression();
dvander@212
    78
        if (!EvaluateForConstant(u->expression(), &inner))
dvander@212
    79
            return false;
dvander@212
    80
        return EvaluateUnaryOperation(u->token(), inner, out);
dvander@212
    81
      }
dvander@212
    82
dvander@212
    83
      case AstNode::kBooleanLiteral:
dvander@212
    84
        *out = BoxedPrimitive::Int(expr->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0);
dvander@212
    85
        return true;
dvander@212
    86
dvander@212
    87
      case AstNode::kIntegerLiteral:
dvander@212
    88
        *out = BoxedPrimitive::Int(expr->toIntegerLiteral()->value());
dvander@212
    89
        return true;
dvander@212
    90
dvander@212
    91
      default:
dvander@212
    92
        return false;
dvander@212
    93
    }
dvander@212
    94
}