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.
dvander@0
     1
/*
dvander@0
     2
 * Copyright (C) 2012 David Anderson
dvander@0
     3
 *
dvander@0
     4
 * This file is part of JITCraft.
dvander@0
     5
 *
dvander@0
     6
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     7
 * the terms of the GNU General Public License as published by the Free
dvander@0
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
     9
 * any later version.
dvander@0
    10
 * 
dvander@0
    11
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    14
 *
dvander@0
    15
 * You should have received a copy of the GNU General Public License along with
dvander@0
    16
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    17
 */
dvander@0
    18
#include "SemanticAnalysis.h"
dvander@0
    19
#include "Types.h"
dvander@0
    20
dvander@0
    21
using namespace jc;
dvander@0
    22
dvander@0
    23
SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
dvander@0
    24
  : tree_(tree)
dvander@0
    25
{
dvander@0
    26
}
dvander@0
    27
dvander@0
    28
bool
dvander@0
    29
SemanticAnalysis::analyze()
dvander@0
    30
{
dvander@0
    31
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@0
    32
        Statement *statement = tree_->statements()->at(i);
dvander@0
    33
        statement->accept(this);
dvander@0
    34
    }
dvander@0
    35
dvander@0
    36
    return true;
dvander@0
    37
}
dvander@0
    38
dvander@0
    39
void
dvander@0
    40
SemanticAnalysis::visit(NameProxy *name)
dvander@0
    41
{
dvander@0
    42
    name->setType(name->binding()->type());
dvander@0
    43
}
dvander@0
    44
dvander@0
    45
static inline bool
dvander@0
    46
IsPrimitiveType(Type *type, PrimitiveType primitive)
dvander@0
    47
{
dvander@0
    48
    if (!type)
dvander@0
    49
        return false;
dvander@0
    50
dvander@0
    51
    if (!type->isPrimitive())
dvander@0
    52
        return false;
dvander@0
    53
dvander@0
    54
    return primitive == type->primitive();
dvander@0
    55
}
dvander@0
    56
dvander@0
    57
void
dvander@0
    58
SemanticAnalysis::visit(Assignment *node)
dvander@0
    59
{
dvander@0
    60
    node->expression()->accept(this);
dvander@0
    61
dvander@0
    62
    if (node->lvalue()->isIndexExpression()) {
dvander@0
    63
        node->lvalue()->accept(this);
dvander@0
    64
      
dvander@0
    65
        node->setType(node->lvalue()->type());
dvander@0
    66
    } else {
dvander@0
    67
        NameProxy *proxy = node->lvalue()->toNameProxy();
dvander@0
    68
        if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@0
    69
            fprintf(stderr, "error\n");
dvander@0
    70
            return;
dvander@0
    71
        }
dvander@0
    72
dvander@0
    73
        Variable *var = proxy->binding()->toVariable();
dvander@0
    74
        node->setType(var->type());
dvander@0
    75
    }
dvander@0
    76
}
dvander@0
    77
dvander@0
    78
void
dvander@0
    79
SemanticAnalysis::visit(BinaryExpression *node)
dvander@0
    80
{
dvander@0
    81
}
dvander@0
    82
dvander@0
    83
void
dvander@0
    84
SemanticAnalysis::visit(ReturnStatement *node)
dvander@0
    85
{
dvander@0
    86
    node->expression()->accept(this);
dvander@0
    87
dvander@0
    88
    // :TODO: type check
dvander@0
    89
}
dvander@0
    90
dvander@0
    91
void
dvander@0
    92
SemanticAnalysis::visit(ForStatement *node)
dvander@0
    93
{
dvander@0
    94
    if (node->declaration())
dvander@0
    95
        node->declaration()->accept(this);
dvander@0
    96
    if (node->condition())
dvander@0
    97
        node->condition()->accept(this);
dvander@0
    98
    if (node->update())
dvander@0
    99
        node->update()->accept(this);
dvander@0
   100
    node->body()->accept(this);
dvander@0
   101
}
dvander@0
   102
