jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 02 01:24:57 2012 -0700 (2012-07-02)
changeset 25 23e8b3d8e4e6
parent 23 8a31742781c1
child 28 a9665857cfd5
permissions -rw-r--r--
Scanning, parsing, and static analysis now report errors properly.
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@11
    20
#include "Zone.h"
dvander@11
    21
#include "TypeManager.h"
dvander@12
    22
#include "Scopes.h"
dvander@0
    23
dvander@0
    24
using namespace jc;
dvander@0
    25
dvander@2
    26
static inline bool
dvander@2
    27
IsPrimitiveType(Type *type, PrimitiveType primitive)
dvander@2
    28
{
dvander@2
    29
    if (!type)
dvander@2
    30
        return false;
dvander@2
    31
dvander@2
    32
    if (!type->isPrimitive())
dvander@2
    33
        return false;
dvander@2
    34
dvander@2
    35
    return primitive == type->primitive();
dvander@2
    36
}
dvander@2
    37
dvander@2
    38
static inline bool
dvander@2
    39
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@2
    40
                        BoxedPrimitive *out)
dvander@2
    41
{
dvander@2
    42
    switch (kind) {
dvander@2
    43
      case TOK_PLUS:
dvander@2
    44
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@2
    45
        return true;
dvander@2
    46
dvander@2
    47
      case TOK_SHL:
dvander@2
    48
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@2
    49
        return true;
dvander@2
    50
    }
dvander@2
    51
dvander@2
    52
    return true;
dvander@2
    53
}
dvander@2
    54
dvander@2
    55
static bool
dvander@2
    56
EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
dvander@2
    57
{
dvander@2
    58
    switch (expression->kind()) {
dvander@2
    59
      case AstNode::kBinaryExpression:
dvander@2
    60
      {
dvander@2
    61
        BoxedPrimitive left;
dvander@2
    62
        BoxedPrimitive right;
dvander@2
    63
        BinaryExpression *b = expression->toBinaryExpression();
dvander@2
    64
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@2
    65
            !EvaluateForConstant(b->right(), &right))
dvander@2
    66
        {
dvander@2
    67
            return false;
dvander@2
    68
        }
dvander@2
    69
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@2
    70
      }
dvander@2
    71
dvander@2
    72
      case AstNode::kNameProxy:
dvander@2
    73
      {
dvander@2
    74
        NameProxy *proxy = expression->toNameProxy();
dvander@2
    75
        if (proxy->binding()->kind() != BoundName::CONSTANT)
dvander@2
    76
            return false;
dvander@2
    77
dvander@2
    78
        NamedConstant *c = proxy->binding()->toNamedConstant();
dvander@2
    79
        if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
dvander@2
    80
            return false;
dvander@2
    81
dvander@2
    82
        *out = c->value();
dvander@2
    83
        return true;
dvander@2
    84
      }
dvander@2
    85
dvander@4
    86
      case AstNode::kIntegerLiteral:
dvander@4
    87
        *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
dvander@2
    88
        return true;
dvander@2
    89
dvander@2
    90
      default:
dvander@2
    91
        return false;
dvander@2
    92
    }
dvander@2
    93
}
dvander@2
    94
dvander@25
    95
SemanticAnalysis::SemanticAnalysis(CompileContext &cc, ParseTree *tree)
dvander@25
    96
  : cc_(cc),
dvander@25
    97
    tree_(tree),
dvander@12
    98
    loopDepth_(0),
dvander@12
    99
    scope_(NULL)
dvander@0
   100
{
dvander@0
   101
}
dvander@0
   102
dvander@0
   103
bool
dvander@0
   104
SemanticAnalysis::analyze()
dvander@0
   105
{
dvander@25
   106
    if (cc_.failures())
dvander@25
   107
        return false;
dvander@25
   108
dvander@25
   109
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@25
   110
        Statement *statement = tree_->statements()->at(i);
dvander@25
   111
        if (statement->isFunctionStatement()) {
dvander@25
   112
            FunctionStatement *funstmt = statement->toFunctionStatement();
dvander@25
   113
            if (!preanalyze(funstmt))
dvander@25
   114
                return false;
dvander@25
   115
        }
dvander@25
   116
    }
