src/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 30 12:13:22 2012 -0700 (2012-07-30)
changeset 142 a000bafece09
parent 137 be919b22085b
child 143 393f1b8ac8c3
permissions -rw-r--r--
Implement re-tag unary expression.
dvander@30
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@30
     2
 *
dvander@0
     3
 * Copyright (C) 2012 David Anderson
dvander@0
     4
 *
dvander@0
     5
 * This file is part of JITCraft.
dvander@0
     6
 *
dvander@0
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     8
 * the terms of the GNU General Public License as published by the Free
dvander@0
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
    10
 * any later version.
dvander@0
    11
 * 
dvander@0
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    15
 *
dvander@0
    16
 * You should have received a copy of the GNU General Public License along with
dvander@0
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    18
 */
danderson@92
    19
#include <string.h>
dvander@0
    20
#include "SemanticAnalysis.h"
dvander@0
    21
#include "Types.h"
dvander@11
    22
#include "Zone.h"
dvander@11
    23
#include "TypeManager.h"
dvander@12
    24
#include "Scopes.h"
dvander@85
    25
#include "NameBinding.h"
dvander@28
    26
#include "Heap-inl.h"
dvander@54
    27
#include "Strings.h"
dvander@0
    28
dvander@59
    29
using namespace ke;
dvander@0
    30
dvander@2
    31
static inline bool
dvander@2
    32
IsPrimitiveType(Type *type, PrimitiveType primitive)
dvander@2
    33
{
dvander@2
    34
    if (!type)
dvander@2
    35
        return false;
dvander@2
    36
dvander@2
    37
    if (!type->isPrimitive())
dvander@2
    38
        return false;
dvander@2
    39
dvander@2
    40
    return primitive == type->primitive();
dvander@2
    41
}
dvander@2
    42
dvander@2
    43
static inline bool
dvander@2
    44
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@2
    45
                        BoxedPrimitive *out)
dvander@2
    46
{
dvander@2
    47
    switch (kind) {
dvander@2
    48
      case TOK_PLUS:
dvander@2
    49
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@2
    50
        return true;
dvander@2
    51
dvander@2
    52
      case TOK_SHL:
dvander@2
    53
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@2
    54
        return true;
dvander@28
    55
dvander@28
    56
      default:
dvander@47
    57
        return false;
dvander@2
    58
    }
dvander@2
    59
}
dvander@2
    60
dvander@2
    61
static bool
dvander@2
    62
EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
dvander@2
    63
{
dvander@2
    64
    switch (expression->kind()) {
dvander@2
    65
      case AstNode::kBinaryExpression:
dvander@2
    66
      {
dvander@2
    67
        BoxedPrimitive left;
dvander@2
    68
        BoxedPrimitive right;
dvander@2
    69
        BinaryExpression *b = expression->toBinaryExpression();
dvander@2
    70
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@2
    71
            !EvaluateForConstant(b->right(), &right))
dvander@2
    72
        {
dvander@2
    73
            return false;
dvander@2
    74
        }
dvander@2
    75
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@2
    76
      }
dvander@2
    77
dvander@2
    78
      case AstNode::kNameProxy:
dvander@2
    79
      {
dvander@2
    80
        NameProxy *proxy = expression->toNameProxy();
dvander@2
    81
        if (proxy->binding()->kind() != BoundName::CONSTANT)
dvander@2
    82
            return false;
dvander@2
    83
dvander@2
    84
        NamedConstant *c = proxy->binding()->toNamedConstant();
dvander@2
    85
        if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
dvander@2
    86
            return false;
dvander@2
    87
dvander@2
    88
        *out = c->value();
dvander@2
    89
        return true;
dvander@2
    90
      }
dvander@2
    91
dvander@4
    92
      case AstNode::kIntegerLiteral:
dvander@4
    93
        *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
dvander@2
    94
        return true;
dvander@2
    95
dvander@2
    96
      default:
dvander@2
    97
        return false;
dvander@2
    98
    }
dvander@2
    99
}
dvander@2
   100
dvander@30
   101
SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
dvander@30
   102
  : zone_(zone),
dvander@30
   103
    cc_(cc),
dvander@25
   104
    tree_(tree),
dvander@71
   105
    scope_(NULL),
dvander@71
   106
    loop_(NULL)
dvander@0
   107
{
dvander@0
   108
}
dvander@0
   109
dvander@0
   110
bool
dvander@0
   111
SemanticAnalysis::analyze()
dvander@0
   112
{
dvander@25
   113
    if (cc_.failures())
dvander@25
   114
        return false;
dvander@25
   115
dvander@85
   116
    scope_ = tree_->scope();
dvander@85
   117
dvander@25
   118
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@25
   119
        Statement *statement = tree_->statements()->at(i);
dvander@25
   120
        if (statement->isFunctionStatement()) {
dvander@25
   121
            FunctionStatement *funstmt = statement->toFunctionStatement();
dvander@25
   122
            if (!preanalyze(funstmt))
dvander@25
   123
                return false;
dvander@25
   124
        }
dvander@25
   125
    }
dvander@25
   126
dvander@0
   127
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@0
   128
        Statement *statement = tree_->statements()->at(i);
dvander@0
   129
        statement->accept(this);
dvander@0
   130
    }
dvander@0
   131
dvander@137
   132
    if (!determineLiveFunctions())
dvander@137
   133
        return false;
dvander@137
   134
dvander@25
   135
    return !cc_.failures();
dvander@0
   136
}
dvander@0
   137
dvander@137
   138
bool
dvander@137
   139
SemanticAnalysis::determineLiveFunctions()
dvander@137
   140
{
dvander@137
   141
    Vector<NamedFunction *> worklist;
dvander@137
   142
dvander@137
   143
    // Add the root set.
dvander@137
   144
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@137
   145
        Statement *statement = tree_->statements()->at(i);
dvander@137
   146
        if (!statement->isFunctionStatement())
dvander@137
   147
            continue;
dvander@137
   148
dvander@137
   149
        FunctionStatement *stmt = statement->toFunctionStatement();
dvander@137
   150
        NamedFunction  *fun = stmt->fun();
dvander@137
   151
        if (!fun->used())
dvander@137
   152
            continue;
dvander@137
   153
dvander@137
   154
        for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
dvander@137
   155
            NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
dvander@137
   156
dvander@137
   157
            // Names in these lists are always unused, however, we mark them
dvander@137
   158
            // as used while inserting into the work queue, to avoid double-
dvander@137
   159
            // insertion.
dvander@137
   160
            if (name->used())
dvander@137
   161
                continue;
dvander@137
   162
dvander@137
   163
            if (!worklist.append(name))
dvander@137
   164
                return false;
dvander@137
   165
dvander@137
   166
            name->setUsed();
dvander@137
   167
        }