dvander@0
   103
void
dvander@0
   104
SemanticAnalysis::visit(BlockStatement *node)
dvander@0
   105
{
dvander@0
   106
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@0
   107
        Statement *statement = node->statements()->at(i);
dvander@0
   108
        statement->accept(this);
dvander@0
   109
    }
dvander@0
   110
}
dvander@0
   111
dvander@0
   112
void
dvander@0
   113
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@0
   114
{
dvander@0
   115
    Tag *tag = NULL;
dvander@0
   116
dvander@0
   117
    Type *type = Type::NewPrimitive(tag);
dvander@0
   118
    if (!type)
dvander@0
   119
        return;
dvander@0
   120
dvander@0
   121
    if (node->postDimensions()) {
dvander@0
   122
        if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@0
   123
            error();
dvander@0
   124
            return;
dvander@0
   125
        }
dvander@0
   126
dvander@0
   127
        for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
dvander@0
   128
            Expression *expr = node->postDimensions()->at(i);
dvander@0
   129
            expr->accept(this);
dvander@0
   130
dvander@0
   131
            if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
dvander@0
   132
                typeError(expr, "integer");
dvander@0
   133
                return;
dvander@0
   134
            }
dvander@0
   135
dvander@0
   136
            int size = -1;
dvander@0
   137
            if (expr->isIntegerLiteralExpression()) {
dvander@0
   138
                size = expr->toIntegerLiteralExpression()->value();
dvander@0
   139
                if (size <= 0) {
dvander@0
   140
                    error();
dvander@0
   141
                    return;
dvander@0
   142
                }
dvander@0
   143
                if (size >= INT_MAX / sizeof(int)) {
dvander@0
   144
                    error();
dvander@0
   145
                    return;
dvander@0
   146
                }
dvander@0
   147
            }
dvander@0
   148
dvander@0
   149
            type = Type::NewUnsafeArray(type, size);
dvander@0
   150
        }
dvander@0
   151
    }
dvander@0
   152
dvander@0
   153
    node->variable()->setType(type);
dvander@0
   154
}
dvander@0
   155
dvander@0
   156
void
dvander@0
   157
SemanticAnalysis::visit(IntegerLiteralExpression *node)
dvander@0
   158
{
dvander@0
   159
    Type *type = Type::NewPrimitive(NULL);
dvander@0
   160
    node->setType(type);
dvander@0
   161
}
dvander@0
   162
dvander@0
   163
void
dvander@0
   164
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@0
   165
{
dvander@0
   166
    node->expression()->accept(this);
dvander@0
   167
}
dvander@0
   168
dvander@0
   169
void
dvander@0
   170
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   171
{
dvander@0
   172
    node->body()->accept(this);
dvander@0
   173
}
dvander@0
   174
dvander@0
   175
void
dvander@0
   176
SemanticAnalysis::visit(CallExpression *node)
dvander@0
   177
{
dvander@0
   178
}
dvander@0
   179
dvander@0
   180
void
dvander@0
   181
SemanticAnalysis::visit(IfStatement *node)
dvander@0
   182
{
dvander@0
   183
}
dvander@0
   184
dvander@0
   185
void
dvander@0
   186
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
   187
{
dvander@0
   188
    node->left()->accept(this);
dvander@0
   189
    node->right()->accept(this);
dvander@0
   190
dvander@0
   191
    if (!node->right()->type(), PrimitiveType_Int32) {
dvander@0
   192
        typeError(node->right(), "integer");
dvander@0
   193
        return;
dvander@0
   194
    }
dvander@0
   195
    if (!node->left()->type() || !node->left()->type()->isArray()) {
dvander@0
   196
        typeError(node->left(), "array");
dvander@0
   197
        return;
dvander@0
   198
    }
dvander@0
   199
    node->setType(node->left()->type()->contained());
dvander@0
   200
}