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