dvander@137
   168
    }
dvander@137
   169
dvander@137
   170
    while (!worklist.empty()) {
dvander@137
   171
        NamedFunction *fun = worklist.popCopy();
dvander@137
   172
dvander@137
   173
        for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
dvander@137
   174
            NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
dvander@137
   175
            if (name->used())
dvander@137
   176
                continue;
dvander@137
   177
            if (!worklist.append(name))
dvander@137
   178
                return false;
dvander@137
   179
            name->setUsed();
dvander@137
   180
        }
dvander@137
   181
    }
dvander@137
   182
dvander@137
   183
    return true;
dvander@137
   184
}
dvander@137
   185
dvander@137
   186
dvander@25
   187
Type *
dvander@25
   188
SemanticAnalysis::visitAndApplyType(Expression *expression)
dvander@0
   189
{
dvander@25
   190
    expression->accept(this);
dvander@25
   191
    return expression->type();
dvander@0
   192
}
dvander@0
   193
dvander@7
   194
Type *
dvander@7
   195
SemanticAnalysis::visitForLoad(Expression *expression)
dvander@7
   196
{
dvander@40
   197
    Local<Type> type(zone_, visitAndApplyType(expression));
dvander@25
   198
    if (!type)
dvander@21
   199
        return NULL;
dvander@21
   200
dvander@21
   201
    if (type->isReference()) {
dvander@21
   202
        expression->setType(type->contained());
dvander@21
   203
    } else if (expression->isIndexExpression()) {
dvander@21
   204
        if (type->isArray())
dvander@14
   205
            expression->setType(type->contained());
dvander@71
   206
    } else if (expression->isCallExpression()) {
dvander@71
   207
        if (type->isVoid()) {
dvander@71
   208
            CallExpression *call = expression->toCallExpression();
dvander@71
   209
            cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
dvander@71
   210
            return NULL;
dvander@71
   211
        }
dvander@14
   212
    }
dvander@25
   213
dvander@7
   214
    return expression->type();
dvander@7
   215
}
dvander@7
   216
dvander@54
   217
// :TODO: this leaks an interior pointer.
dvander@25
   218
static inline const char *
dvander@25
   219
GetTypeName(Type *type)
dvander@4
   220
{
dvander@25
   221
    if (type->isArray())
dvander@25
   222
        return "array";
dvander@25
   223
    if (type->isFunction())
dvander@25
   224
        return "function";
dvander@129
   225
    if (type->isVoid())
dvander@129
   226
        return "void";
dvander@25
   227
    if (type->isReference())
dvander@25
   228
        type = type->contained();
dvander@25
   229
    if (type->tag())
dvander@54
   230
        return type->tag()->chars();
dvander@25
   231
    return "int";
dvander@4
   232
}
dvander@4
   233
dvander@25
   234
void
dvander@40
   235
SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
dvander@21
   236
{
dvander@25
   237
    const char *op = TokenNames[token];
dvander@25
   238
    const char *name = GetTypeName(type);
dvander@21
   239
dvander@25
   240
    cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
dvander@21
   241
}
dvander@21
   242
dvander@25
   243
void
dvander@40
   244
SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@22
   245
{
dvander@25
   246
    const char *op = TokenNames[token];
dvander@25
   247
    const char *leftName = GetTypeName(left);
dvander@25
   248
    const char *rightName = GetTypeName(right);
dvander@22
   249
dvander@25
   250
    cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
dvander@25
   251
}
dvander@25
   252
dvander@25
   253
Type *
dvander@40
   254
SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@25
   255
{
dvander@22
   256
    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
dvander@22
   257
        (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
dvander@22
   258
    {
dvander@22
   259
        // If either side is a float, the other side must be a float or int.
dvander@22
   260
        if (left->isFloat() || right->isFloat()) {
dvander@25
   261
            Type *floatType = left->isFloat() ? left : right;
dvander@25
   262
            Type *other = left->isFloat() ? right : left;
dvander@25
   263
            if (other->isFloat() || (other->isInt32() && !other->tag()))
dvander@28
   264
                return floatType;
dvander@22
   265
        }
dvander@22
   266
    }
dvander@22
   267
dvander@79
   268
    if (token == TOK_OR || token == TOK_AND) {
dvander@79
   269
        if (!canTest(node, left) || !canTest(node, right))
dvander@79
   270
            return NULL;
dvander@79
   271
        return zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@79
   272
    }
dvander@79
   273
dvander@79
   274
    if (token >= TOK_EQUALS && token <= TOK_GE) {
dvander@74
   275
        if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
dvander@75
   276
            (right->isFloat() || (right->isInt32() && !right->tag())))
dvander@74
   277
        {
dvander@74
   278
            return zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@74
   279
        }
dvander@74
   280
        binaryTypeError(node, token, left, right);
dvander@74
   281
        return NULL;
dvander@74
   282
    }
dvander@74
   283
dvander@25
   284
    if ((!left->isInt32() || left->tag()) ||
dvander@25
   285
        (!right->isInt32() || right->tag()))
dvander@25
   286
    {
dvander@25
   287
        binaryTypeError(node, token, left, right);
dvander@25
   288
        return NULL;
dvander@25
   289
    }
dvander@25
   290
dvander@22
   291
    return left;
dvander@22
   292
}
dvander@22
   293
dvander@25
   294
bool
dvander@40
   295
SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
dvander@25
   296
{
dvander@79
   297
    if (type->isArray() || (type->isInt32() && type->tag())) {
dvander@25
   298
        cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
dvander@25
   299
        return false;
dvander@25
   300
    }
dvander@25
   301
    return true;
dvander@25
   302
}
dvander@25
   303
dvander@23
   304
Type *
dvander@23
   305
