jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Thu Jun 28 01:38:56 2012 -0700 (2012-06-28)
changeset 10 0c3bcd50e361
parent 9 73781c5a59d7
child 11 a350c2cc736a
permissions -rw-r--r--
Implemented break and continue support.
     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     loopDepth_(0)
    95 {
    96 }
    97 
    98 bool
    99 SemanticAnalysis::analyze()
   100 {
   101     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   102         Statement *statement = tree_->statements()->at(i);
   103         statement->accept(this);
   104     }
   105 
   106     return true;
   107 }
   108 
   109 void
   110 SemanticAnalysis::visit(NameProxy *name)
   111 {
   112     name->setType(name->binding()->type());
   113 }
   114 
   115 Type *
   116 SemanticAnalysis::visitForLoad(Expression *expression)
   117 {
   118     expression->accept(this);
   119     if (expression->type() && expression->type()->isArray())
   120         expression->setType(expression->type()->contained());
   121     return expression->type();
   122 }
   123 
   124 Type *
   125 SemanticAnalysis::visitForRef(Expression *expression)
   126 {
   127     expression->accept(this);
   128     return expression->type();
   129 }
   130 
   131 static inline bool
   132 TypeCheck(Type *left, Type *right)
   133 {
   134     if (!left || !right)
   135         return false;
   136 
   137     if (left->isPrimitive()) {
   138         if (!right->isPrimitive())
   139             return false;
   140         return left->primitive() == right->primitive();
   141     }
   142 
   143     return false;
   144 }
   145 
   146 void
   147 SemanticAnalysis::visit(Assignment *node)
   148 {
   149     visitForLoad(node->expression());
   150 
   151     if (node->lvalue()->isIndexExpression()) {
   152         node->lvalue()->accept(this);
   153         node->setType(node->lvalue()->type()->contained());
   154     } else {
   155         NameProxy *proxy = node->lvalue()->toNameProxy();
   156         if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   157             fprintf(stderr, "error\n");
   158             return;
   159         }
   160 
   161         Variable *var = proxy->binding()->toVariable();
   162         node->setType(var->type());
   163     }
   164 
   165     assert(TypeCheck(node->type(), node->expression()->type()));
   166 }
   167 
   168 
   169 void
   170 SemanticAnalysis::visit(BinaryExpression *node)
   171 {
   172     Type *left = visitForLoad(node->left());
   173     Type *right = visitForLoad(node->right());
   174 
   175     if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
   176         // Both sides must be primitive.
   177         if (!left || !right)
   178             return;
   179 
   180         // If either side is a float, the other side must be a float or int.
   181         if (left->isFloat() || right->isFloat()) {
   182             assert(left->isFloat() || left->isInt());
   183             assert(right->isFloat() || right->isInt());
   184             node->setType(left->isFloat() ? left : right);
   185             return;
   186         }
   187     }
   188 
   189     // For now, assert everything else is integer and untagged.
   190     assert(left->isInt() && right->isInt());
   191     assert(!left->tag() && !right->tag());
   192     node->setType(left);
   193 }
   194 
   195 void
   196 SemanticAnalysis::visit(ReturnStatement *node)
   197 {
   198     visitForLoad(node->expression());
   199 
   200     // :TODO: type check
   201 }
   202 
   203 void
   204 SemanticAnalysis::visit(ForStatement *node)
   205 {
   206     loopDepth_++;
   207     if (node->declaration())
   208         node->declaration()->accept(this);
   209     if (node->condition())
   210         visitForLoad(node->condition());
   211     if (node->update())
   212         node->update()->accept(this);
   213     node->body()->accept(this);
   214     loopDepth_--;
   215 }
   216 
   217 void 
   218 SemanticAnalysis::visit(WhileStatement *node)
   219 {
   220     loopDepth_++;
   221     node->condition()->accept(this);
   222     node->body()->accept(this);
   223     loopDepth_--;
   224 }
   225 
   226 void
   227 SemanticAnalysis::visit(BlockStatement *node)
   228 {
   229     for (size_t i = 0; i < node->statements()->length(); i++) {
   230         Statement *statement = node->statements()->at(i);
   231         statement->accept(this);
   232     }
   233 }
   234 
   235 void
   236 SemanticAnalysis::visit(VariableDeclaration *node)
   237 {
   238     Type *type = Type::NewPrimitive(node->tag());
   239     if (!type)
   240         return;
   241 
   242     if (node->postDimensions()) {
   243         if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   244             error();
   245             return;
   246         }
   247 
   248         for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
   249             Expression *expr = node->postDimensions()->at(i);
   250             visitForLoad(expr);
   251 
   252             if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
   253                 typeError(expr, "integer");
   254                 return;
   255             }
   256 
   257             int size = -1;
   258             if (expr->isIntegerLiteral()) {
   259                 size = expr->toIntegerLiteral()->value();
   260                 if (size <= 0) {
   261                     error();
   262                     return;
   263                 }
   264                 if (size >= INT_MAX / sizeof(int)) {
   265                     error();
   266                     return;
   267                 }
   268             }
   269 
   270             type = Type::NewUnsafeArray(type, size);
   271         }
   272     } else {
   273         if (node->initialization()) {
   274             Type *right = visitForLoad(node->initialization());
   275             assert(TypeCheck(type, right));
   276         }
   277     }
   278 
   279     node->variable()->setType(type);
   280 }
   281 
   282 void
   283 SemanticAnalysis::visit(IntegerLiteral *node)
   284 {
   285     Type *type = Type::NewPrimitive(NULL);
   286     node->setType(type);
   287 }
   288 
   289 void
   290 SemanticAnalysis::visit(ExpressionStatement *node)
   291 {
   292     node->expression()->accept(this);
   293 }
   294 
   295 void
   296 SemanticAnalysis::visit(FunctionStatement *node)
   297 {
   298     node->body()->accept(this);
   299 }
   300 
   301 void
   302 SemanticAnalysis::visit(CallExpression *node)
   303 {
   304 }
   305 
   306 void
   307 SemanticAnalysis::visit(IfStatement *node)
   308 {
   309     visitForLoad(node->condition());
   310     node->ifTrue()->accept(this);
   311     if (node->ifFalse())
   312         node->ifFalse()->accept(this);
   313 }
   314 
   315 void
   316 SemanticAnalysis::visit(IndexExpression *node)
   317 {
   318     Type *left = visitForRef(node->left());
   319     Type *right = visitForLoad(node->right());
   320 
   321     if (!right || !right->isInt()) {
   322         typeError(node->right(), "integer");
   323         return;
   324     }
   325     if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
   326         typeError(node->left(), "array");
   327         return;
   328     }
   329     node->setType(left);
   330 }
   331 
   332 void
   333 SemanticAnalysis::visit(EnumStatement *node)
   334 {
   335     // :TODO: test "enum Float { ..."
   336     Name *tag = node->name();
   337 
   338     Type *type = Type::NewPrimitive(tag);
   339     if (!type)
   340         return;
   341 
   342     int value = 0;
   343     for (size_t i = 0; i < node->entries()->size(); i++) {
   344         EnumStatement::Entry &entry = node->entries()->at(i);
   345 
   346         BoxedPrimitive box = BoxedPrimitive::Int(value);
   347         if (entry.expr) {
   348             entry.expr->accept(this);
   349             if (!EvaluateForConstant(entry.expr, &box))
   350                 fprintf(stderr, "expected constant integer expression\n");
   351 
   352             assert(box.type() == PrimitiveType_Int32);
   353             value = box.toInt();
   354         }
   355 
   356         entry.name->set(type, box);
   357         value++;
   358     }
   359 }
   360 
   361 void
   362 SemanticAnalysis::visit(FloatLiteral *node)
   363 {
   364     Type *type = Type::NewPrimitive(PrimitiveType_Float);
   365     if (!type)
   366         return;
   367 
   368     node->setType(type);
   369 }
   370 
   371 void
   372 SemanticAnalysis::visit(BreakStatement *node)
   373 {
   374     assert(loopDepth_ > 0);
   375 }
   376 
   377 void
   378 SemanticAnalysis::visit(ContinueStatement *node)
   379 {
   380     assert(loopDepth_ > 0);
   381 }