dvander@25
   117
dvander@0
   118
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@0
   119
        Statement *statement = tree_->statements()->at(i);
dvander@0
   120
        statement->accept(this);
dvander@0
   121
    }
dvander@0
   122
dvander@25
   123
    return !cc_.failures();
dvander@0
   124
}
dvander@0
   125
dvander@25
   126
Type *
dvander@25
   127
SemanticAnalysis::visitAndApplyType(Expression *expression)
dvander@0
   128
{
dvander@25
   129
    expression->accept(this);
dvander@25
   130
    return expression->type();
dvander@0
   131
}
dvander@0
   132
dvander@7
   133
Type *
dvander@7
   134
SemanticAnalysis::visitForLoad(Expression *expression)
dvander@7
   135
{
dvander@25
   136
    // :TODO: use Local
dvander@25
   137
    Type *type = visitAndApplyType(expression);
dvander@25
   138
    if (!type)
dvander@21
   139
        return NULL;
dvander@21
   140
dvander@21
   141
    if (type->isReference()) {
dvander@21
   142
        expression->setType(type->contained());
dvander@21
   143
    } else if (expression->isIndexExpression()) {
dvander@21
   144
        if (type->isArray())
dvander@14
   145
            expression->setType(type->contained());
dvander@14
   146
    }
dvander@25
   147
dvander@7
   148
    return expression->type();
dvander@7
   149
}
dvander@7
   150
dvander@7
   151
Type *
dvander@7
   152
SemanticAnalysis::visitForRef(Expression *expression)
dvander@7
   153
{
dvander@7
   154
    expression->accept(this);
dvander@7
   155
    return expression->type();
dvander@7
   156
}
dvander@7
   157
dvander@25
   158
static inline const char *
dvander@25
   159
GetTypeName(Type *type)
dvander@4
   160
{
dvander@25
   161
    if (type->isArray())
dvander@25
   162
        return "array";
dvander@25
   163
    if (type->isFunction())
dvander@25
   164
        return "function";
dvander@25
   165
    if (type->isReference())
dvander@25
   166
        type = type->contained();
dvander@25
   167
    if (type->tag())
dvander@25
   168
        return type->tag();
dvander@25
   169
    return "int";
dvander@4
   170
}
dvander@4
   171
dvander@25
   172
void
dvander@25
   173
SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Type *type)
dvander@21
   174
{
dvander@25
   175
    const char *op = TokenNames[token];
dvander@25
   176
    const char *name = GetTypeName(type);
dvander@21
   177
dvander@25
   178
    cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
dvander@21
   179
}
dvander@21
   180
dvander@25
   181
void
dvander@25
   182
SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Type *left, Type *right)
dvander@22
   183
{
dvander@25
   184
    const char *op = TokenNames[token];
dvander@25
   185
    const char *leftName = GetTypeName(left);
dvander@25
   186
    const char *rightName = GetTypeName(right);
dvander@22
   187
dvander@25
   188
    cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
dvander@25
   189
}
dvander@25
   190
dvander@25
   191
Type *
dvander@25
   192
SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Type *left, Type *right)
dvander@25
   193
{
dvander@22
   194
    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
dvander@22
   195
        (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
dvander@22
   196
    {
dvander@22
   197
        // If either side is a float, the other side must be a float or int.
dvander@22
   198
        if (left->isFloat() || right->isFloat()) {
dvander@25
   199
            Type *floatType = left->isFloat() ? left : right;
dvander@25
   200
            Type *other = left->isFloat() ? right : left;
dvander@25
   201
            if (other->isFloat() || (other->isInt32() && !other->tag()))
dvander@25
   202
                return other;
dvander@22
   203
        }
dvander@22
   204
    }
dvander@22
   205
dvander@25
   206
    if ((!left->isInt32() || left->tag()) ||
dvander@25
   207
        (!right->isInt32() || right->tag()))
dvander@25
   208
    {
dvander@25
   209
        binaryTypeError(node, token, left, right);
dvander@25
   210
        return NULL;
dvander@25
   211
    }
dvander@25
   212
dvander@22
   213
    return left;
dvander@22
   214
}
dvander@22
   215
dvander@25
   216
bool
dvander@25
   217
SemanticAnalysis::canTest(AstNode *node, Type *type)
dvander@25
   218
{
dvander@25
   219
    if (type->isArray()) {
dvander@25
   220
        cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
dvander@25
   221
        return false;
dvander@25
   222
    }
dvander@25
   223
    return true;
dvander@25
   224
}
dvander@25
   225
dvander@23
   226
Type *
dvander@23
   227
SemanticAnalysis::visitForLValue(Expression *expression)
dvander@23
   228
{
dvander@23
   229
    if (expression->isIndexExpression()) {
dvander@25
   230
        Type *type = visitAndApplyType(expression);
dvander@25
   231
        if (!type)
dvander@23
   232
            return NULL;
dvander@25
   233
dvander@25
   234
        return type->contained();
dvander@23
   235
    }
dvander@23
   236
dvander@23
   237
    if (!expression->isNameProxy()) {
dvander@25
   238
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   239
        return NULL;
dvander@23
   240
    }
dvander@23
   241
dvander@23
   242
    NameProxy *proxy = expression->toNameProxy();
dvander@23
   243
    if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@25
   244
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   245
        return NULL;
dvander@23
   246
    }
dvander@23
   247
dvander@23
   248
    Variable *var = proxy->binding()->toVariable();
dvander@23
   249
    if (!var->type())
dvander@23
   250
        return NULL;
dvander@23
   251
dvander@23
   252
    if  (var->type()->isReference())
dvander@23
   253
        return var->type()->contained();
dvander@23
   254
    return var->type();
dvander@23
   255
}
dvander@23
   256
dvander@0
   257
void
dvander@25
   258
SemanticAnalysis::visit(NameProxy *name)
dvander@25
   259
{
dvander@25
   260
    name->setType(name->binding()->type());
dvander@25
   261
}
dvander@25
   262
dvander@25
   263
void
dvander@0
   264
SemanticAnalysis::visit(Assignment *node)
dvander@0
   265
{
dvander@25
   266
    Type *exprType = visitForLoad(node->expression());
dvander@25
   267
    if (!exprType)
dvander@25
   268
        return ;
dvander@0
   269
dvander@23
   270
    // :TODO: use Local
dvander@23
   271
    Type *type = visitForLValue(node->lvalue());
dvander@23
   272
    if (!type)
dvander@23
   273
        return;
dvander@4
   274
dvander@25
   275
    if (node->token() != TOK_ASSIGN) {
dvander@25
   276
        if (!typeCheckBinary(node, node->token(), type, exprType))
dvander@25
   277
            return;
dvander@25
   278
    }
dvander@22
   279
dvander@25
   280
    if (!typeCheckAssignment(node, exprType, type, true))
dvander@25
   281
        return;
dvander@25
   282
dvander@25
   283
    node->setType(type);
dvander@0
   284
}
dvander@0
   285
dvander@0
   286
void
dvander@23
   287
SemanticAnalysis::visit(IncDecExpression *node)
dvander@23
   288
{
dvander@23
   289
    // :TODO: use Local
dvander@23
   290
    Type *type = visitForLValue(node->expression());
dvander@23
   291
    if (!type)
dvander@23
   292
        return;
dvander@23
   293
dvander@23
   294
    assert(!type->isReference());
dvander@25
   295
dvander@25
   296
    if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
dvander@25
   297
        unaryTypeError(node, node->token(), type);
dvander@23
   298
        return;
dvander@23
   299
    }
dvander@23
   300
dvander@23
   301
    node->setType(type);
dvander@23
   302
}
dvander@23
   303
dvander@23
   304
void
dvander@0
   305
SemanticAnalysis::visit(BinaryExpression *node)
dvander@0
   306
{
dvander@22
   307
    // :TODO: use Local
dvander@7
   308
    Type *left = visitForLoad(node->left());
dvander@7
   309
    Type *right = visitForLoad(node->right());
dvander@25
   310
    if (!left || !right)
dvander@25
   311
        return;
dvander@4
   312
dvander@25
   313
    Type *result = typeCheckBinary(node, node->token(), left, right);
dvander@25
   314
    if (!result)
dvander@25
   315
        return;
dvander@25
   316
dvander@22
   317
    node->setType(result);
dvander@0
   318
}
dvander@0
   319