SemanticAnalysis::visitForLValue(Expression *expression)
dvander@23
   306
{
dvander@23
   307
    if (expression->isIndexExpression()) {
dvander@25
   308
        Type *type = visitAndApplyType(expression);
dvander@25
   309
        if (!type)
dvander@23
   310
            return NULL;
dvander@25
   311
dvander@67
   312
        if (type->isConst()) {
dvander@67
   313
            cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@67
   314
            return NULL;
dvander@67
   315
        }
dvander@67
   316
dvander@25
   317
        return type->contained();
dvander@23
   318
    }
dvander@23
   319
dvander@23
   320
    if (!expression->isNameProxy()) {
dvander@25
   321
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   322
        return NULL;
dvander@23
   323
    }
dvander@23
   324
dvander@23
   325
    NameProxy *proxy = expression->toNameProxy();
dvander@23
   326
    if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@25
   327
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   328
        return NULL;
dvander@23
   329
    }
dvander@23
   330
dvander@23
   331
    Variable *var = proxy->binding()->toVariable();
dvander@23
   332
    if (!var->type())
dvander@23
   333
        return NULL;
dvander@23
   334
dvander@67
   335
    if  (var->type()->isReference()) {
dvander@67
   336
        if (var->type()->isConst()) {
dvander@67
   337
            cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@67
   338
            return NULL;
dvander@67
   339
        }
dvander@23
   340
        return var->type()->contained();
dvander@67
   341
    }
dvander@23
   342
    return var->type();
dvander@23
   343
}
dvander@23
   344
dvander@71
   345
SemanticAnalysis::ControlStatus
dvander@71
   346
SemanticAnalysis::visitForControl(Statement *statement)
dvander@71
   347
{
dvander@71
   348
    ControlScope scope(&control_);
dvander@71
   349
    statement->accept(this);
dvander@71
   350
    return scope.status();
dvander@71
   351
}
dvander@71
   352
dvander@0
   353
void
dvander@25
   354
SemanticAnalysis::visit(NameProxy *name)
dvander@25
   355
{
dvander@137
   356
    BoundName *binding = name->binding();
dvander@137
   357
dvander@137
   358
    if (binding->scope()->kind() == Scope::GLOBAL) {
dvander@137
   359
        if (!function_ || function_->isPublic()) {
dvander@137
   360
            // Whatever we're referencing must be kept alive no matter what.
dvander@137
   361
            // As such, we simply mark it used, and don't do anything special.
dvander@137
   362
            binding->setUsed();
dvander@137
   363
        } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
dvander@137
   364
            // Otherwise, we're inside a normal stock or function. Since we
dvander@137
   365
            // don't really know if we've been used yet, we shouldn't
dvander@137
   366
            // prematurely references as alive. Instead, we keep a list of
dvander@137
   367
            // which names have been used, so we can mark them later if needed.
dvander@137
   368
            //
dvander@137
   369
            // Note that we skip this step if the binding is already in the
dvander@137
   370
            // root set.
dvander@137
   371
            if (!function_->addUsedGlobal(binding))
dvander@137
   372
                return;
dvander@137
   373
        }
dvander@137
   374
    }
dvander@137
   375
dvander@137
   376
    name->setType(binding->type());
dvander@25
   377
}
dvander@25
   378
dvander@25
   379
void
dvander@0
   380
SemanticAnalysis::visit(Assignment *node)
dvander@0
   381
{
dvander@40
   382
    Local<Type> exprType(zone_, visitForLoad(node->expression()));
dvander@25
   383
    if (!exprType)
dvander@25
   384
        return ;
dvander@0
   385
dvander@40
   386
    Local<Type> type(zone_, visitForLValue(node->lvalue()));
dvander@23
   387
    if (!type)
dvander@23
   388
        return;
dvander@4
   389
dvander@25
   390
    if (node->token() != TOK_ASSIGN) {
dvander@25
   391
        if (!typeCheckBinary(node, node->token(), type, exprType))
dvander@25
   392
            return;
dvander@25
   393
    }
dvander@22
   394
dvander@25
   395
    if (!typeCheckAssignment(node, exprType, type, true))
dvander@25
   396
        return;
dvander@25
   397
dvander@25
   398
    node->setType(type);
dvander@0
   399
}
dvander@0
   400
dvander@0
   401
void
dvander@23
   402
SemanticAnalysis::visit(IncDecExpression *node)
dvander@23
   403
{
dvander@40
   404
    Local<Type> type(zone_, visitForLValue(node->expression()));
dvander@23
   405
    if (!type)
dvander@23
   406
        return;
dvander@23
   407
dvander@23
   408
    assert(!type->isReference());
dvander@25
   409
dvander@25
   410
    if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
dvander@25
   411
        unaryTypeError(node, node->token(), type);
dvander@23
   412
        return;
dvander@23
   413
    }
dvander@23
   414
dvander@23
   415
    node->setType(type);
dvander@23
   416
}
dvander@23
   417
dvander@23
   418
void
dvander@78
   419
