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