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