jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Thu Jun 28 00:26:55 2012 -0700 (2012-06-28)
changeset 8 069d207a8f2a
parent 7 0478c27ba82c
child 9 73781c5a59d7
permissions -rw-r--r--
Added support for bitwise operators.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #include "SemanticAnalysis.h"
    19 #include "Types.h"
    20 
    21 using namespace jc;
    22 
    23 static inline bool
    24 IsPrimitiveType(Type *type, PrimitiveType primitive)
    25 {
    26     if (!type)
    27         return false;
    28 
    29     if (!type->isPrimitive())
    30         return false;
    31 
    32     return primitive == type->primitive();
    33 }
    34 
    35 static inline bool
    36 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
    37                         BoxedPrimitive *out)
    38 {
    39     switch (kind) {
    40       case TOK_PLUS:
    41         *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
    42         return true;
    43 
    44       case TOK_SHL:
    45         *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
    46         return true;
    47     }
    48 
    49     return true;
    50 }
    51 
    52 static bool
    53 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
    54 {
    55     switch (expression->kind()) {
    56       case AstNode::kBinaryExpression:
    57       {
    58         BoxedPrimitive left;
    59         BoxedPrimitive right;
    60         BinaryExpression *b = expression->toBinaryExpression();
    61         if (!EvaluateForConstant(b->left(), &left) ||
    62             !EvaluateForConstant(b->right(), &right))
    63         {
    64             return false;
    65         }
    66         return EvaluateBinaryOperation(b->token(), left, right, out);
    67       }
    68 
    69       case AstNode::kNameProxy:
    70       {
    71         NameProxy *proxy = expression->toNameProxy();
    72         if (proxy->binding()->kind() != BoundName::CONSTANT)
    73             return false;
    74 
    75         NamedConstant *c = proxy->binding()->toNamedConstant();
    76         if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
    77             return false;
    78 
    79         *out = c->value();
    80         return true;
    81       }
    82 
    83       case AstNode::kIntegerLiteral:
    84         *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
    85         return true;
    86 
    87       default:
    88         return false;
    89     }
    90 }
    91 
    92 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
    93   : tree_(tree)
    94 {
    95 }
    96 
    97 bool
    98 SemanticAnalysis::analyze()
    99 {
   100     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   101         Statement *statement = tree_->statements()->at(i);
   102         statement->accept(this);
   103     }
   104 
   105     return true;
   106 }
   107 
   108 void
   109 SemanticAnalysis::visit(NameProxy *name)
   110 {
   111     name->setType(name->binding()->type());
   112 }
   113 
   114 Type *
   115 SemanticAnalysis::visitForLoad(Expression *expression)
   116 {
   117     expression->accept(this);
   118     if (expression->type() && expression->type()->isArray())
   119         expression->setType(expression->type()->contained());
   120     return expression->type();
   121 }
   122 
   123 Type *
   124 SemanticAnalysis::visitForRef(Expression *expression)
   125 {
   126     expression->accept(this);
   127     return expression->type();
   128 }
   129 
   130 static inline bool
   131 TypeCheck(Type *left, Type *right)
   132 {
   133     if (!left || !right)
   134         return false;
   135 
   136     if (left->isPrimitive()) {
   137         if (!right->isPrimitive())
   138             return false;
   139         return left->primitive() == right->primitive();
   140     }
   141 
   142     return false;
   143 }
   144 
   145 void
   146 SemanticAnalysis::visit(Assignment *node)
   147 {
   148     visitForLoad(node->expression());
   149 
   150     if (node->lvalue()->isIndexExpression()) {
   151         node->lvalue()->accept(this);
   152         node->setType(node->lvalue()->type()->contained());
   153     } else {
   154         NameProxy *proxy = node->lvalue()->toNameProxy();
   155         if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   156             fprintf(stderr, "error\n");
   157             return;
   158         }
   159 
   160         Variable *var = proxy->binding()->toVariable();
   161         node->setType(var->type());
   162     }
   163 
   164     assert(TypeCheck(node->type(), node->expression()->type()));
   165 }
   166 
   167 
   168 void
   169 SemanticAnalysis::visit(BinaryExpression *node)
   170 {
   171     Type *left = visitForLoad(node->left());
   172     Type *right = visitForLoad(node->right());
   173 
   174     if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
   175         // Both sides must be primitive.
   176         if (!left || !right)
   177             return;
   178 
   179         // If either side is a float, the other side must be a float or int.
   180         if (left->isFloat() || right->isFloat()) {
   181             assert(left->isFloat() || left->isInt());
   182             assert(right->isFloat() || right->isInt());
   183             node->setType(left->isFloat() ? left : right);
   184             return;
   185         }
   186     }
   187 
   188     // For now, assert everything else is integer and untagged.
   189     assert(left->isInt() && right->isInt());
   190     assert(!left->tag() && !right->tag());
   191     node->setType(left);
   192 }
   193 
   194 void
   195 SemanticAnalysis::visit(ReturnStatement *node)
   196 {
   197     visitForLoad(node->expression());
   198 
   199     // :TODO: type check
   200 }
   201 
   202 void
   203 SemanticAnalysis::visit(ForStatement *node)
   204 {
   205     if (node->declaration())
   206         node->declaration()->accept(this);
   207     if (node->condition())
   208         visitForLoad(node->condition());
   209     if (node->update())
   210         node->update()->accept(this);
   211     node->body()->accept(this);
   212 }
   213 
   214 void
   215 SemanticAnalysis::visit(BlockStatement *node)
   216 {
   217     for (size_t i = 0; i < node->statements()->length(); i++) {
   218         Statement *statement = node->statements()->at(i);
   219         statement->accept(this);
   220     }
   221 }
   222 
   223 void
   224 SemanticAnalysis::visit(VariableDeclaration *node)
   225 {
   226     Type *type = Type::NewPrimitive(node->tag());
   227     if (!type)
   228         return;
   229 
   230     if (node->postDimensions()) {
   231         if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   232             error();
   233             return;
   234         }
   235 
   236         for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
   237             Expression *expr = node->postDimensions()->at(i);
   238             visitForLoad(expr);
   239 
   240             if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
   241                 typeError(expr, "integer");
   242                 return;
   243             }
   244 
   245             int size = -1;
   246             if (expr->isIntegerLiteral()) {
   247                 size = expr->toIntegerLiteral()->value();
   248                 if (size <= 0) {
   249                     error();
   250                     return;
   251                 }
   252                 if (size >= INT_MAX / sizeof(int)) {
   253                     error();
   254                     return;
   255                 }
   256             }
   257 
   258             type = Type::NewUnsafeArray(type, size);
   259         }
   260     } else {
   261         Type *right = visitForLoad(node->initialization());
   262         assert(TypeCheck(type, right));
   263     }
   264 
   265     node->variable()->setType(type);
   266 }
   267 
   268 void
   269 SemanticAnalysis::visit(IntegerLiteral *node)
   270 {
   271     Type *type = Type::NewPrimitive(NULL);
   272     node->setType(type);
   273 }
   274 
   275 void
   276 SemanticAnalysis::visit(ExpressionStatement *node)
   277 {
   278     node->expression()->accept(this);
   279 }
   280 
   281 void
   282 SemanticAnalysis::visit(FunctionStatement *node)
   283 {
   284     node->body()->accept(this);
   285 }
   286 
   287 void
   288 SemanticAnalysis::visit(CallExpression *node)
   289 {
   290 }
   291 
   292 void
   293 SemanticAnalysis::visit(IfStatement *node)
   294 {
   295 }
   296 
   297 void
   298 SemanticAnalysis::visit(IndexExpression *node)
   299 {
   300     Type *left = visitForRef(node->left());
   301     Type *right = visitForLoad(node->right());
   302 
   303     if (!right || !right->isInt()) {
   304         typeError(node->right(), "integer");
   305         return;
   306     }
   307     if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
   308         typeError(node->left(), "array");
   309         return;
   310     }
   311     node->setType(left);
   312 }
   313 
   314 void
   315 SemanticAnalysis::visit(EnumStatement *node)
   316 {
   317     // :TODO: test "enum Float { ..."
   318     Name *tag = node->name();
   319 
   320     Type *type = Type::NewPrimitive(tag);
   321     if (!type)
   322         return;
   323 
   324     int value = 0;
   325     for (size_t i = 0; i < node->entries()->size(); i++) {
   326         EnumStatement::Entry &entry = node->entries()->at(i);
   327 
   328         BoxedPrimitive box = BoxedPrimitive::Int(value);
   329         if (entry.expr) {
   330             entry.expr->accept(this);
   331             if (!EvaluateForConstant(entry.expr, &box))
   332                 fprintf(stderr, "expected constant integer expression\n");
   333 
   334             assert(box.type() == PrimitiveType_Int32);
   335             value = box.toInt();
   336         }
   337 
   338         entry.name->set(type, box);
   339         value++;
   340     }
   341 }
   342 
   343 void
   344 SemanticAnalysis::visit(FloatLiteral *node)
   345 {
   346     Type *type = Type::NewPrimitive(PrimitiveType_Float);
   347     if (!type)
   348         return;
   349 
   350     node->setType(type);
   351 }