SemanticAnalysis::visit(UnaryExpression *node)
dvander@78
   420
{
dvander@78
   421
    Local<Type> type(zone_, visitForLoad(node->expression()));
dvander@78
   422
    if (!type)
dvander@78
   423
        return;
dvander@78
   424
dvander@78
   425
    switch (node->token())
dvander@78
   426
    {
dvander@79
   427
      case TOK_NOT:
dvander@79
   428
        if (!canTest(node->expression(), type))
dvander@79
   429
            return;
dvander@79
   430
        type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@79
   431
        if (!type)
dvander@79
   432
            return;
dvander@79
   433
        node->setType(type);
dvander@79
   434
        break;
dvander@79
   435
dvander@80
   436
      case TOK_MINUS:
dvander@80
   437
        if (!type->isFloat() && (!type->isInt32() || type->tag())) {
dvander@80
   438
            unaryTypeError(node, node->token(), type);
dvander@80
   439
            return;
dvander@80
   440
        }
dvander@80
   441
        node->setType(type);
dvander@80
   442
        break;
dvander@80
   443
dvander@142
   444
      case TOK_LABEL:
dvander@142
   445
      {
dvander@142
   446
        Local<String> tag(zone_, node->tag());
dvander@142
   447
        Local<Type> to(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@142
   448
        if (!to)
dvander@142
   449
            return;
dvander@142
   450
dvander@142
   451
        if ((!type->isFloat() && !type->isInt32()) ||
dvander@142
   452
            (!to->isFloat() && !to->isInt32()))
dvander@142
   453
        {
dvander@142
   454
            unaryTypeError(node, node->token(), type);
dvander@142
   455
            return;
dvander@142
   456
        }
dvander@142
   457
dvander@142
   458
        node->setType(to);
dvander@142
   459
        break;
dvander@142
   460
      }
dvander@142
   461
dvander@78
   462
      default:
dvander@78
   463
        assert(node->token() == TOK_TILDE);
dvander@78
   464
        if (!type->isInt32() || type->tag()) {
dvander@78
   465
            unaryTypeError(node, node->token(), type);
dvander@78
   466
            return;
dvander@78
   467
        }
dvander@78
   468
        node->setType(type);
dvander@78
   469
        break;
dvander@78
   470
    }
dvander@78
   471
}
dvander@78
   472
dvander@78
   473
void
dvander@83
   474
SemanticAnalysis::visit(TernaryExpression *node)
dvander@83
   475
{
dvander@83
   476
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@83
   477
    if (!type)
dvander@83
   478
        return;
dvander@83
   479
dvander@83
   480
    if (!canTest(node->condition(), type))
dvander@83
   481
        return;
dvander@83
   482
dvander@83
   483
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@83
   484
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@83
   485
    if (!left || !right)
dvander@83
   486
        return;
dvander@83
   487
dvander@83
   488
    if (left != right) {
dvander@83
   489
        binaryTypeError(node, TOK_QMARK, left, right);
dvander@83
   490
        return;
dvander@83
   491
    }
dvander@83
   492
}
dvander@83
   493
dvander@83
   494
void
dvander@0
   495
SemanticAnalysis::visit(BinaryExpression *node)
dvander@0
   496
{
dvander@40
   497
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@40
   498
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@25
   499
    if (!left || !right)
dvander@25
   500
        return;
dvander@4
   501
dvander@40
   502
    Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
dvander@25
   503
    if (!result)
dvander@25
   504
        return;
dvander@25
   505
dvander@22
   506
    node->setType(result);
dvander@0
   507
}
dvander@0
   508
dvander@0
   509
void
dvander@0
   510
SemanticAnalysis::visit(ReturnStatement *node)
dvander@0
   511
{
dvander@71
   512
    // Set this early, so if we error we don't get more errors.
dvander@71
   513
    control_->returns(Returns_Always);
dvander@71
   514
dvander@72
   515
    if (!node->expression()) {
dvander@137
   516
        if (!function_->type()->returnType()->isVoid())
dvander@72
   517
            cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
dvander@72
   518
        return;
dvander@72
   519
    }
dvander@72
   520
dvander@40
   521
    Local<Type> type(zone_, visitForLoad(node->expression()));
dvander@25
   522
    if (!type)
dvander@25
   523
        return;
dvander@0
   524
dvander@137
   525
    Local<Type> returnType(zone_, function_->type()->returnType());
dvander@40
   526
    if (!typeCheckAssignment(node, type, returnType, true))
dvander@25
   527
        return;
dvander@0
   528
}
dvander@0
   529
dvander@0
   530
void
dvander@0
   531
SemanticAnalysis::visit(ForStatement *node)
dvander@0
   532
{
dvander@71
   533
    LoopScope loop(&loop_);
dvander@71
   534
dvander@12
   535
    if (node->scope())
dvander@12
   536
        scope_ = node->scope();
dvander@25
   537
dvander@22
   538
    if (node->initialization())
dvander@22
   539
        node->initialization()->accept(this);
dvander@25
   540
dvander@25
   541
    if (node->condition()) {
dvander@40
   542
        Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
   543
        if (!type || !canTest(node->condition(), type)) {
dvander@25
   544
            return;
dvander@25
   545
        }
dvander@25
   546
    }
dvander@25
   547
dvander@0
   548
    if (node->update())
dvander@0
   549
        node->update()->accept(this);
dvander@25
   550
dvander@71
   551
    ControlStatus status = visitForControl(node->body());
dvander@71
   552
dvander@71
   553
    // If there is a condition, we treat this like a while loop. Otherwise,
dvander@71
   554
    // join point is only reachable if the loop contains a break. The
dvander@71
   555
    // termination status doesn't tell us anything yet.
dvander@71
   556
    if (node->condition() || loop.breaks())
dvander@71
   557
        control_->merge(status, ControlStatus(false, Returns_Never));
dvander@71
   558
    else
dvander@71
   559
        control_->terminate(status.returns());
dvander@25
   560
dvander@12
   561
    if (node->scope())
dvander@12
   562
        scope_ = scope_->enclosing();
dvander@0
   563
}
dvander@0
   564
dvander@9
   565
void 
dvander@9
   566
SemanticAnalysis::visit(WhileStatement *node)
dvander@9
   567
{
dvander@71
   568
    LoopScope loop(&loop_);
dvander@25
   569
dvander@40
   570
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
   571
    if (!type || !canTest(node->condition(), type)) {
dvander@25
   572
        return;
dvander@25
   573
    }
dvander@25
   574
dvander@71
   575
    ControlStatus status = visitForControl(node->body());
dvander@71
   576
dvander@71
   577
    // Detect loops that will always have a fork in the control-flow graph.
dvander@71
   578
    // This will be a |while| loop, or a |do-while| loop whose body does
dvander@71
   579
    // not terminate.
dvander@71
   580
    //
dvander@71
   581
    // For now, we treat these as an |if| regardless of the direction the
dvander@71
   582
    // branch can take. That means the control-flow is always conditional.
dvander@71
   583
    if (node->token() == TOK_WHILE ||
dvander@71
   584
        !status.terminates() ||
dvander@71
   585
        loop.breaks())
dvander@71
   586
    {
dvander@71
   587
        control_->merge(status, ControlStatus(false, Returns_Never));
dvander@71
   588
    } else {
dvander@71
   589
        // At this point, we've got a do-while loop with a |return| or
dvander@71
   590
        // |continue|, meaning that the rest of the block is unreachable.
dvander@71
   591
        control_->terminate(status.returns());
dvander@71
   592
    }
dvander@9
   593
}
dvander@9
   594
dvander@0
   595
void
dvander@0
   596
SemanticAnalysis::visit(BlockStatement *node)
dvander@0
   597
{
dvander@12
   598
    if (node->scope())
dvander@12
   599
        scope_ = node->scope();
dvander@0
   600
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@0
   601
        Statement *statement = node->statements()->at(i);
dvander@0
   602
        statement->accept(this);
dvander@0
   603
    }
dvander@12
   604
    if (node->scope())
dvander@12
   605
        scope_ = scope_->enclosing();
dvander@0
   606
}
dvander@0
   607
