jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Fri Jun 29 19:35:17 2012 -0700 (2012-06-29)
changeset 11 a350c2cc736a
parent 10 0c3bcd50e361
child 12 75e385f68b7e
permissions -rw-r--r--
Imported garbage collection allocator and converted Type to a gc object.
     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 #include "Zone.h"
    21 #include "TypeManager.h"
    22 
    23 using namespace jc;
    24 
    25 static inline bool
    26 IsPrimitiveType(Type *type, PrimitiveType primitive)
    27 {
    28     if (!type)
    29         return false;
    30 
    31     if (!type->isPrimitive())
    32         return false;
    33 
    34     return primitive == type->primitive();
    35 }
    36 
    37 static inline bool
    38 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
    39                         BoxedPrimitive *out)
    40 {
    41     switch (kind) {
    42       case TOK_PLUS:
    43         *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
    44         return true;
    45 
    46       case TOK_SHL:
    47         *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
    48         return true;
    49     }
    50 
    51     return true;
    52 }
    53 
    54 static bool
    55 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
    56 {
    57     switch (expression->kind()) {
    58       case AstNode::kBinaryExpression:
    59       {
    60         BoxedPrimitive left;
    61         BoxedPrimitive right;
    62         BinaryExpression *b = expression->toBinaryExpression();
    63         if (!EvaluateForConstant(b->left(), &left) ||
    64             !EvaluateForConstant(b->right(), &right))
    65         {
    66             return false;
    67         }
    68         return EvaluateBinaryOperation(b->token(), left, right, out);
    69       }
    70 
    71       case AstNode::kNameProxy:
    72       {
    73         NameProxy *proxy = expression->toNameProxy();
    74         if (proxy->binding()->kind() != BoundName::CONSTANT)
    75             return false;
    76 
    77         NamedConstant *c = proxy->binding()->toNamedConstant();
    78         if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
    79             return false;
    80 
    81         *out = c->value();
    82         return true;
    83       }
    84 
    85       case AstNode::kIntegerLiteral:
    86         *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
    87         return true;
    88 
    89       default:
    90         return false;
    91     }
    92 }
    93 
    94 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
    95   : tree_(tree),
    96     loopDepth_(0)
    97 {
    98 }
    99 
   100 bool
   101 SemanticAnalysis::analyze()
   102 {
   103     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   104         Statement *statement = tree_->statements()->at(i);
   105         statement->accept(this);
   106     }
   107 
   108     return true;
   109 }
   110 
   111 void
   112 SemanticAnalysis::visit(NameProxy *name)
   113 {
   114     name->setType(name->binding()->type());
   115 }
   116 
   117 Type *
   118 SemanticAnalysis::visitForLoad(Expression *expression)
   119 {
   120     expression->accept(this);
   121     if (expression->type() && expression->type()->isArray())
   122         expression->setType(expression->type()->contained());
   123     return expression->type();
   124 }
   125 
   126 Type *
   127 SemanticAnalysis::visitForRef(Expression *expression)
   128 {
   129     expression->accept(this);
   130     return expression->type();
   131 }
   132 
   133 static inline bool
   134 TypeCheck(Type *left, Type *right)
   135 {
   136     if (!left || !right)
   137         return false;
   138 
   139     if (left->isPrimitive()) {
   140         if (!right->isPrimitive())
   141             return false;
   142         return left->primitive() == right->primitive();
   143     }
   144 
   145     return false;
   146 }
   147 
   148 void
   149 SemanticAnalysis::visit(Assignment *node)
   150 {
   151     visitForLoad(node->expression());
   152 
   153     if (node->lvalue()->isIndexExpression()) {
   154         node->lvalue()->accept(this);
   155         node->setType(node->lvalue()->type()->contained());
   156     } else {
   157         NameProxy *proxy = node->lvalue()->toNameProxy();
   158         if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   159             fprintf(stderr, "error\n");
   160             return;
   161         }
   162 
   163         Variable *var = proxy->binding()->toVariable();
   164         node->setType(var->type());
   165     }
   166 
   167     assert(TypeCheck(node->type(), node->expression()->type()));
   168 }
   169 
   170 
   171 void
   172 SemanticAnalysis::visit(BinaryExpression *node)
   173 {
   174     Type *left = visitForLoad(node->left());
   175     Type *right = visitForLoad(node->right());
   176 
   177     if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
   178         // Both sides must be primitive.
   179         if (!left || !right)
   180             return;
   181 
   182         // If either side is a float, the other side must be a float or int.
   183         if (left->isFloat() || right->isFloat()) {
   184             assert(left->isFloat() || left->isInt());
   185             assert(right->isFloat() || right->isInt());
   186             node->setType(left->isFloat() ? left : right);
   187             return;
   188         }
   189     }
   190 
   191     // For now, assert everything else is integer and untagged.
   192     assert(left->isInt() && right->isInt());
   193     assert(!left->tag() && !right->tag());
   194     node->setType(left);
   195 }
   196 
   197 void
   198 SemanticAnalysis::visit(ReturnStatement *node)
   199 {
   200     visitForLoad(node->expression());
   201 
   202     // :TODO: type check
   203 }
   204 
   205 void
   206 SemanticAnalysis::visit(ForStatement *node)
   207 {
   208     loopDepth_++;
   209     if (node->declaration())
   210         node->declaration()->accept(this);
   211     if (node->condition())
   212         visitForLoad(node->condition());
   213     if (node->update())
   214         node->update()->accept(this);
   215     node->body()->accept(this);
   216     loopDepth_--;
   217 }
   218 
   219 void 
   220 SemanticAnalysis::visit(WhileStatement *node)
   221 {
   222     loopDepth_++;
   223     node->condition()->accept(this);
   224     node->body()->accept(this);
   225     loopDepth_--;
   226 }
   227 
   228 void
   229 SemanticAnalysis::visit(BlockStatement *node)
   230 {
   231     for (size_t i = 0; i < node->statements()->length(); i++) {
   232         Statement *statement = node->statements()->at(i);
   233         statement->accept(this);
   234     }
   235 }
   236 
   237 void
   238 SemanticAnalysis::visit(VariableDeclaration *node)
   239 {
   240     Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
   241     if (!type)
   242         return;
   243 
   244     if (node->postDimensions()) {
   245         if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   246             error();
   247             return;
   248         }
   249 
   250         for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
   251             Expression *expr = node->postDimensions()->at(i);
   252             visitForLoad(expr);
   253 
   254             if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
   255                 typeError(expr, "integer");
   256                 return;
   257             }
   258 
   259             int size = -1;
   260             if (expr->isIntegerLiteral()) {
   261                 size = expr->toIntegerLiteral()->value();
   262                 if (size <= 0) {
   263                     error();
   264                     return;
   265                 }
   266                 if (size >= INT_MAX / sizeof(int)) {
   267                     error();
   268                     return;
   269                 }
   270             }
   271 
   272             type = ZONE()->types()->unsafeArray(type, size);
   273         }
   274     } else {
   275         if (node->initialization()) {
   276             Type *right = visitForLoad(node->initialization());
   277             assert(TypeCheck(type, right));
   278         }
   279     }
   280 
   281     node->variable()->setType(type);
   282 }
   283 
   284 void
   285 SemanticAnalysis::visit(IntegerLiteral *node)
   286 {
   287     node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
   288 }
   289 
   290 void
   291 SemanticAnalysis::visit(ExpressionStatement *node)
   292 {
   293     node->expression()->accept(this);
   294 }
   295 
   296 void
   297 SemanticAnalysis::visit(FunctionStatement *node)
   298 {
   299     node->body()->accept(this);
   300 }
   301 
   302 void
   303 SemanticAnalysis::visit(CallExpression *node)
   304 {
   305 }
   306 
   307 void
   308 SemanticAnalysis::visit(IfStatement *node)
   309 {
   310     visitForLoad(node->condition());
   311     node->ifTrue()->accept(this);
   312     if (node->ifFalse())
   313         node->ifFalse()->accept(this);
   314 }
   315 
   316 void
   317 SemanticAnalysis::visit(IndexExpression *node)
   318 {
   319     Type *left = visitForRef(node->left());
   320     Type *right = visitForLoad(node->right());
   321 
   322     if (!right || !right->isInt()) {
   323         typeError(node->right(), "integer");
   324         return;
   325     }
   326     if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
   327         typeError(node->left(), "array");
   328         return;
   329     }
   330     node->setType(left);
   331 }
   332 
   333 void
   334 SemanticAnalysis::visit(EnumStatement *node)
   335 {
   336     // :TODO: test "enum Float { ..."
   337     Name *tag = node->name();
   338 
   339     Type *type = ZONE()->types()->getPrimitiveForTag(tag);
   340     if (!type)
   341         return;
   342 
   343     int value = 0;
   344     for (size_t i = 0; i < node->entries()->size(); i++) {
   345         EnumStatement::Entry &entry = node->entries()->at(i);
   346 
   347         BoxedPrimitive box = BoxedPrimitive::Int(value);
   348         if (entry.expr) {
   349             entry.expr->accept(this);
   350             if (!EvaluateForConstant(entry.expr, &box))
   351                 fprintf(stderr, "expected constant integer expression\n");
   352 
   353             assert(box.type() == PrimitiveType_Int32);
   354             value = box.toInt();
   355         }
   356 
   357         entry.name->set(type, box);
   358         value++;
   359     }
   360 }
   361 
   362 void
   363 SemanticAnalysis::visit(FloatLiteral *node)
   364 {
   365     Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
   366     if (!type)
   367         return;
   368 
   369     node->setType(type);
   370 }
   371 
   372 void
   373 SemanticAnalysis::visit(BreakStatement *node)
   374 {
   375     assert(loopDepth_ > 0);
   376 }
   377 
   378 void
   379 SemanticAnalysis::visit(ContinueStatement *node)
   380 {
   381     assert(loopDepth_ > 0);
   382 }