src/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Sun Aug 05 12:55:51 2012 -0700 (2012-08-05)
changeset 164 3bf7c007883d
parent 160 12807399b953
child 166 3ac2a36a7a0c
permissions -rw-r--r--
Support FieldExpressions as references.
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@164
   863
            if (type->isStruct()) {
dvander@164
   864
                cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
dvander@164
   865
                return NULL;
dvander@164
   866
            }
dvander@164
   867
dvander@67
   868
            type = zone_->types()->getReference(type, parameter->isConst());
dvander@14
   869
            if (!type)
dvander@14
   870
                return false;
dvander@66
   871
        } else if (parameter->dimensions()) {
dvander@66
   872
            if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@68
   873
                cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
dvander@68
   874
                return false;
dvander@68
   875
            }
dvander@68
   876
dvander@68
   877
            if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
dvander@68
   878
                cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
dvander@66
   879
                return false;
dvander@66
   880
            }
dvander@66
   881
dvander@66
   882
            for (size_t i = parameter->dimensions()->length() - 1;
dvander@66
   883
                 i < parameter->dimensions()->length();
dvander@66
   884
                 i++)
dvander@66
   885
            {
dvander@66
   886
                int size = Type::UNKNOWN_SIZE;
dvander@66
   887
                if (Expression *expr = parameter->dimensions()->at(i)) {
dvander@66
   888
                    BoxedPrimitive box;
dvander@66
   889
                    if (!EvaluateForConstant(expr, &box)) {
dvander@66
   890
                        cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
dvander@66
   891
                        return false;
dvander@66
   892
                    }
dvander@66
   893
                    size = box.toInt();
dvander@66
   894
                }
dvander@66
   895
dvander@67
   896
                type = zone_->types()->unsafeArray(type, size, parameter->isConst());
dvander@66
   897
                if (!type)
dvander@66
   898
                    return false;
dvander@66
   899
            }
dvander@14
   900
        }
dvander@14
   901
dvander@145
   902
        if (IsScalarString(type)) {
dvander@68
   903
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@68
   904
            return false;
dvander@68
   905
        }
dvander@68
   906
dvander@30
   907
        args->set(zone_, i, type);
dvander@14
   908
        parameter->variable()->setType(type);
dvander@14
   909
    }
dvander@14
   910
dvander@71
   911
    Local<Type> returnType(zone_);
dvander@145
   912
    if (node->returnType() ||
dvander@145
   913
        node->hasExplicitReturn() ||
dvander@145
   914
        node->fun()->isNative())
dvander@145
   915
    {
dvander@145
   916
        returnType = bindType(node->pos(), node->returnType());
dvander@132
   917
    } else {
dvander@71
   918
        returnType = zone_->types()->getVoid();
dvander@132
   919
    }
dvander@14
   920
    if (!returnType)
dvander@14
   921
        return false;
dvander@14
   922
dvander@68
   923
    Local<Type> funtype(zone_);
dvander@68
   924
    if (node->fun()->isNative())
dvander@68
   925
        funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
dvander@68
   926
    else
dvander@68
   927
        funtype = zone_->types()->newFunction(returnType, args);
dvander@14
   928
    if (!funtype)
dvander@14
   929
        return false;
dvander@63
   930
    
dvander@63
   931
    // If the function already has a type, it was forward declared before, and
dvander@63
   932
    // now this is our chance to type check the second declaration.
dvander@63
   933
    if (node->fun()->type()) {
dvander@63
   934
        Local<Type> forward(zone_, node->fun()->type());
dvander@63
   935
        if (!Type::Compare(funtype, forward)) {
dvander@63
   936
            cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
dvander@63
   937
            return false;
dvander@63
   938
        }
dvander@63
   939
        node->fun()->setForwardType(forward);
dvander@63
   940
    }
dvander@14
   941
dvander@14
   942
    node->fun()->setType(funtype);
dvander@63
   943
dvander@14
   944
    return true;
dvander@14
   945
}
dvander@14
   946
dvander@0
   947