dvander@0
   320
void
dvander@0
   321
SemanticAnalysis::visit(ReturnStatement *node)
dvander@0
   322
{
dvander@25
   323
    Type *type = visitForLoad(node->expression());
dvander@25
   324
    if (!type)
dvander@25
   325
        return;
dvander@0
   326
dvander@25
   327
    if (!typeCheckAssignment(node, type, function_->returnType(), true))
dvander@25
   328
        return;
dvander@0
   329
}
dvander@0
   330
dvander@0
   331
void
dvander@0
   332
SemanticAnalysis::visit(ForStatement *node)
dvander@0
   333
{
dvander@10
   334
    loopDepth_++;
dvander@12
   335
    if (node->scope())
dvander@12
   336
        scope_ = node->scope();
dvander@25
   337
dvander@22
   338
    if (node->initialization())
dvander@22
   339
        node->initialization()->accept(this);
dvander@25
   340
dvander@25
   341
    if (node->condition()) {
dvander@25
   342
        Type *type = visitForLoad(node->condition());
dvander@25
   343
        if (!type || !canTest(node->condition(), type)) {
dvander@25
   344
            loopDepth_--;
dvander@25
   345
            return;
dvander@25
   346
        }
dvander@25
   347
    }
dvander@25
   348
dvander@0
   349
    if (node->update())
dvander@0
   350
        node->update()->accept(this);
dvander@25
   351
dvander@0
   352
    node->body()->accept(this);
dvander@25
   353
dvander@12
   354
    if (node->scope())
dvander@12
   355
        scope_ = scope_->enclosing();
dvander@10
   356
    loopDepth_--;
dvander@0
   357
}
dvander@0
   358
dvander@9
   359
void 
dvander@9
   360
SemanticAnalysis::visit(WhileStatement *node)
dvander@9
   361
{
dvander@10
   362
    loopDepth_++;
dvander@25
   363
dvander@25
   364
    Type *type = visitForLoad(node->condition());
dvander@25
   365
    if (!type || !canTest(node->condition(), type)) {
dvander@25
   366
        loopDepth_--;
dvander@25
   367
        return;
dvander@25
   368
    }
dvander@25
   369
dvander@9
   370
    node->body()->accept(this);
dvander@10
   371
    loopDepth_--;
dvander@9
   372
}
dvander@9
   373
dvander@0
   374
void
dvander@0
   375
SemanticAnalysis::visit(BlockStatement *node)
dvander@0
   376
{
dvander@12
   377
    if (node->scope())
dvander@12
   378
        scope_ = node->scope();
dvander@0
   379
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@0
   380
        Statement *statement = node->statements()->at(i);
dvander@0
   381
        statement->accept(this);
dvander@0
   382
    }
dvander@12
   383
    if (node->scope())
dvander@12
   384
        scope_ = scope_->enclosing();
dvander@0
   385
}
dvander@0
   386
dvander@0
   387
