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