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