dvander@0
   608
void
dvander@0
   609
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@0
   610
{
dvander@54
   611
    Local<String> tag(zone_, node->tag());
dvander@54
   612
    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@0
   613
    if (!type)
dvander@0
   614
        return;
dvander@0
   615
dvander@0
   616
    if (node->postDimensions()) {
dvander@37
   617
        Local<Type> init(zone_);
dvander@21
   618
        if (node->initialization()) {
dvander@71
   619
            if ((init = visitForLoad(node->initialization())) == NULL)
dvander@21
   620
                return;
dvander@21
   621
        }
dvander@21
   622
dvander@55
   623
        if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@25
   624
            cc_.reportError(node->pos(), Message_MaximumArrayDepth);
dvander@0
   625
            return;
dvander@0
   626
        }
dvander@0
   627
dvander@21
   628
        // If we have an initializer, make sure it's the same type.
dvander@55
   629
        if (init && node->postDimensions()->length() != init->levels()) {
dvander@25
   630
            cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
dvander@25
   631
            return;
dvander@21
   632
        }
dvander@21
   633
dvander@37
   634
        Local<Type> check(zone_, init);
dvander@55
   635
        for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
dvander@0
   636
            Expression *expr = node->postDimensions()->at(i);
dvander@25
   637
            int size = -1;
dvander@0
   638
dvander@25
   639
            if (expr) {
dvander@37
   640
                Local<Type> exprType(zone_, visitForLoad(expr));
dvander@25
   641
                if (!exprType)
dvander@25
   642
                    return;
dvander@0
   643
dvander@25
   644
                if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
dvander@25
   645
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   646
                    return;
dvander@0
   647
                }
dvander@25
   648
dvander@25
   649
                BoxedPrimitive box;
dvander@25
   650
                if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@25
   651
                    size = box.toInt();
dvander@25
   652
                    if (size <= 0) {
dvander@25
   653
                        cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@25
   654
                        return;
dvander@25
   655
                    }
danderson@92
   656
                    if (size >= int(INT_MAX / sizeof(int))) {
dvander@25
   657
                        cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
dvander@25
   658
                        return;
dvander@25
   659
                    }
dvander@25
   660
dvander@25
   661
                    if (check) {
dvander@25
   662
                        if (check->elements() == -1) {
dvander@25
   663
                            cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   664
                            return;
dvander@25
   665
                        }
dvander@25
   666
dvander@25
   667
                        if (check->isCharArray()) {
dvander@25
   668
                            if (check->elements() > size) {
dvander@25
   669
                                cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   670
                                return;
dvander@25
   671
                            }
dvander@25
   672
                        } else if (check->elements() != size) {
dvander@25
   673
                            cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
dvander@25
   674
                            return;
dvander@25
   675
                        }
dvander@25
   676
                    }
dvander@25
   677
                } else {
dvander@25
   678
                    if (init) {
dvander@25
   679
                        cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
dvander@25
   680
                        return;
dvander@25
   681
                    }
dvander@25
   682
dvander@25
   683
                    // here until we get dynamic array support.
dvander@25
   684
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   685
                    return;
dvander@0
   686
                }
dvander@21
   687
            } else {
dvander@25
   688
                // Infer the size from the initializer.
dvander@25
   689
                if (!init) {
dvander@25
   690
                    cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
dvander@25
   691
                    return;
dvander@25
   692
                }
dvander@25
   693
                if (init->elements() == -1) {
dvander@25
   694
                    cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   695
                    return;
dvander@25
   696
                }
dvander@25
   697
                size = init->elements();
dvander@0
   698
            }
dvander@0
   699
dvander@67
   700
            type = zone_->types()->unsafeArray(type, size, false);
dvander@25
   701
            if (!type)
dvander@25
   702
                return;
dvander@21
   703
dvander@21
   704
            if (check)
dvander@21
   705
                check = check->contained();
dvander@0
   706
        }
dvander@12
   707
dvander@85
   708
        // If this variable is stack allocated, we could use the LIFO heap
dvander@85
   709
        // to allocate it. If that's the case, make sure to reserve a slot
dvander@85
   710
        // so we can unwind the LIFO heap at the end of this scope.
dvander@85
   711
        if (!node->variable()->needsHeapAllocation())
dvander@85
   712
            scope_->setUsesLifoHeap();
dvander@8
   713
    } else {
dvander@10
   714
        if (node->initialization()) {
dvander@40
   715
            Local<Type> right(zone_, visitForLoad(node->initialization()));
dvander@25
   716
            if (!right)
dvander@25
   717
                return;
dvander@25
   718
            if (!typeCheckAssignment(node, type, right, true))
dvander@25
   719
                return;
dvander@10
   720
        }
dvander@21
   721
        if (type->primitive() == PrimitiveType_Char) {
dvander@25
   722
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@21
   723
            return;
dvander@21
   724
        }
dvander@0
   725
    }
dvander@0
   726
dvander@0
   727
    node->variable()->setType(type);
dvander@0
   728
}
dvander@0
   729
dvander@0
   730
void
dvander@4
   731
SemanticAnalysis::visit(IntegerLiteral *node)
dvander@0
   732
{
dvander@30
   733
    node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@0
   734
}
dvander@0
   735
dvander@0
   736
void
dvander@0
   737
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@0
   738
{
dvander@71
   739
    visitAndApplyType(node->expression());
dvander@0
   740
}
dvander@0
   741
dvander@14
   742
bool
dvander@14
   743