void
dvander@0
   388
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@0
   389
{
dvander@14
   390
    // :TODO: use locals
dvander@11
   391
    Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
dvander@0
   392
    if (!type)
dvander@0
   393
        return;
dvander@0
   394
dvander@0
   395
    if (node->postDimensions()) {
dvander@21
   396
        Type *init = NULL;
dvander@21
   397
        if (node->initialization()) {
dvander@25
   398
            if ((init = visitAndApplyType(node->initialization())) == NULL)
dvander@21
   399
                return;
dvander@21
   400
        }
dvander@21
   401
dvander@0
   402
        if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@25
   403
            cc_.reportError(node->pos(), Message_MaximumArrayDepth);
dvander@0
   404
            return;
dvander@0
   405
        }
dvander@0
   406
dvander@21
   407
        // If we have an initializer, make sure it's the same type.
dvander@25
   408
        if (init && node->postDimensions()->size() != init->levels()) {
dvander@25
   409
            cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
dvander@25
   410
            return;
dvander@21
   411
        }
dvander@21
   412
dvander@21
   413
        Type *check = init;
dvander@0
   414
        for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
dvander@0
   415
            Expression *expr = node->postDimensions()->at(i);
dvander@25
   416
            int size = -1;
dvander@0
   417
dvander@25
   418
            if (expr) {
dvander@25
   419
                Type *exprType = visitForLoad(expr);
dvander@25
   420
                if (!exprType)
dvander@25
   421
                    return;
dvander@0
   422
dvander@25
   423
                if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
dvander@25
   424
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   425
                    return;
dvander@0
   426
                }
dvander@25
   427
dvander@25
   428
                BoxedPrimitive box;
dvander@25
   429
                if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@25
   430
                    size = box.toInt();
dvander@25
   431
                    if (size <= 0) {
dvander@25
   432
                        cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@25
   433
                        return;
dvander@25
   434
                    }
dvander@25
   435
                    if (size >= INT_MAX / sizeof(int)) {
dvander@25
   436
                        cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
dvander@25
   437
                        return;
dvander@25
   438
                    }
dvander@25
   439
dvander@25
   440
                    if (check) {
dvander@25
   441
                        if (check->elements() == -1) {
dvander@25
   442
                            cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   443
                            return;
dvander@25
   444
                        }
dvander@25
   445
dvander@25
   446
                        if (check->isCharArray()) {
dvander@25
   447
                            if (check->elements() > size) {
dvander@25
   448
                                cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   449
                                return;
dvander@25
   450
                            }
dvander@25
   451
                        } else if (check->elements() != size) {
dvander@25
   452
                            cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
dvander@25
   453
                            return;
dvander@25
   454
                        }
dvander@25
   455
                    }
dvander@25
   456
                } else {
dvander@25
   457
                    if (init) {
dvander@25
   458
                        cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
dvander@25
   459
                        return;
dvander@25
   460
                    }
dvander@25
   461
dvander@25
   462
                    // here until we get dynamic array support.
dvander@25
   463
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   464
                    return;
dvander@0
   465
                }
dvander@21
   466
            } else {
dvander@25
   467
                // Infer the size from the initializer.
dvander@25
   468
                if (!init) {
dvander@25
   469
                    cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
dvander@25
   470
                    return;
dvander@25
   471
                }
dvander@25
   472
                if (init->elements() == -1) {
dvander@25
   473
                    cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   474
                    return;
dvander@25
   475
                }
dvander@25
   476
                size = init->elements();
dvander@0
   477
            }
dvander@0
   478
dvander@11
   479
            type = ZONE()->types()->unsafeArray(type, size);
dvander@25
   480
            if (!type)
dvander@25
   481
                return;
dvander@21
   482
dvander@21
   483
            if (check)
dvander@21
   484
                check = check->contained();
dvander@0
   485
        }
dvander@12
   486
dvander@12
   487
        // Right now, any array is allowed on the LIFO heap. In case the
dvander@12
   488
        // runtime actually decides to use the LIFO heap, we must reserve
dvander@12
   489
        // a slot so we can unwind the heap when the current scope leaves.
dvander@12
   490
        scope_->setUsesLifoHeap();
dvander@8
   491
    } else {
dvander@10
   492
        if (node->initialization()) {
dvander@10
   493
            Type *right = visitForLoad(node->initialization());
dvander@25
   494
            if (!right)
dvander@25
   495
                return;
dvander@25
   496
            if (!typeCheckAssignment(node, type, right, true))
dvander@25
   497
                return;
dvander@10
   498
        }
dvander@21
   499
        if (type->primitive() == PrimitiveType_Char) {
dvander@25
   500
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@21
   501
            return;
dvander@21
   502
        }
dvander@0
   503
    }
dvander@0
   504
dvander@0
   505
    node->variable()->setType(type);
dvander@0
   506
}
dvander@0
   507
dvander@0
   508
void
dvander@4
   509
SemanticAnalysis::visit(IntegerLiteral *node)
dvander@0
   510
{
dvander@11
   511
    node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
dvander@0
   512
}
dvander@0
   513
dvander@0
   514
void
dvander@0
   515
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@0
   516
{
dvander@0
   517
    node->expression()->accept(this);
dvander@0
   518
}
dvander@0
   519
dvander@14
   520
bool
dvander@14
   521