void
dvander@0
   948
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   949
{
dvander@137
   950
    function_ = node->fun();
dvander@12
   951
    scope_ = node->scope();
dvander@71
   952
dvander@71
   953
    ControlScope control(&control_);
dvander@71
   954
    if (node->body()) {
dvander@63
   955
        node->body()->accept(this);
dvander@71
   956
dvander@71
   957
        ControlStatus status = control.status();
dvander@71
   958
        if (status.returns() == Returns_Sometimes) {
dvander@71
   959
            cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
dvander@71
   960
        } else if (status.returns() == Returns_Never) {
dvander@137
   961
            if (!function_->type()->returnType()->isVoid())
dvander@71
   962
                cc_.reportError(node->pos(), Message_MissingReturnValue);
dvander@71
   963
        }
dvander@71
   964
    }
dvander@71
   965
dvander@12
   966
    scope_ = NULL;
dvander@25
   967
    function_ = NULL;
dvander@0
   968
}
dvander@0
   969
dvander@145
   970
void
dvander@145
   971
SemanticAnalysis::typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given)
dvander@145
   972
{
dvander@145
   973
    cc_.reportError(node->pos(),Message_TypeMismatch,
dvander@145
   974
                    GetTypeName(actual),
dvander@145
   975
                    GetTypeName(given));
dvander@145
   976
}
dvander@145
   977
dvander@25
   978
bool
dvander@40
   979
SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@14
   980
{
dvander@40
   981
    Local<Type> actual(zone_, argActual);
dvander@40
   982
    Local<Type> given(zone_, argGiven);
dvander@40
   983
dvander@25
   984
    if (!given->isArray()) {
dvander@25
   985
        cc_.reportError(node->pos(), Message_ExpectedArray);
dvander@25
   986
        return false;
dvander@25
   987
    }
dvander@25
   988
    if (given->levels() != actual->levels()) {
dvander@25
   989
        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
dvander@25
   990
        return false;
dvander@25
   991
    }
dvander@25
   992
dvander@25
   993
    unsigned level = 0;
dvander@25
   994
    while (given->isArray()) {
dvander@25
   995
        if (actual->elements() != -1) {
dvander@25
   996
            if (forAssign) {
dvander@25
   997
                if (given->elements() == -1 || actual->elements() == -1) {
dvander@25
   998
                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
dvander@25
   999
                    return false;
dvander@25
  1000
                }
dvander@25
  1001
dvander@25
  1002
                if (actual->isCharArray()) {
dvander@25
  1003
                    // String assignment can have a truncated |given|.
dvander@25
  1004
                    if (given->elements() > actual->elements()) {
dvander@25
  1005
                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
  1006
                        return false;
dvander@25
  1007
                    }
dvander@25
  1008
                } else {
dvander@25
  1009
                    if (given->elements() != actual->elements()) {
dvander@25
  1010
                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
  1011
                        return false;
dvander@25
  1012
                    }
dvander@25
  1013
                }
dvander@25
  1014
            } else {
dvander@25
  1015
                if (actual->elements() != -1 && given->elements() != actual->elements()) {
dvander@25
  1016
                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
  1017
                    return false;
dvander@25
  1018
                }
dvander@25
  1019
            }
dvander@25
  1020
        }
dvander@25
  1021
        given = given->contained();
dvander@25
  1022
        actual = actual->contained();
dvander@14
  1023
    }
dvander@14
  1024
dvander@145
  1025
    return typeCheckAssignment(node, given, actual, forAssign);
dvander@25
  1026
}
dvander@25
  1027
dvander@25
  1028
bool
dvander@40
  1029
SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@25
  1030
{
dvander@40
  1031
    Local<Type> actual(zone_, argActual);
dvander@40
  1032
    Local<Type> given(zone_, argGiven);
dvander@40
  1033
dvander@25
  1034
    if (actual->isArray())
dvander@25
  1035
        return typeCheckArrayAssignment(node, given, actual, forAssign);
dvander@25
  1036
dvander@25
  1037
    if (given->isArray()) {
dvander@25
  1038
        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
dvander@25
  1039
        return false;
dvander@25
  1040
    }
dvander@25
  1041
dvander@47
  1042
    // The given type may not have been dereferenced.
dvander@47
  1043
    if (given->isReference())
dvander@47
  1044
        given = given->contained();
dvander@47
  1045
    if (actual->isReference())
dvander@47
  1046
        actual = actual->contained();
dvander@47
  1047
dvander@145
  1048
    if (actual->isEnum()) {
dvander@145
  1049
        if (!given->isEnum() || actual != given) {
dvander@145
  1050
            typeMismatch(node, actual, given);
dvander@145
  1051
            return false;
dvander@145
  1052
        }
dvander@145
  1053
        return true;
dvander@145
  1054
    }
dvander@145
  1055
dvander@149
  1056
    if (actual->isStruct()) {
dvander@149
  1057
        if (!given->isStruct() || actual != given) {
dvander@149
  1058
            typeMismatch(node, actual, given);
dvander@149
  1059
            return false;
dvander@149
  1060
        }
dvander@149
  1061
        return true;
dvander@149
  1062
    }
dvander@149
  1063
dvander@149
  1064
    if (given->isEnum() || given->isFunction() || given->isStruct()) {
dvander@145
  1065
        typeMismatch(node, actual, given);
dvander@25
  1066
        return false;
dvander@25
  1067
    }
dvander@145
  1068
dvander@25
  1069
    if (given->primitive() != actual->primitive()) {
dvander@145
  1070
        typeMismatch(node, actual, given);
dvander@25
  1071
        return false;
dvander@25
  1072
    }
dvander@25
  1073
dvander@25
  1074
    return true;
dvander@25
  1075
}
dvander@25
  1076
dvander@25
  1077
bool
dvander@40
  1078
SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
dvander@25
  1079
{
dvander@25
  1080
    return typeCheckAssignment(node, given, actual, false);
dvander@14
  1081
}
dvander@14
  1082
dvander@0
  1083
void
dvander@0
  1084
SemanticAnalysis::visit(CallExpression *node)
dvander@0
  1085
{
dvander@40
  1086
    Local<Type> type(zone_, visitForLoad(node->callee()));
dvander@14
  1087
    if (!type)
dvander@14
  1088
        return;
dvander@14
  1089
dvander@25
  1090
    if (!type->isFunction()) {
dvander@25
  1091
        cc_.reportError(node->pos(), Message_CalleeNotFunction);
dvander@25
  1092
        return;
dvander@25
  1093
    }
dvander@55
  1094
    if (node->arguments()->length() != type->parameters()->length()) {
dvander@68
  1095
        if (!type->isNative() ||
dvander@68
  1096
            !type->isNativeVariadic() ||
dvander@68
  1097
            node->arguments()->length() < type->parameters()->length())
dvander@68
  1098
        {
dvander@68
  1099
            cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
dvander@68
  1100
            return;
dvander@68
  1101
        }
dvander@25
  1102
    }
dvander@14
  1103
dvander@63
  1104
    // Currently, only calls from a NameProxy are possible.
dvander@63
  1105
    NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
dvander@63
  1106
    if (fun->isForward()) {
dvander@63
  1107
        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
dvander@63
  1108
        return;
dvander@63
  1109
    }
dvander@63
  1110
dvander@55
  1111
    for (unsigned i = 0; i < node->arguments()->length(); i++) {
dvander@17
  1112
        // Note: we don't compute references unless the callee needs a
dvander@17
  1113
        // reference type.
dvander@14
  1114
        Expression *expression = node->arguments()->at(i);
dvander@40
  1115
        Local<Type> given(zone_, visitAndApplyType(expression));
dvander@14
  1116
        if (!given)
dvander@14
  1117
            return;
dvander@14
  1118
dvander@71
  1119
        // Since we skip a load, check for a call expression that returns void.
dvander@71
  1120
        if (given->isVoid()) {
dvander@71
  1121
            assert(expression->isCallExpression());
dvander@71
  1122
            CallExpression *call = expression->toCallExpression();
dvander@71
  1123
            cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
dvander@71
  1124
            return;
dvander@71
  1125
        }
dvander@71
  1126
        
dvander@68
  1127
        bool mustComputeReference;
dvander@68
  1128
        if (i >= type->parameters()->length()) {
dvander@68
  1129
            // Special handling for natives. Arguments past the formal must
dvander@68
  1130
            // always have references computed. However, arrays are already
dvander@68
  1131
            // references for natives.  
dvander@68
  1132
            assert(type->isNative() && type->isNativeVariadic());
dvander@68
  1133
            mustComputeReference = !given->isReference() && !given->isArray();
dvander@68
  1134
        } else {
dvander@68
  1135
            Local<Type> actual(zone_, type->parameterAt(i));
dvander@68
  1136
            if (!typeCheckParameter(expression, given, actual))
dvander@68
  1137
                return;
dvander@68
  1138
            mustComputeReference = actual->isReference() && !given->isReference();
dvander@68
  1139
        }
dvander@14
  1140
dvander@14
  1141
        // If the actual is a reference, and the given is not, we'll need to
dvander@14
  1142
        // compute a reference, which may be allocated on the stack.
dvander@68
  1143
        if (mustComputeReference)
dvander@14
  1144
            scope_->setUsesLifoHeap();
dvander@14
  1145
    }
dvander@66
  1146
dvander@66
  1147
    node->setType(fun->type()->returnType());
dvander@0
  1148
}
dvander@0
  1149