SemanticAnalysis::preanalyze(FunctionStatement *node)
dvander@14
   744
{
dvander@57
   745
    Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
dvander@14
   746
    if (!args)
dvander@14
   747
        return false;
dvander@14
   748
dvander@14
   749
    // Apply types to arguments.
dvander@57
   750
    for (size_t i = 0; i < node->parameters()->length(); i++) {
dvander@14
   751
        Parameter *parameter = node->parameters()->at(i);
dvander@14
   752
        
dvander@54
   753
        Local<String> tag(zone_, parameter->tag());
dvander@54
   754
        Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@14
   755
        if (!type)
dvander@14
   756
            return false;
dvander@14
   757
dvander@14
   758
        if (parameter->reference()) {
dvander@66
   759
            if (parameter->dimensions()) {
dvander@66
   760
                cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
dvander@66
   761
                return NULL;
dvander@66
   762
            }
dvander@66
   763
dvander@67
   764
            type = zone_->types()->getReference(type, parameter->isConst());
dvander@14
   765
            if (!type)
dvander@14
   766
                return false;
dvander@66
   767
        } else if (parameter->dimensions()) {
dvander@66
   768
            if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@68
   769
                cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
dvander@68
   770
                return false;
dvander@68
   771
            }
dvander@68
   772
dvander@68
   773
            if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
dvander@68
   774
                cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
dvander@66
   775
                return false;
dvander@66
   776
            }
dvander@66
   777
dvander@66
   778
            for (size_t i = parameter->dimensions()->length() - 1;
dvander@66
   779
                 i < parameter->dimensions()->length();
dvander@66
   780
                 i++)
dvander@66
   781
            {
dvander@66
   782
                int size = Type::UNKNOWN_SIZE;
dvander@66
   783
                if (Expression *expr = parameter->dimensions()->at(i)) {
dvander@66
   784
                    BoxedPrimitive box;
dvander@66
   785
                    if (!EvaluateForConstant(expr, &box)) {
dvander@66
   786
                        cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
dvander@66
   787
                        return false;
dvander@66
   788
                    }
dvander@66
   789
                    size = box.toInt();
dvander@66
   790
                }
dvander@66
   791
dvander@67
   792
                type = zone_->types()->unsafeArray(type, size, parameter->isConst());
dvander@66
   793
                if (!type)
dvander@66
   794
                    return false;
dvander@66
   795
            }
dvander@14
   796
        }
dvander@14
   797
dvander@68
   798
        if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
dvander@68
   799
            (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
dvander@68
   800
        {
dvander@68
   801
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@68
   802
            return false;
dvander@68
   803
        }
dvander@68
   804
dvander@30
   805
        args->set(zone_, i, type);
dvander@14
   806
        parameter->variable()->setType(type);
dvander@14
   807
    }
dvander@14
   808
dvander@71
   809
    Local<Type> returnType(zone_);
dvander@132
   810
    if (node->returnTag()) {
dvander@132
   811
        Local<String> tag(zone_, node->returnTag());
dvander@132
   812
        returnType = zone_->types()->getPrimitiveForTag(tag);
dvander@132
   813
    } else if (node->hasExplicitReturn() || node->fun()->isNative()) {
dvander@71
   814
        returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@132
   815
    } else {
dvander@71
   816
        returnType = zone_->types()->getVoid();
dvander@132
   817
    }
dvander@14
   818
    if (!returnType)
dvander@14
   819
        return false;
dvander@14
   820
dvander@68
   821
    Local<Type> funtype(zone_);
dvander@68
   822
    if (node->fun()->isNative())
dvander@68
   823
        funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
dvander@68
   824
    else
dvander@68
   825
        funtype = zone_->types()->newFunction(returnType, args);
dvander@14
   826
    if (!funtype)
dvander@14
   827
        return false;
dvander@63
   828
    
dvander@63
   829
    // If the function already has a type, it was forward declared before, and
dvander@63
   830
    // now this is our chance to type check the second declaration.
dvander@63
   831
    if (node->fun()->type()) {
dvander@63
   832
        Local<Type> forward(zone_, node->fun()->type());
dvander@63
   833
        if (!Type::Compare(funtype, forward)) {
dvander@63
   834
            cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
dvander@63
   835
            return false;
dvander@63
   836
        }
dvander@63
   837
        node->fun()->setForwardType(forward);
dvander@63
   838
    }
dvander@14
   839
dvander@14
   840
    node->fun()->setType(funtype);
dvander@63
   841
dvander@14
   842
    return true;
dvander@14
   843
}
dvander@14
   844
dvander@0
   845
void
dvander@0
   846
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   847
{
dvander@137
   848
    function_ = node->fun();
dvander@12
   849
    scope_ = node->scope();
dvander@71
   850
dvander@71
   851
    ControlScope control(&control_);
dvander@71
   852
    if (node->body()) {
dvander@63
   853
        node->body()->accept(this);
dvander@71
   854
dvander@71
   855
        ControlStatus status = control.status();
dvander@71
   856
        if (status.returns() == Returns_Sometimes) {
dvander@71
   857
            cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
dvander@71
   858
        } else if (status.returns() == Returns_Never) {
dvander@137
   859
            if (!function_->type()->returnType()->isVoid())
dvander@71
   860
                cc_.reportError(node->pos(), Message_MissingReturnValue);
dvander@71
   861
        }
dvander@71
   862
    }
dvander@71
   863
dvander@12
   864
    scope_ = NULL;
dvander@25
   865
    function_ = NULL;
dvander@0
   866
}
dvander@0
   867
dvander@25
   868
bool
dvander@40
   869
SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@14
   870
{
dvander@40
   871
    Local<Type> actual(zone_, argActual);
dvander@40
   872
    Local<Type> given(zone_, argGiven);
dvander@40
   873
dvander@25
   874
    if (!given->isArray()) {
dvander@25
   875
        cc_.reportError(node->pos(), Message_ExpectedArray);
dvander@25
   876
        return false;
dvander@25
   877
    }
dvander@25
   878
    if (given->levels() != actual->levels()) {
dvander@25
   879
        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
dvander@25
   880
        return false;
dvander@25
   881
    }
dvander@25
   882
dvander@25
   883
    unsigned level = 0;
dvander@25
   884
    while (given->isArray()) {
dvander@25
   885
        if (actual->elements() != -1) {
dvander@25
   886
            if (forAssign) {
dvander@25
   887
                if (given->elements() == -1 || actual->elements() == -1) {
dvander@25
   888
                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
dvander@25
   889
                    return false;
dvander@25
   890
                }
dvander@25
   891
dvander@25
   892
                if (actual->isCharArray()) {
dvander@25
   893
                    // String assignment can have a truncated |given|.
dvander@25
   894
                    if (given->elements() > actual->elements()) {
dvander@25
   895
                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   896
                        return false;
dvander@25
   897
                    }
dvander@25
   898
                } else {
dvander@25
   899
                    if (given->elements() != actual->elements()) {
dvander@25
   900
                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   901
                        return false;
dvander@25
   902
                    }
dvander@25
   903
                }
dvander@25
   904
            } else {
dvander@25
   905
                if (actual->elements() != -1 && given->elements() != actual->elements()) {
dvander@25
   906
                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   907
                    return false;
dvander@25
   908
                }
dvander@25
   909
            }
dvander@25
   910
        }
dvander@25
   911
        given = given->contained();
dvander@25
   912
        actual = actual->contained();
dvander@14
   913
    }
dvander@14
   914
dvander@25
   915
    if (given->primitive() != actual->primitive()) {
dvander@54
   916
        // :TODO: leaks an interior pointer.
dvander@54
   917
        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
dvander@54
   918
        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
dvander@25
   919
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   920
        return false;
dvander@25
   921
    }
dvander@25
   922
dvander@25
   923
    return true;
dvander@25
   924
}
dvander@25
   925