SemanticAnalysis::preanalyze(FunctionStatement *node)
dvander@14
   522
{
dvander@14
   523
    // :TODO: use Local
dvander@14
   524
dvander@14
   525
    FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
dvander@14
   526
    if (!args)
dvander@14
   527
        return false;
dvander@14
   528
dvander@14
   529
    // Apply types to arguments.
dvander@14
   530
    for (size_t i = 0; i < node->parameters()->size(); i++) {
dvander@14
   531
        Parameter *parameter = node->parameters()->at(i);
dvander@14
   532
        
dvander@14
   533
        Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
dvander@14
   534
        if (!type)
dvander@14
   535
            return false;
dvander@14
   536
dvander@25
   537
        if (type->primitive() == PrimitiveType_Char) {
dvander@25
   538
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@25
   539
            return false;
dvander@25
   540
        }
dvander@25
   541
dvander@14
   542
        if (parameter->reference()) {
dvander@14
   543
            type = ZONE()->types()->getReference(type);
dvander@14
   544
            if (!type)
dvander@14
   545
                return false;
dvander@14
   546
        }
dvander@14
   547
dvander@14
   548
        args->set(ZONE(), i, type);
dvander@14
   549
        parameter->variable()->setType(type);
dvander@14
   550
    }
dvander@14
   551
dvander@14
   552
    Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
dvander@14
   553
    if (!returnType)
dvander@14
   554
        return false;
dvander@14
   555
dvander@14
   556
    Type *funtype = ZONE()->types()->newFunction(returnType, args);
dvander@14
   557
    if (!funtype)
dvander@14
   558
        return false;
dvander@14
   559
dvander@14
   560
    node->fun()->setType(funtype);
dvander@14
   561
    return true;
dvander@14
   562
}
dvander@14
   563
dvander@0
   564
void
dvander@0
   565
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   566
{
dvander@25
   567
    function_ = node->fun()->type();
dvander@12
   568
    scope_ = node->scope();
dvander@0
   569
    node->body()->accept(this);
dvander@12
   570
    scope_ = NULL;
dvander@25
   571
    function_ = NULL;
dvander@0
   572
}
dvander@0
   573
dvander@25
   574
bool
dvander@25
   575
SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
dvander@14
   576
{
dvander@25
   577
    if (!given->isArray()) {
dvander@25
   578
        cc_.reportError(node->pos(), Message_ExpectedArray);
dvander@25
   579
        return false;
dvander@25
   580
    }
dvander@25
   581
    if (given->levels() != actual->levels()) {
dvander@25
   582
        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
dvander@25
   583
        return false;
dvander@25
   584
    }
dvander@25
   585
dvander@25
   586
    unsigned level = 0;
dvander@25
   587
    while (given->isArray()) {
dvander@25
   588
        if (actual->elements() != -1) {
dvander@25
   589
            if (forAssign) {
dvander@25
   590
                if (given->elements() == -1 || actual->elements() == -1) {
dvander@25
   591
                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
dvander@25
   592
                    return false;
dvander@25
   593
                }
dvander@25
   594
dvander@25
   595
                if (actual->isCharArray()) {
dvander@25
   596
                    // String assignment can have a truncated |given|.
dvander@25
   597
                    if (given->elements() > actual->elements()) {
dvander@25
   598
                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   599
                        return false;
dvander@25
   600
                    }
dvander@25
   601
                } else {
dvander@25
   602
                    if (given->elements() != actual->elements()) {
dvander@25
   603
                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   604
                        return false;
dvander@25
   605
                    }
dvander@25
   606
                }
dvander@25
   607
            } else {
dvander@25
   608
                if (actual->elements() != -1 && given->elements() != actual->elements()) {
dvander@25
   609
                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   610
                    return false;
dvander@25
   611
                }
dvander@25
   612
            }
dvander@25
   613
        }
dvander@25
   614
        given = given->contained();
dvander@25
   615
        actual = actual->contained();
dvander@14
   616
    }
dvander@14
   617
dvander@25
   618
    if (given->primitive() != actual->primitive()) {
dvander@25
   619
        const char *givenTag = given->tag() ? given->tag() : "_";
dvander@25
   620
        const char *actualTag = given->tag() ? given->tag() : "_";
dvander@25
   621
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   622
        return false;
dvander@25
   623
    }
dvander@25
   624
dvander@25
   625
    return true;
dvander@25
   626
}
dvander@25
   627
