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