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