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