dvander@0
  1150
void
dvander@71
  1151
SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
dvander@71
  1152
{
dvander@71
  1153
    // If both sides terminate in a return, we consider this a return as well.
dvander@71
  1154
    if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
dvander@71
  1155
        terminate(Returns_Always);
dvander@71
  1156
        return;
dvander@71
  1157
    }
dvander@71
  1158
dvander@71
  1159
    ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
dvander@71
  1160
                          ? Returns_Never
dvander@71
  1161
                          : Returns_Sometimes;
dvander@71
  1162
dvander@71
  1163
    if (left.terminates() && right.terminates())
dvander@71
  1164
        terminate(status);
dvander@71
  1165
    else
dvander@71
  1166
        returns(status);
dvander@71
  1167
}
dvander@71
  1168
dvander@71
  1169
void
dvander@0
  1170
SemanticAnalysis::visit(IfStatement *node)
dvander@0
  1171
{
dvander@40
  1172
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
  1173
    if (!type)
dvander@25
  1174
        return;
dvander@25
  1175
dvander@25
  1176
    if (!canTest(node, type))
dvander@25
  1177
        return;
dvander@25
  1178
dvander@71
  1179
    ControlStatus trueBranch = visitForControl(node->ifTrue());
dvander@71
  1180
    ControlStatus falseBranch = ControlStatus(false, Returns_Never);
dvander@71
  1181
dvander@10
  1182
    if (node->ifFalse())
dvander@71
  1183
        falseBranch = visitForControl(node->ifFalse());
dvander@71
  1184
dvander@71
  1185
    control_->merge(trueBranch, falseBranch);
dvander@0
  1186
}
dvander@0
  1187
dvander@0
  1188
void
dvander@0
  1189
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
  1190
{
dvander@71
  1191
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@40
  1192
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@0
  1193
dvander@25
  1194
    if (!left || !right)
dvander@25
  1195
        return;
dvander@25
  1196
dvander@145
  1197
    if (!right->isInt32() && !right->isEnum()) {
dvander@25
  1198
        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
dvander@0
  1199
        return;
dvander@0
  1200
    }
dvander@25
  1201
    if (!left->isArray()) {
dvander@25
  1202
        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
dvander@0
  1203
        return;
dvander@0
  1204
    }
dvander@160
  1205
dvander@160
  1206
    // Note: char arrays are automatically up-casted to return an int32.
dvander@160
  1207
    if (left->isCharArray())
dvander@160
  1208
        node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@160
  1209
    else
dvander@160
  1210
        node->setType(left->contained());
dvander@0
  1211
}
dvander@2
  1212
