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