jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jun 25 02:57:28 2012 -0700 (2012-06-25)
changeset 0 c455ebb9a5dc
child 2 46fc53b8fd2f
permissions -rw-r--r--
Initial import of prototype.
     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 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
    24   : tree_(tree)
    25 {
    26 }
    27 
    28 bool
    29 SemanticAnalysis::analyze()
    30 {
    31     for (size_t i = 0; i < tree_->statements()->length(); i++) {
    32         Statement *statement = tree_->statements()->at(i);
    33         statement->accept(this);
    34     }
    35 
    36     return true;
    37 }
    38 
    39 void
    40 SemanticAnalysis::visit(NameProxy *name)
    41 {
    42     name->setType(name->binding()->type());
    43 }
    44 
    45 static inline bool
    46 IsPrimitiveType(Type *type, PrimitiveType primitive)
    47 {
    48     if (!type)
    49         return false;
    50 
    51     if (!type->isPrimitive())
    52         return false;
    53 
    54     return primitive == type->primitive();
    55 }
    56 
    57 void
    58 SemanticAnalysis::visit(Assignment *node)
    59 {
    60     node->expression()->accept(this);
    61 
    62     if (node->lvalue()->isIndexExpression()) {
    63         node->lvalue()->accept(this);
    64       
    65         node->setType(node->lvalue()->type());
    66     } else {
    67         NameProxy *proxy = node->lvalue()->toNameProxy();
    68         if (!proxy->binding()->kind() == BoundName::VARIABLE) {
    69             fprintf(stderr, "error\n");
    70             return;
    71         }
    72 
    73         Variable *var = proxy->binding()->toVariable();
    74         node->setType(var->type());
    75     }
    76 }
    77 
    78 void
    79 SemanticAnalysis::visit(BinaryExpression *node)
    80 {
    81 }
    82 
    83 void
    84 SemanticAnalysis::visit(ReturnStatement *node)
    85 {
    86     node->expression()->accept(this);
    87 
    88     // :TODO: type check
    89 }
    90 
    91 void
    92 SemanticAnalysis::visit(ForStatement *node)
    93 {
    94     if (node->declaration())
    95         node->declaration()->accept(this);
    96     if (node->condition())
    97         node->condition()->accept(this);
    98     if (node->update())
    99         node->update()->accept(this);
   100     node->body()->accept(this);
   101 }
   102 
   103 void
   104 SemanticAnalysis::visit(BlockStatement *node)
   105 {
   106     for (size_t i = 0; i < node->statements()->length(); i++) {
   107         Statement *statement = node->statements()->at(i);
   108         statement->accept(this);
   109     }
   110 }
   111 
   112 void
   113 SemanticAnalysis::visit(VariableDeclaration *node)
   114 {
   115     Tag *tag = NULL;
   116 
   117     Type *type = Type::NewPrimitive(tag);
   118     if (!type)
   119         return;
   120 
   121     if (node->postDimensions()) {
   122         if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   123             error();
   124             return;
   125         }
   126 
   127         for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
   128             Expression *expr = node->postDimensions()->at(i);
   129             expr->accept(this);
   130 
   131             if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
   132                 typeError(expr, "integer");
   133                 return;
   134             }
   135 
   136             int size = -1;
   137             if (expr->isIntegerLiteralExpression()) {
   138                 size = expr->toIntegerLiteralExpression()->value();
   139                 if (size <= 0) {
   140                     error();
   141                     return;
   142                 }
   143                 if (size >= INT_MAX / sizeof(int)) {
   144                     error();
   145                     return;
   146                 }
   147             }
   148 
   149             type = Type::NewUnsafeArray(type, size);
   150         }
   151     }
   152 
   153     node->variable()->setType(type);
   154 }
   155 
   156 void
   157 SemanticAnalysis::visit(IntegerLiteralExpression *node)
   158 {
   159     Type *type = Type::NewPrimitive(NULL);
   160     node->setType(type);
   161 }
   162 
   163 void
   164 SemanticAnalysis::visit(ExpressionStatement *node)
   165 {
   166     node->expression()->accept(this);
   167 }
   168 
   169 void
   170 SemanticAnalysis::visit(FunctionStatement *node)
   171 {
   172     node->body()->accept(this);
   173 }
   174 
   175 void
   176 SemanticAnalysis::visit(CallExpression *node)
   177 {
   178 }
   179 
   180 void
   181 SemanticAnalysis::visit(IfStatement *node)
   182 {
   183 }
   184 
   185 void
   186 SemanticAnalysis::visit(IndexExpression *node)
   187 {
   188     node->left()->accept(this);
   189     node->right()->accept(this);
   190 
   191     if (!node->right()->type(), PrimitiveType_Int32) {
   192         typeError(node->right(), "integer");
   193         return;
   194     }
   195     if (!node->left()->type() || !node->left()->type()->isArray()) {
   196         typeError(node->left(), "array");
   197         return;
   198     }
   199     node->setType(node->left()->type()->contained());
   200 }