dvander@2
  1213
void
dvander@148
  1214
SemanticAnalysis::visit(FieldExpression *node)
dvander@148
  1215
{
dvander@148
  1216
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@148
  1217
    if (!left)
dvander@148
  1218
        return;
dvander@148
  1219
dvander@148
  1220
    if (!left->isStruct()) {
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
    Local<String> field(zone_, node->field());
dvander@148
  1227
dvander@148
  1228
    unsigned offset;
dvander@148
  1229
    Local<Descriptor> desc(zone_, left->lookupField(field, &offset));
dvander@148
  1230
    if (!desc) {
dvander@148
  1231
        cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
dvander@148
  1232
                        GetTypeName(left));
dvander@148
  1233
        return;
dvander@148
  1234
    }
dvander@148
  1235
dvander@148
  1236
    node->setFieldIndex(offset);
dvander@148
  1237
    node->setType(desc->type());
dvander@148
  1238
}
dvander@148
  1239
dvander@148
  1240
void
dvander@2
  1241
SemanticAnalysis::visit(EnumStatement *node)
dvander@2
  1242
{
dvander@145
  1243
    Local<Type> type(zone_, node->decl()->type());
dvander@3
  1244
dvander@145
  1245
    assert(type);
dvander@2
  1246
dvander@2
  1247
    int value = 0;
dvander@57
  1248
    for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@2
  1249
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@2
  1250
dvander@2
  1251
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@2
  1252
        if (entry.expr) {
dvander@2
  1253
            entry.expr->accept(this);
dvander@25
  1254
            if (!EvaluateForConstant(entry.expr, &box)) {
dvander@25
  1255
                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@25
  1256
                return;
dvander@25
  1257
            }
dvander@2
  1258
dvander@2
  1259
            assert(box.type() == PrimitiveType_Int32);
dvander@2
  1260
            value = box.toInt();
dvander@2
  1261
        }
dvander@2
  1262
dvander@2
  1263
        entry.name->set(type, box);
dvander@2
  1264
        value++;
dvander@2
  1265
    }
dvander@2
  1266
}
dvander@4
  1267
dvander@4
  1268
void
dvander@146
  1269
SemanticAnalysis::visit(StructureStatement *node)
dvander@146
  1270
{
dvander@146
  1271
    // If this node already has a type, it was pre-analyzed, so skip it.
dvander@146
  1272
    if (node->decl()->type())
dvander@146
  1273
        return;
dvander@146
  1274
dvander@146
  1275
    FieldList *fields = node->fields();
dvander@146
  1276
    Local<FixedArray> desctable(zone_, FixedArray::New(zone_, fields->length(), Heap::Tenure_Old));
dvander@146
  1277
    if (!desctable)
dvander@146
  1278
        return;
dvander@146
  1279
dvander@153
  1280
    Vector<unsigned> composedList;
dvander@146
  1281
    StructureBufferBuilder builder;
dvander@146
  1282
dvander@146
  1283
    Local<Type> type(zone_);
dvander@146
  1284
    Local<String> name(zone_);
dvander@146
  1285
    Local<Descriptor> desc(zone_);
dvander@146
  1286
    for (size_t i = 0; i < fields->length(); i++) {
dvander@146
  1287
        StructureStatement::Field *field = fields->at(i);
dvander@146
  1288
dvander@146
  1289
        type = bindType(field->pos(), field->type());
dvander@146
  1290
        if (!type)
dvander@146
  1291
            return;
dvander@146
  1292
dvander@159
  1293
        if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
dvander@159
  1294
            cc_.reportError(field->pos(), Message_CannotDeclareStringCell);
dvander@159
  1295
            return;
dvander@159
  1296
        }
dvander@159
  1297
dvander@146
  1298
        unsigned offset;
dvander@146
  1299
        if (!builder.add(type, &offset))
dvander@146
  1300
            return;
dvander@146
  1301
dvander@146
  1302
        name = field->name();
dvander@146
  1303
        desc = Descriptor::New(zone_, name, type, offset);
dvander@146
  1304
        if (!desc)
dvander@146
  1305
            return;
dvander@146
  1306
dvander@146
  1307
        desctable->set(zone_, i, desc);
dvander@153
  1308
dvander@153
  1309
        if (type->isStruct() || type->isArray()) {
dvander@153
  1310
            if (!composedList.append(i))
dvander@153
  1311
                return;
dvander@153
  1312
        }
dvander@146
  1313
    }