dvander@25
   926
bool
dvander@40
   927
SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@25
   928
{
dvander@40
   929
    Local<Type> actual(zone_, argActual);
dvander@40
   930
    Local<Type> given(zone_, argGiven);
dvander@40
   931
dvander@25
   932
    if (actual->isArray())
dvander@25
   933
        return typeCheckArrayAssignment(node, given, actual, forAssign);
dvander@25
   934
dvander@25
   935
    if (given->isArray()) {
dvander@25
   936
        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
dvander@25
   937
        return false;
dvander@25
   938
    }
dvander@25
   939
dvander@47
   940
    // The given type may not have been dereferenced.
dvander@47
   941
    if (given->isReference())
dvander@47
   942
        given = given->contained();
dvander@47
   943
    if (actual->isReference())
dvander@47
   944
        actual = actual->contained();
dvander@47
   945
dvander@47
   946
    if (!given->isPrimitive() || !actual->isPrimitive()) {
dvander@25
   947
        cc_.reportError(node->pos(), Message_UnsupportedType);
dvander@25
   948
        return false;
dvander@25
   949
    }
dvander@25
   950
    
dvander@25
   951
    if (given->primitive() != actual->primitive()) {
dvander@54
   952
        // :TODO: leaks an interior pointer
dvander@54
   953
        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
dvander@85
   954
        const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
dvander@25
   955
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   956
        return false;
dvander@25
   957
    }
dvander@25
   958
dvander@25
   959
    return true;
dvander@25
   960
}
dvander@25
   961
dvander@25
   962
bool
dvander@40
   963
SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
dvander@25
   964
{
dvander@25
   965
    return typeCheckAssignment(node, given, actual, false);
dvander@14
   966
}
dvander@14
   967
dvander@0
   968
void
dvander@0
   969
SemanticAnalysis::visit(CallExpression *node)
dvander@0
   970
{
dvander@40
   971
    Local<Type> type(zone_, visitForLoad(node->callee()));
dvander@14
   972
    if (!type)
dvander@14
   973
        return;
dvander@14
   974
dvander@25
   975
    if (!type->isFunction()) {
dvander@25
   976
        cc_.reportError(node->pos(), Message_CalleeNotFunction);
dvander@25
   977
        return;
dvander@25
   978
    }
dvander@55
   979
    if (node->arguments()->length() != type->parameters()->length()) {
dvander@68
   980
        if (!type->isNative() ||
dvander@68
   981
            !type->isNativeVariadic() ||
dvander@68
   982
            node->arguments()->length() < type->parameters()->length())
dvander@68
   983
        {
dvander@68
   984
            cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
dvander@68
   985
            return;
dvander@68
   986
        }
dvander@25
   987
    }
dvander@14
   988
dvander@63
   989
    // Currently, only calls from a NameProxy are possible.
dvander@63
   990
    NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
dvander@63
   991
    if (fun->isForward()) {
dvander@63
   992
        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
dvander@63
   993
        return;
dvander@63
   994
    }
dvander@63
   995
dvander@55
   996
    for (unsigned i = 0; i < node->arguments()->length(); i++) {
dvander@17
   997
        // Note: we don't compute references unless the callee needs a
dvander@17
   998
        // reference type.
dvander@14
   999
        Expression *expression = node->arguments()->at(i);
dvander@40
  1000
        Local<Type> given(zone_, visitAndApplyType(expression));
dvander@14
  1001
        if (!given)
dvander@14
  1002
            return;
dvander@14
  1003
dvander@71
  1004
        // Since we skip a load, check for a call expression that returns void.
dvander@71
  1005
        if (given->isVoid()) {
dvander@71
  1006
            assert(expression->isCallExpression());
dvander@71
  1007
            CallExpression *call = expression->toCallExpression();
dvander@71
  1008
            cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
dvander@71
  1009
            return;
dvander@71
  1010
        }
dvander@71
  1011
        
dvander@17
  1012
        // If it's an IndexExpression, we special case the ability to compute
dvander@25
  1013
        // a reference.
dvander@17
  1014
        if (expression->isIndexExpression())
dvander@17
  1015
            given = given->contained();
dvander@17
  1016
dvander@68
  1017
        bool mustComputeReference;
dvander@68
  1018
        if (i >= type->parameters()->length()) {
dvander@68
  1019
            // Special handling for natives. Arguments past the formal must
dvander@68
  1020
            // always have references computed. However, arrays are already
dvander@68
  1021
            // references for natives.  
dvander@68
  1022
            assert(type->isNative() && type->isNativeVariadic());
dvander@68
  1023
            mustComputeReference = !given->isReference() && !given->isArray();
dvander@68
  1024
        } else {
dvander@68
  1025
            Local<Type> actual(zone_, type->parameterAt(i));
dvander@68
  1026
            if (!typeCheckParameter(expression, given, actual))
dvander@68
  1027
                return;
dvander@68
  1028
            mustComputeReference = actual->isReference() && !given->isReference();
dvander@68
  1029
        }
dvander@14
  1030
dvander@14
  1031
        // If the actual is a reference, and the given is not, we'll need to
dvander@14
  1032
        // compute a reference, which may be allocated on the stack.
dvander@68
  1033
        if (mustComputeReference)
dvander@14
  1034
            scope_->setUsesLifoHeap();
dvander@14
  1035
    }
dvander@66
  1036
dvander@66
  1037
    node->setType(fun->type()->returnType());
dvander@0
  1038
}
dvander@0
  1039