dvander@25
   628
bool
dvander@25
   629
SemanticAnalysis::typeCheckAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
dvander@25
   630
{
dvander@25
   631
    if (actual->isArray())
dvander@25
   632
        return typeCheckArrayAssignment(node, given, actual, forAssign);
dvander@25
   633
dvander@25
   634
    if (given->isArray()) {
dvander@25
   635
        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
dvander@25
   636
        return false;
dvander@25
   637
    }
dvander@25
   638
dvander@25
   639
    if (!given->isPrimitive() || !actual->primitive()) {
dvander@25
   640
        cc_.reportError(node->pos(), Message_UnsupportedType);
dvander@25
   641
        return false;
dvander@25
   642
    }
dvander@25
   643
    
dvander@25
   644
    // The given type may not have been dereferenced.
dvander@25
   645
    if (given->isReference())
dvander@25
   646
        given = given->contained();
dvander@25
   647
    if (actual->isReference())
dvander@25
   648
        actual = given->contained();
dvander@25
   649
dvander@25
   650
    if (given->primitive() != actual->primitive()) {
dvander@25
   651
        const char *givenTag = given->tag() ? given->tag() : "_";
dvander@25
   652
        const char *actualTag = given->tag() ? given->tag() : "_";
dvander@25
   653
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   654
        return false;
dvander@25
   655
    }
dvander@25
   656
dvander@25
   657
    return true;
dvander@25
   658
}
dvander@25
   659
dvander@25
   660
bool
dvander@25
   661
SemanticAnalysis::typeCheckParameter(AstNode *node, Type *given, Type *actual)
dvander@25
   662
{
dvander@25
   663
    return typeCheckAssignment(node, given, actual, false);
dvander@14
   664
}
dvander@14
   665
dvander@0
   666
void
dvander@0
   667
SemanticAnalysis::visit(CallExpression *node)
dvander@0
   668
{
dvander@25
   669
    Type *type = visitForLoad(node->callee());
dvander@14
   670
    if (!type)
dvander@14
   671
        return;
dvander@14
   672
dvander@25
   673
    if (!type->isFunction()) {
dvander@25
   674
        cc_.reportError(node->pos(), Message_CalleeNotFunction);
dvander@25
   675
        return;
dvander@25
   676
    }
dvander@25
   677
    if (node->arguments()->size() != type->parameters()->length()) {
dvander@25
   678
        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
dvander@25
   679
        return;
dvander@25
   680
    }
dvander@14
   681
dvander@14
   682
    for (unsigned i = 0; i < node->arguments()->size(); i++) {
dvander@17
   683
        // Note: we don't compute references unless the callee needs a
dvander@17
   684
        // reference type.
dvander@14
   685
        Expression *expression = node->arguments()->at(i);
dvander@25
   686
        Type *given = visitAndApplyType(expression);
dvander@14
   687
        if (!given)
dvander@14
   688
            return;
dvander@14
   689
dvander@17
   690
        // If it's an IndexExpression, we special case the ability to compute
dvander@25
   691
        // a reference.
dvander@17
   692
        if (expression->isIndexExpression())
dvander@17
   693
            given = given->contained();
dvander@17
   694
dvander@25
   695
        Type *actual = type->parameterAt(i);
dvander@25
   696
        if (!typeCheckParameter(expression, given, actual))
dvander@25
   697
            return;
dvander@14
   698
dvander@14
   699
        // If the actual is a reference, and the given is not, we'll need to
dvander@14
   700
        // compute a reference, which may be allocated on the stack.
dvander@14
   701
        if (actual->isReference() && !given->isReference())
dvander@14
   702
            scope_->setUsesLifoHeap();
dvander@14
   703
    }
dvander@0
   704
}
dvander@0
   705
dvander@0
   706
void
dvander@0
   707
