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