dvander@0
  1040
void
dvander@71
  1041
SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
dvander@71
  1042
{
dvander@71
  1043
    // If both sides terminate in a return, we consider this a return as well.
dvander@71
  1044
    if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
dvander@71
  1045
        terminate(Returns_Always);
dvander@71
  1046
        return;
dvander@71
  1047
    }
dvander@71
  1048
dvander@71
  1049
    ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
dvander@71
  1050
                          ? Returns_Never
dvander@71
  1051
                          : Returns_Sometimes;
dvander@71
  1052
dvander@71
  1053
    if (left.terminates() && right.terminates())
dvander@71
  1054
        terminate(status);
dvander@71
  1055
    else
dvander@71
  1056
        returns(status);
dvander@71
  1057
}
dvander@71
  1058
dvander@71
  1059
void
dvander@0
  1060
SemanticAnalysis::visit(IfStatement *node)
dvander@0
  1061
{
dvander@40
  1062
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
  1063
    if (!type)
dvander@25
  1064
        return;
dvander@25
  1065
dvander@25
  1066
    if (!canTest(node, type))
dvander@25
  1067
        return;
dvander@25
  1068
dvander@71
  1069
    ControlStatus trueBranch = visitForControl(node->ifTrue());
dvander@71
  1070
    ControlStatus falseBranch = ControlStatus(false, Returns_Never);
dvander@71
  1071
dvander@10
  1072
    if (node->ifFalse())
dvander@71
  1073
        falseBranch = visitForControl(node->ifFalse());
dvander@71
  1074
dvander@71
  1075
    control_->merge(trueBranch, falseBranch);
dvander@0
  1076
}
dvander@0
  1077
dvander@0
  1078
void
dvander@0
  1079
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
  1080
{
dvander@71
  1081
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@40
  1082
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@0
  1083
dvander@25
  1084
    if (!left || !right)
dvander@25
  1085
        return;
dvander@25
  1086
dvander@25
  1087
    if (!right->isInt32()) {
dvander@25
  1088
        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
dvander@0
  1089
        return;
dvander@0
  1090
    }
dvander@25
  1091
    if (!left->isArray()) {
dvander@25
  1092
        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
dvander@0
  1093
        return;
dvander@0
  1094
    }
dvander@7
  1095
    node->setType(left);
dvander@0
  1096
}
dvander@2
  1097
dvander@2
  1098
void
dvander@2
  1099
SemanticAnalysis::visit(EnumStatement *node)
dvander@2
  1100
{
dvander@25
  1101
    // Forbid the blessed types.
dvander@54
  1102
    Local<String> tag(zone_, node->name());
dvander@54
  1103
    if (!strcmp(tag->chars(), "Float") ||
dvander@54
  1104
        !strcmp(tag->chars(), "String") ||
dvander@54
  1105
        !strcmp(tag->chars(), "any") ||
dvander@54
  1106
        !strcmp(tag->chars(), "bool"))
dvander@25
  1107
    {
dvander@25
  1108
        cc_.reportError(node->pos(), Message_InvalidEnumName);
dvander@25
  1109
        return;
dvander@25
  1110
    }
dvander@3
  1111
dvander@40
  1112
    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@2
  1113
    if (!type)
dvander@2
  1114
        return;
dvander@2
  1115
dvander@2
  1116
    int value = 0;
dvander@57
  1117
    for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@2
  1118
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@2
  1119
dvander@2
  1120
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@2
  1121
        if (entry.expr) {
dvander@2
  1122
            entry.expr->accept(this);
dvander@25
  1123
            if (!EvaluateForConstant(entry.expr, &box)) {
dvander@25
  1124
                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@25
  1125
                return;
dvander@25
  1126
            }
dvander@2
  1127
dvander@2
  1128
            assert(box.type() == PrimitiveType_Int32);
dvander@2
  1129
            value = box.toInt();
dvander@2
  1130
        }
dvander@2
  1131
dvander@2
  1132
        entry.name->set(type, box);
dvander@2
  1133
        value++;
dvander@2
  1134
    }
dvander@2
  1135
}
dvander@4
  1136
dvander@4
  1137
void
dvander@21
  1138
SemanticAnalysis::visit(StringLiteral *node)
dvander@21
  1139
{
dvander@40
  1140
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
dvander@21
  1141
    if (!type)
dvander@21
  1142
        return;
dvander@21
  1143
dvander@30
  1144
    type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
dvander@21
  1145
    if (!type)
dvander@21
  1146
        return;
dvander@21
  1147
dvander@21
  1148
    node->setType(type);
dvander@21
  1149
}
dvander@21
  1150
dvander@21
  1151
void
dvander@4
  1152
SemanticAnalysis::visit(FloatLiteral *node)
dvander@4
  1153
{
dvander@40
  1154
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
dvander@4
  1155
    if (!type)
dvander@4
  1156
        return;
dvander@4
  1157
dvander@4
  1158
    node->setType(type);
dvander@4
  1159
}
dvander@10
  1160
dvander@10
  1161
void
dvander@10
  1162
SemanticAnalysis::visit(BreakStatement *node)
dvander@10
  1163
{
dvander@71
  1164
    if (!loop_) {
dvander@25
  1165
        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
dvander@71
  1166
        return;
dvander@71
  1167
    }
dvander@71
  1168
dvander@71
  1169
    // Note: ignore breaks that occur in unreachable control-flow.
dvander@71
  1170
    if (!control_->status().terminates())
dvander@71
  1171
        loop_->addBreak();
dvander@71
  1172
dvander@71
  1173
    control_->terminate(Returns_Never);
dvander@10
  1174
}
dvander@10
  1175
dvander@10
  1176
void
dvander@10
  1177
SemanticAnalysis::visit(ContinueStatement *node)
dvander@10
  1178
{
dvander@71
  1179
    if (!loop_) {
dvander@25
  1180
        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
dvander@71
  1181
        return;
dvander@71
  1182
    }
dvander@71
  1183
dvander@71
  1184
    // Note: ignore continues that occur in unreachable control-flow.
dvander@71
  1185
    if (!control_->status().terminates())
dvander@71
  1186
        loop_->addContinue();
dvander@71
  1187
dvander@71
  1188
    control_->terminate(Returns_Never);
dvander@10
  1189
}