SemanticAnalysis::visit(IfStatement *node)
dvander@0
   708
{
dvander@25
   709
    Type *type = visitForLoad(node->condition());
dvander@25
   710
    if (!type)
dvander@25
   711
        return;
dvander@25
   712
dvander@25
   713
    if (!canTest(node, type))
dvander@25
   714
        return;
dvander@25
   715
dvander@10
   716
    node->ifTrue()->accept(this);
dvander@10
   717
    if (node->ifFalse())
dvander@10
   718
        node->ifFalse()->accept(this);
dvander@0
   719
}
dvander@0
   720
dvander@0
   721
void
dvander@0
   722
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
   723
{
dvander@14
   724
    // :TODO: use locals
dvander@7
   725
    Type *left = visitForRef(node->left());
dvander@7
   726
    Type *right = visitForLoad(node->right());
dvander@0
   727
dvander@25
   728
    if (!left || !right)
dvander@25
   729
        return;
dvander@25
   730
dvander@25
   731
    if (!right->isInt32()) {
dvander@25
   732
        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
dvander@0
   733
        return;
dvander@0
   734
    }
dvander@25
   735
    if (!left->isArray()) {
dvander@25
   736
        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
dvander@0
   737
        return;
dvander@0
   738
    }
dvander@7
   739
    node->setType(left);
dvander@0
   740
}
dvander@2
   741
dvander@2
   742
void
dvander@2
   743
SemanticAnalysis::visit(EnumStatement *node)
dvander@2
   744
{
dvander@25
   745
    // Forbid the blessed types.
dvander@4
   746
    Name *tag = node->name();
dvander@25
   747
    if (!strcmp(tag, "Float") ||
dvander@25
   748
        !strcmp(tag, "String") ||
dvander@25
   749
        !strcmp(tag, "any") ||
dvander@25
   750
        !strcmp(tag, "bool"))
dvander@25
   751
    {
dvander@25
   752
        cc_.reportError(node->pos(), Message_InvalidEnumName);
dvander@25
   753
        return;
dvander@25
   754
    }
dvander@3
   755
dvander@11
   756
    Type *type = ZONE()->types()->getPrimitiveForTag(tag);
dvander@2
   757
    if (!type)
dvander@2
   758
        return;
dvander@2
   759
dvander@2
   760
    int value = 0;
dvander@2
   761
    for (size_t i = 0; i < node->entries()->size(); i++) {
dvander@2
   762
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@2
   763
dvander@2
   764
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@2
   765
        if (entry.expr) {
dvander@2
   766
            entry.expr->accept(this);
dvander@25
   767
            if (!EvaluateForConstant(entry.expr, &box)) {
dvander@25
   768
                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@25
   769
                return;
dvander@25
   770
            }
dvander@2
   771
dvander@2
   772
            assert(box.type() == PrimitiveType_Int32);
dvander@2
   773
            value = box.toInt();
dvander@2
   774
        }
dvander@2
   775
dvander@2
   776
        entry.name->set(type, box);
dvander@2
   777
        value++;
dvander@2
   778
    }
dvander@2
   779
}
dvander@4
   780
dvander@4
   781
void
dvander@21
   782
SemanticAnalysis::visit(StringLiteral *node)
dvander@21
   783
{
dvander@21
   784
    Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
dvander@21
   785
    if (!type)
dvander@21
   786
        return;
dvander@21
   787
dvander@21
   788
    type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
dvander@21
   789
    if (!type)
dvander@21
   790
        return;
dvander@21
   791
dvander@21
   792
    node->setType(type);
dvander@21
   793
}
dvander@21
   794
dvander@21
   795
void
dvander@4
   796
SemanticAnalysis::visit(FloatLiteral *node)
dvander@4
   797
{
dvander@11
   798
    Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
dvander@4
   799
    if (!type)
dvander@4
   800
        return;
dvander@4
   801
dvander@4
   802
    node->setType(type);
dvander@4
   803
}
dvander@10
   804
dvander@10
   805
void
dvander@10
   806
SemanticAnalysis::visit(BreakStatement *node)
dvander@10
   807
{
dvander@25
   808
    if (loopDepth_ == 0)
dvander@25
   809
        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
dvander@10
   810
}
dvander@10
   811
dvander@10
   812
void
dvander@10
   813
SemanticAnalysis::visit(ContinueStatement *node)
dvander@10
   814
{
dvander@25
   815
    if (loopDepth_ == 0)
dvander@25
   816
        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
dvander@10
   817
}