dvander@146
  1314
dvander@153
  1315
    Local<FixedArray> composed(zone_);
dvander@153
  1316
    if (composedList.length()) {
dvander@153
  1317
        composed = FixedArray::New(zone_, composedList.length(), Heap::Tenure_Old);
dvander@153
  1318
        if (!composed)
dvander@153
  1319
            return;
dvander@153
  1320
dvander@153
  1321
        for (unsigned i = 0; i < composedList.length(); i++)
dvander@153
  1322
            composed->set(zone_, i, desctable->at(i));
dvander@153
  1323
    }
dvander@153
  1324
dvander@153
  1325
    Local<StructMap> map(zone_, StructMap::New(zone_, builder, composed));
dvander@147
  1326
    if (!map)
dvander@147
  1327
        return;
dvander@147
  1328
dvander@146
  1329
    name = node->decl()->name();
dvander@147
  1330
    type = zone_->types()->newStruct(name, desctable, map);
dvander@146
  1331
    if (!type)
dvander@146
  1332
        return;
dvander@146
  1333
dvander@147
  1334
    map->setType(type);
dvander@146
  1335
    node->decl()->setType(type);
dvander@146
  1336
}
dvander@146
  1337
dvander@146
  1338
void
dvander@21
  1339
SemanticAnalysis::visit(StringLiteral *node)
dvander@21
  1340
{
dvander@40
  1341
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
dvander@21
  1342
    if (!type)
dvander@21
  1343
        return;
dvander@21
  1344
dvander@30
  1345
    type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
dvander@21
  1346
    if (!type)
dvander@21
  1347
        return;
dvander@21
  1348
dvander@21
  1349
    node->setType(type);
dvander@21
  1350
}
dvander@21
  1351
dvander@21
  1352
void
dvander@4
  1353
SemanticAnalysis::visit(FloatLiteral *node)
dvander@4
  1354
{
dvander@40
  1355
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
dvander@4
  1356
    if (!type)
dvander@4
  1357
        return;
dvander@4
  1358
dvander@4
  1359
    node->setType(type);
dvander@4
  1360
}
dvander@10
  1361
dvander@10
  1362
void
dvander@10
  1363
SemanticAnalysis::visit(BreakStatement *node)
dvander@10
  1364
{
dvander@71
  1365
    if (!loop_) {
dvander@25
  1366
        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
dvander@71
  1367
        return;
dvander@71
  1368
    }
dvander@71
  1369
dvander@71
  1370
    // Note: ignore breaks that occur in unreachable control-flow.
dvander@71
  1371
    if (!control_->status().terminates())
dvander@71
  1372
        loop_->addBreak();
dvander@71
  1373
dvander@71
  1374
    control_->terminate(Returns_Never);
dvander@10
  1375
}
dvander@10
  1376
dvander@10
  1377
void
dvander@10
  1378
SemanticAnalysis::visit(ContinueStatement *node)
dvander@10
  1379
{
dvander@71
  1380
    if (!loop_) {
dvander@25
  1381
        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
dvander@71
  1382
        return;
dvander@71
  1383
    }
dvander@71
  1384
dvander@71
  1385
    // Note: ignore continues that occur in unreachable control-flow.
dvander@71
  1386
    if (!control_->status().terminates())
dvander@71
  1387
        loop_->addContinue();
dvander@71
  1388
dvander@71
  1389
    control_->terminate(Returns_Never);
dvander@10
  1390
}