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