jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jul 10 02:11:13 2012 -0700 (2012-07-10)
changeset 68 b40b0e18a918
parent 67 b765a6383849
child 71 f7e573226c2b
permissions -rw-r--r--
Added support for ISourcePawnEngine natives.
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@12
   103
    loopDepth_(0),
dvander@12
   104
    scope_(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@14
   150
    }
dvander@25
   151
dvander@7
   152
    return expression->type();
dvander@7
   153
}
dvander@7
   154
dvander@7
   155
Type *
dvander@7
   156
SemanticAnalysis::visitForRef(Expression *expression)
dvander@7
   157
{
dvander@7
   158
    expression->accept(this);
dvander@7
   159
    return expression->type();
dvander@7
   160
}
dvander@7
   161
dvander@54
   162
// :TODO: this leaks an interior pointer.
dvander@25
   163
static inline const char *
dvander@25
   164
GetTypeName(Type *type)
dvander@4
   165
{
dvander@25
   166
    if (type->isArray())
dvander@25
   167
        return "array";
dvander@25
   168
    if (type->isFunction())
dvander@25
   169
        return "function";
dvander@25
   170
    if (type->isReference())
dvander@25
   171
        type = type->contained();
dvander@25
   172
    if (type->tag())
dvander@54
   173
        return type->tag()->chars();
dvander@25
   174
    return "int";
dvander@4
   175
}
dvander@4
   176
dvander@25
   177
void
dvander@40
   178
SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
dvander@21
   179
{
dvander@25
   180
    const char *op = TokenNames[token];
dvander@25
   181
    const char *name = GetTypeName(type);
dvander@21
   182
dvander@25
   183
    cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
dvander@21
   184
}
dvander@21
   185
dvander@25
   186
void
dvander@40
   187
SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@22
   188
{
dvander@25
   189
    const char *op = TokenNames[token];
dvander@25
   190
    const char *leftName = GetTypeName(left);
dvander@25
   191
    const char *rightName = GetTypeName(right);
dvander@22
   192
dvander@25
   193
    cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
dvander@25
   194
}
dvander@25
   195
dvander@25
   196
Type *
dvander@40
   197
SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@25
   198
{
dvander@22
   199
    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
dvander@22
   200
        (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
dvander@22
   201
    {
dvander@22
   202
        // If either side is a float, the other side must be a float or int.
dvander@22
   203
        if (left->isFloat() || right->isFloat()) {
dvander@25
   204
            Type *floatType = left->isFloat() ? left : right;
dvander@25
   205
            Type *other = left->isFloat() ? right : left;
dvander@25
   206
            if (other->isFloat() || (other->isInt32() && !other->tag()))
dvander@28
   207
                return floatType;
dvander@22
   208
        }
dvander@22
   209
    }
dvander@22
   210
dvander@25
   211
    if ((!left->isInt32() || left->tag()) ||
dvander@25
   212
        (!right->isInt32() || right->tag()))
dvander@25
   213
    {
dvander@25
   214
        binaryTypeError(node, token, left, right);
dvander@25
   215
        return NULL;
dvander@25
   216
    }
dvander@25
   217
dvander@22
   218
    return left;
dvander@22
   219
}
dvander@22
   220
dvander@25
   221
bool
dvander@40
   222
SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
dvander@25
   223
{
dvander@25
   224
    if (type->isArray()) {
dvander@25
   225
        cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
dvander@25
   226
        return false;
dvander@25
   227
    }
dvander@25
   228
    return true;
dvander@25
   229
}
dvander@25
   230
dvander@23
   231
Type *
dvander@23
   232
SemanticAnalysis::visitForLValue(Expression *expression)
dvander@23
   233
{
dvander@23
   234
    if (expression->isIndexExpression()) {
dvander@25
   235
        Type *type = visitAndApplyType(expression);
dvander@25
   236
        if (!type)
dvander@23
   237
            return NULL;
dvander@25
   238
dvander@67
   239
        if (type->isConst()) {
dvander@67
   240
            cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@67
   241
            return NULL;
dvander@67
   242
        }
dvander@67
   243
dvander@25
   244
        return type->contained();
dvander@23
   245
    }
dvander@23
   246
dvander@23
   247
    if (!expression->isNameProxy()) {
dvander@25
   248
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   249
        return NULL;
dvander@23
   250
    }
dvander@23
   251
dvander@23
   252
    NameProxy *proxy = expression->toNameProxy();
dvander@23
   253
    if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@25
   254
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@23
   255
        return NULL;
dvander@23
   256
    }
dvander@23
   257
dvander@23
   258
    Variable *var = proxy->binding()->toVariable();
dvander@23
   259
    if (!var->type())
dvander@23
   260
        return NULL;
dvander@23
   261
dvander@67
   262
    if  (var->type()->isReference()) {
dvander@67
   263
        if (var->type()->isConst()) {
dvander@67
   264
            cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@67
   265
            return NULL;
dvander@67
   266
        }
dvander@23
   267
        return var->type()->contained();
dvander@67
   268
    }
dvander@23
   269
    return var->type();
dvander@23
   270
}
dvander@23
   271
dvander@0
   272
void
dvander@25
   273
SemanticAnalysis::visit(NameProxy *name)
dvander@25
   274
{
dvander@25
   275
    name->setType(name->binding()->type());
dvander@25
   276
}
dvander@25
   277
dvander@25
   278
void
dvander@0
   279
SemanticAnalysis::visit(Assignment *node)
dvander@0
   280
{
dvander@40
   281
    Local<Type> exprType(zone_, visitForLoad(node->expression()));
dvander@25
   282
    if (!exprType)
dvander@25
   283
        return ;
dvander@0
   284
dvander@40
   285
    Local<Type> type(zone_, visitForLValue(node->lvalue()));
dvander@23
   286
    if (!type)
dvander@23
   287
        return;
dvander@4
   288
dvander@25
   289
    if (node->token() != TOK_ASSIGN) {
dvander@25
   290
        if (!typeCheckBinary(node, node->token(), type, exprType))
dvander@25
   291
            return;
dvander@25
   292
    }
dvander@22
   293
dvander@25
   294
    if (!typeCheckAssignment(node, exprType, type, true))
dvander@25
   295
        return;
dvander@25
   296
dvander@25
   297
    node->setType(type);
dvander@0
   298
}
dvander@0
   299
dvander@0
   300
void
dvander@23
   301
SemanticAnalysis::visit(IncDecExpression *node)
dvander@23
   302
{
dvander@40
   303
    Local<Type> type(zone_, visitForLValue(node->expression()));
dvander@23
   304
    if (!type)
dvander@23
   305
        return;
dvander@23
   306
dvander@23
   307
    assert(!type->isReference());
dvander@25
   308
dvander@25
   309
    if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
dvander@25
   310
        unaryTypeError(node, node->token(), type);
dvander@23
   311
        return;
dvander@23
   312
    }
dvander@23
   313
dvander@23
   314
    node->setType(type);
dvander@23
   315
}
dvander@23
   316
dvander@23
   317
void
dvander@0
   318
SemanticAnalysis::visit(BinaryExpression *node)
dvander@0
   319
{
dvander@40
   320
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@40
   321
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@25
   322
    if (!left || !right)
dvander@25
   323
        return;
dvander@4
   324
dvander@40
   325
    Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
dvander@25
   326
    if (!result)
dvander@25
   327
        return;
dvander@25
   328
dvander@22
   329
    node->setType(result);
dvander@0
   330
}
dvander@0
   331
dvander@0
   332
void
dvander@0
   333
SemanticAnalysis::visit(ReturnStatement *node)
dvander@0
   334
{
dvander@40
   335
    Local<Type> type(zone_, visitForLoad(node->expression()));
dvander@25
   336
    if (!type)
dvander@25
   337
        return;
dvander@0
   338
dvander@40
   339
    Local<Type> returnType(zone_, function_->returnType());
dvander@40
   340
    if (!typeCheckAssignment(node, type, returnType, true))
dvander@25
   341
        return;
dvander@0
   342
}
dvander@0
   343
dvander@0
   344
void
dvander@0
   345
SemanticAnalysis::visit(ForStatement *node)
dvander@0
   346
{
dvander@10
   347
    loopDepth_++;
dvander@12
   348
    if (node->scope())
dvander@12
   349
        scope_ = node->scope();
dvander@25
   350
dvander@22
   351
    if (node->initialization())
dvander@22
   352
        node->initialization()->accept(this);
dvander@25
   353
dvander@25
   354
    if (node->condition()) {
dvander@40
   355
        Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
   356
        if (!type || !canTest(node->condition(), type)) {
dvander@25
   357
            loopDepth_--;
dvander@25
   358
            return;
dvander@25
   359
        }
dvander@25
   360
    }
dvander@25
   361
dvander@0
   362
    if (node->update())
dvander@0
   363
        node->update()->accept(this);
dvander@25
   364
dvander@0
   365
    node->body()->accept(this);
dvander@25
   366
dvander@12
   367
    if (node->scope())
dvander@12
   368
        scope_ = scope_->enclosing();
dvander@10
   369
    loopDepth_--;
dvander@0
   370
}
dvander@0
   371
dvander@9
   372
void 
dvander@9
   373
SemanticAnalysis::visit(WhileStatement *node)
dvander@9
   374
{
dvander@10
   375
    loopDepth_++;
dvander@25
   376
dvander@40
   377
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
   378
    if (!type || !canTest(node->condition(), type)) {
dvander@25
   379
        loopDepth_--;
dvander@25
   380
        return;
dvander@25
   381
    }
dvander@25
   382
dvander@9
   383
    node->body()->accept(this);
dvander@10
   384
    loopDepth_--;
dvander@9
   385
}
dvander@9
   386
dvander@0
   387
void
dvander@0
   388
SemanticAnalysis::visit(BlockStatement *node)
dvander@0
   389
{
dvander@12
   390
    if (node->scope())
dvander@12
   391
        scope_ = node->scope();
dvander@0
   392
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@0
   393
        Statement *statement = node->statements()->at(i);
dvander@0
   394
        statement->accept(this);
dvander@0
   395
    }
dvander@12
   396
    if (node->scope())
dvander@12
   397
        scope_ = scope_->enclosing();
dvander@0
   398
}
dvander@0
   399
dvander@0
   400
void
dvander@0
   401
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@0
   402
{
dvander@54
   403
    Local<String> tag(zone_, node->tag());
dvander@54
   404
    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@0
   405
    if (!type)
dvander@0
   406
        return;
dvander@0
   407
dvander@0
   408
    if (node->postDimensions()) {
dvander@37
   409
        Local<Type> init(zone_);
dvander@21
   410
        if (node->initialization()) {
dvander@25
   411
            if ((init = visitAndApplyType(node->initialization())) == NULL)
dvander@21
   412
                return;
dvander@21
   413
        }
dvander@21
   414
dvander@55
   415
        if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@25
   416
            cc_.reportError(node->pos(), Message_MaximumArrayDepth);
dvander@0
   417
            return;
dvander@0
   418
        }
dvander@0
   419
dvander@21
   420
        // If we have an initializer, make sure it's the same type.
dvander@55
   421
        if (init && node->postDimensions()->length() != init->levels()) {
dvander@25
   422
            cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
dvander@25
   423
            return;
dvander@21
   424
        }
dvander@21
   425
dvander@37
   426
        Local<Type> check(zone_, init);
dvander@55
   427
        for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
dvander@0
   428
            Expression *expr = node->postDimensions()->at(i);
dvander@25
   429
            int size = -1;
dvander@0
   430
dvander@25
   431
            if (expr) {
dvander@37
   432
                Local<Type> exprType(zone_, visitForLoad(expr));
dvander@25
   433
                if (!exprType)
dvander@25
   434
                    return;
dvander@0
   435
dvander@25
   436
                if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
dvander@25
   437
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   438
                    return;
dvander@0
   439
                }
dvander@25
   440
dvander@25
   441
                BoxedPrimitive box;
dvander@25
   442
                if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@25
   443
                    size = box.toInt();
dvander@25
   444
                    if (size <= 0) {
dvander@25
   445
                        cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@25
   446
                        return;
dvander@25
   447
                    }
dvander@25
   448
                    if (size >= INT_MAX / sizeof(int)) {
dvander@25
   449
                        cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
dvander@25
   450
                        return;
dvander@25
   451
                    }
dvander@25
   452
dvander@25
   453
                    if (check) {
dvander@25
   454
                        if (check->elements() == -1) {
dvander@25
   455
                            cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   456
                            return;
dvander@25
   457
                        }
dvander@25
   458
dvander@25
   459
                        if (check->isCharArray()) {
dvander@25
   460
                            if (check->elements() > size) {
dvander@25
   461
                                cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   462
                                return;
dvander@25
   463
                            }
dvander@25
   464
                        } else if (check->elements() != size) {
dvander@25
   465
                            cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
dvander@25
   466
                            return;
dvander@25
   467
                        }
dvander@25
   468
                    }
dvander@25
   469
                } else {
dvander@25
   470
                    if (init) {
dvander@25
   471
                        cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
dvander@25
   472
                        return;
dvander@25
   473
                    }
dvander@25
   474
dvander@25
   475
                    // here until we get dynamic array support.
dvander@25
   476
                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@0
   477
                    return;
dvander@0
   478
                }
dvander@21
   479
            } else {
dvander@25
   480
                // Infer the size from the initializer.
dvander@25
   481
                if (!init) {
dvander@25
   482
                    cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
dvander@25
   483
                    return;
dvander@25
   484
                }
dvander@25
   485
                if (init->elements() == -1) {
dvander@25
   486
                    cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
dvander@25
   487
                    return;
dvander@25
   488
                }
dvander@25
   489
                size = init->elements();
dvander@0
   490
            }
dvander@0
   491
dvander@67
   492
            type = zone_->types()->unsafeArray(type, size, false);
dvander@25
   493
            if (!type)
dvander@25
   494
                return;
dvander@21
   495
dvander@21
   496
            if (check)
dvander@21
   497
                check = check->contained();
dvander@0
   498
        }
dvander@12
   499
dvander@12
   500
        // Right now, any array is allowed on the LIFO heap. In case the
dvander@12
   501
        // runtime actually decides to use the LIFO heap, we must reserve
dvander@12
   502
        // a slot so we can unwind the heap when the current scope leaves.
dvander@12
   503
        scope_->setUsesLifoHeap();
dvander@8
   504
    } else {
dvander@10
   505
        if (node->initialization()) {
dvander@40
   506
            Local<Type> right(zone_, visitForLoad(node->initialization()));
dvander@25
   507
            if (!right)
dvander@25
   508
                return;
dvander@25
   509
            if (!typeCheckAssignment(node, type, right, true))
dvander@25
   510
                return;
dvander@10
   511
        }
dvander@21
   512
        if (type->primitive() == PrimitiveType_Char) {
dvander@25
   513
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@21
   514
            return;
dvander@21
   515
        }
dvander@0
   516
    }
dvander@0
   517
dvander@0
   518
    node->variable()->setType(type);
dvander@0
   519
}
dvander@0
   520
dvander@0
   521
void
dvander@4
   522
SemanticAnalysis::visit(IntegerLiteral *node)
dvander@0
   523
{
dvander@30
   524
    node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@0
   525
}
dvander@0
   526
dvander@0
   527
void
dvander@0
   528
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@0
   529
{
dvander@0
   530
    node->expression()->accept(this);
dvander@0
   531
}
dvander@0
   532
dvander@14
   533
bool
dvander@14
   534
SemanticAnalysis::preanalyze(FunctionStatement *node)
dvander@14
   535
{
dvander@57
   536
    Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
dvander@14
   537
    if (!args)
dvander@14
   538
        return false;
dvander@14
   539
dvander@14
   540
    // Apply types to arguments.
dvander@57
   541
    for (size_t i = 0; i < node->parameters()->length(); i++) {
dvander@14
   542
        Parameter *parameter = node->parameters()->at(i);
dvander@14
   543
        
dvander@54
   544
        Local<String> tag(zone_, parameter->tag());
dvander@54
   545
        Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@14
   546
        if (!type)
dvander@14
   547
            return false;
dvander@14
   548
dvander@14
   549
        if (parameter->reference()) {
dvander@66
   550
            if (parameter->dimensions()) {
dvander@66
   551
                cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
dvander@66
   552
                return NULL;
dvander@66
   553
            }
dvander@66
   554
dvander@67
   555
            type = zone_->types()->getReference(type, parameter->isConst());
dvander@14
   556
            if (!type)
dvander@14
   557
                return false;
dvander@66
   558
        } else if (parameter->dimensions()) {
dvander@66
   559
            if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@68
   560
                cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
dvander@68
   561
                return false;
dvander@68
   562
            }
dvander@68
   563
dvander@68
   564
            if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
dvander@68
   565
                cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
dvander@66
   566
                return false;
dvander@66
   567
            }
dvander@66
   568
dvander@66
   569
            for (size_t i = parameter->dimensions()->length() - 1;
dvander@66
   570
                 i < parameter->dimensions()->length();
dvander@66
   571
                 i++)
dvander@66
   572
            {
dvander@66
   573
                int size = Type::UNKNOWN_SIZE;
dvander@66
   574
                if (Expression *expr = parameter->dimensions()->at(i)) {
dvander@66
   575
                    BoxedPrimitive box;
dvander@66
   576
                    if (!EvaluateForConstant(expr, &box)) {
dvander@66
   577
                        cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
dvander@66
   578
                        return false;
dvander@66
   579
                    }
dvander@66
   580
                    size = box.toInt();
dvander@66
   581
                }
dvander@66
   582
dvander@67
   583
                type = zone_->types()->unsafeArray(type, size, parameter->isConst());
dvander@66
   584
                if (!type)
dvander@66
   585
                    return false;
dvander@66
   586
            }
dvander@14
   587
        }
dvander@14
   588
dvander@68
   589
        if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
dvander@68
   590
            (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
dvander@68
   591
        {
dvander@68
   592
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@68
   593
            return false;
dvander@68
   594
        }
dvander@68
   595
dvander@30
   596
        args->set(zone_, i, type);
dvander@14
   597
        parameter->variable()->setType(type);
dvander@14
   598
    }
dvander@14
   599
dvander@37
   600
    Local<Type> returnType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@14
   601
    if (!returnType)
dvander@14
   602
        return false;
dvander@14
   603
dvander@68
   604
    Local<Type> funtype(zone_);
dvander@68
   605
    if (node->fun()->isNative())
dvander@68
   606
        funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
dvander@68
   607
    else
dvander@68
   608
        funtype = zone_->types()->newFunction(returnType, args);
dvander@14
   609
    if (!funtype)
dvander@14
   610
        return false;
dvander@63
   611
    
dvander@63
   612
    // If the function already has a type, it was forward declared before, and
dvander@63
   613
    // now this is our chance to type check the second declaration.
dvander@63
   614
    if (node->fun()->type()) {
dvander@63
   615
        Local<Type> forward(zone_, node->fun()->type());
dvander@63
   616
        if (!Type::Compare(funtype, forward)) {
dvander@63
   617
            cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
dvander@63
   618
            return false;
dvander@63
   619
        }
dvander@63
   620
        node->fun()->setForwardType(forward);
dvander@63
   621
    }
dvander@14
   622
dvander@14
   623
    node->fun()->setType(funtype);
dvander@63
   624
dvander@14
   625
    return true;
dvander@14
   626
}
dvander@14
   627
dvander@0
   628
void
dvander@0
   629
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   630
{
dvander@25
   631
    function_ = node->fun()->type();
dvander@12
   632
    scope_ = node->scope();
dvander@63
   633
    if (node->body())
dvander@63
   634
        node->body()->accept(this);
dvander@12
   635
    scope_ = NULL;
dvander@25
   636
    function_ = NULL;
dvander@0
   637
}
dvander@0
   638
dvander@25
   639
bool
dvander@40
   640
SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@14
   641
{
dvander@40
   642
    Local<Type> actual(zone_, argActual);
dvander@40
   643
    Local<Type> given(zone_, argGiven);
dvander@40
   644
dvander@25
   645
    if (!given->isArray()) {
dvander@25
   646
        cc_.reportError(node->pos(), Message_ExpectedArray);
dvander@25
   647
        return false;
dvander@25
   648
    }
dvander@25
   649
    if (given->levels() != actual->levels()) {
dvander@25
   650
        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
dvander@25
   651
        return false;
dvander@25
   652
    }
dvander@25
   653
dvander@25
   654
    unsigned level = 0;
dvander@25
   655
    while (given->isArray()) {
dvander@25
   656
        if (actual->elements() != -1) {
dvander@25
   657
            if (forAssign) {
dvander@25
   658
                if (given->elements() == -1 || actual->elements() == -1) {
dvander@25
   659
                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
dvander@25
   660
                    return false;
dvander@25
   661
                }
dvander@25
   662
dvander@25
   663
                if (actual->isCharArray()) {
dvander@25
   664
                    // String assignment can have a truncated |given|.
dvander@25
   665
                    if (given->elements() > actual->elements()) {
dvander@25
   666
                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
dvander@25
   667
                        return false;
dvander@25
   668
                    }
dvander@25
   669
                } else {
dvander@25
   670
                    if (given->elements() != actual->elements()) {
dvander@25
   671
                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   672
                        return false;
dvander@25
   673
                    }
dvander@25
   674
                }
dvander@25
   675
            } else {
dvander@25
   676
                if (actual->elements() != -1 && given->elements() != actual->elements()) {
dvander@25
   677
                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
dvander@25
   678
                    return false;
dvander@25
   679
                }
dvander@25
   680
            }
dvander@25
   681
        }
dvander@25
   682
        given = given->contained();
dvander@25
   683
        actual = actual->contained();
dvander@14
   684
    }
dvander@14
   685
dvander@25
   686
    if (given->primitive() != actual->primitive()) {
dvander@54
   687
        // :TODO: leaks an interior pointer.
dvander@54
   688
        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
dvander@54
   689
        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
dvander@25
   690
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   691
        return false;
dvander@25
   692
    }
dvander@25
   693
dvander@25
   694
    return true;
dvander@25
   695
}
dvander@25
   696
dvander@25
   697
bool
dvander@40
   698
SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
dvander@25
   699
{
dvander@40
   700
    Local<Type> actual(zone_, argActual);
dvander@40
   701
    Local<Type> given(zone_, argGiven);
dvander@40
   702
dvander@25
   703
    if (actual->isArray())
dvander@25
   704
        return typeCheckArrayAssignment(node, given, actual, forAssign);
dvander@25
   705
dvander@25
   706
    if (given->isArray()) {
dvander@25
   707
        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
dvander@25
   708
        return false;
dvander@25
   709
    }
dvander@25
   710
dvander@47
   711
    // The given type may not have been dereferenced.
dvander@47
   712
    if (given->isReference())
dvander@47
   713
        given = given->contained();
dvander@47
   714
    if (actual->isReference())
dvander@47
   715
        actual = actual->contained();
dvander@47
   716
dvander@47
   717
    if (!given->isPrimitive() || !actual->isPrimitive()) {
dvander@25
   718
        cc_.reportError(node->pos(), Message_UnsupportedType);
dvander@25
   719
        return false;
dvander@25
   720
    }
dvander@25
   721
    
dvander@25
   722
    if (given->primitive() != actual->primitive()) {
dvander@54
   723
        // :TODO: leaks an interior pointer
dvander@54
   724
        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
dvander@54
   725
        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
dvander@25
   726
        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
dvander@25
   727
        return false;
dvander@25
   728
    }
dvander@25
   729
dvander@25
   730
    return true;
dvander@25
   731
}
dvander@25
   732
dvander@25
   733
bool
dvander@40
   734
SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
dvander@25
   735
{
dvander@25
   736
    return typeCheckAssignment(node, given, actual, false);
dvander@14
   737
}
dvander@14
   738
dvander@0
   739
void
dvander@0
   740
SemanticAnalysis::visit(CallExpression *node)
dvander@0
   741
{
dvander@40
   742
    Local<Type> type(zone_, visitForLoad(node->callee()));
dvander@14
   743
    if (!type)
dvander@14
   744
        return;
dvander@14
   745
dvander@25
   746
    if (!type->isFunction()) {
dvander@25
   747
        cc_.reportError(node->pos(), Message_CalleeNotFunction);
dvander@25
   748
        return;
dvander@25
   749
    }
dvander@55
   750
    if (node->arguments()->length() != type->parameters()->length()) {
dvander@68
   751
        if (!type->isNative() ||
dvander@68
   752
            !type->isNativeVariadic() ||
dvander@68
   753
            node->arguments()->length() < type->parameters()->length())
dvander@68
   754
        {
dvander@68
   755
            cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
dvander@68
   756
            return;
dvander@68
   757
        }
dvander@25
   758
    }
dvander@14
   759
dvander@63
   760
    // Currently, only calls from a NameProxy are possible.
dvander@63
   761
    NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
dvander@63
   762
    if (fun->isForward()) {
dvander@63
   763
        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
dvander@63
   764
        return;
dvander@63
   765
    }
dvander@63
   766
dvander@55
   767
    for (unsigned i = 0; i < node->arguments()->length(); i++) {
dvander@17
   768
        // Note: we don't compute references unless the callee needs a
dvander@17
   769
        // reference type.
dvander@14
   770
        Expression *expression = node->arguments()->at(i);
dvander@40
   771
        Local<Type> given(zone_, visitAndApplyType(expression));
dvander@14
   772
        if (!given)
dvander@14
   773
            return;
dvander@14
   774
dvander@17
   775
        // If it's an IndexExpression, we special case the ability to compute
dvander@25
   776
        // a reference.
dvander@17
   777
        if (expression->isIndexExpression())
dvander@17
   778
            given = given->contained();
dvander@17
   779
dvander@68
   780
        bool mustComputeReference;
dvander@68
   781
        if (i >= type->parameters()->length()) {
dvander@68
   782
            // Special handling for natives. Arguments past the formal must
dvander@68
   783
            // always have references computed. However, arrays are already
dvander@68
   784
            // references for natives.  
dvander@68
   785
            assert(type->isNative() && type->isNativeVariadic());
dvander@68
   786
            mustComputeReference = !given->isReference() && !given->isArray();
dvander@68
   787
        } else {
dvander@68
   788
            Local<Type> actual(zone_, type->parameterAt(i));
dvander@68
   789
            if (!typeCheckParameter(expression, given, actual))
dvander@68
   790
                return;
dvander@68
   791
            mustComputeReference = actual->isReference() && !given->isReference();
dvander@68
   792
        }
dvander@14
   793
dvander@14
   794
        // If the actual is a reference, and the given is not, we'll need to
dvander@14
   795
        // compute a reference, which may be allocated on the stack.
dvander@68
   796
        if (mustComputeReference)
dvander@14
   797
            scope_->setUsesLifoHeap();
dvander@14
   798
    }
dvander@66
   799
dvander@66
   800
    node->setType(fun->type()->returnType());
dvander@0
   801
}
dvander@0
   802
dvander@0
   803
void
dvander@0
   804
SemanticAnalysis::visit(IfStatement *node)
dvander@0
   805
{
dvander@40
   806
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@25
   807
    if (!type)
dvander@25
   808
        return;
dvander@25
   809
dvander@25
   810
    if (!canTest(node, type))
dvander@25
   811
        return;
dvander@25
   812
dvander@10
   813
    node->ifTrue()->accept(this);
dvander@10
   814
    if (node->ifFalse())
dvander@10
   815
        node->ifFalse()->accept(this);
dvander@0
   816
}
dvander@0
   817
dvander@0
   818
void
dvander@0
   819
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
   820
{
dvander@40
   821
    Local<Type> left(zone_, visitForRef(node->left()));
dvander@40
   822
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@0
   823
dvander@25
   824
    if (!left || !right)
dvander@25
   825
        return;
dvander@25
   826
dvander@25
   827
    if (!right->isInt32()) {
dvander@25
   828
        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
dvander@0
   829
        return;
dvander@0
   830
    }
dvander@25
   831
    if (!left->isArray()) {
dvander@25
   832
        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
dvander@0
   833
        return;
dvander@0
   834
    }
dvander@7
   835
    node->setType(left);
dvander@0
   836
}
dvander@2
   837
dvander@2
   838
void
dvander@2
   839
SemanticAnalysis::visit(EnumStatement *node)
dvander@2
   840
{
dvander@25
   841
    // Forbid the blessed types.
dvander@54
   842
    Local<String> tag(zone_, node->name());
dvander@54
   843
    if (!strcmp(tag->chars(), "Float") ||
dvander@54
   844
        !strcmp(tag->chars(), "String") ||
dvander@54
   845
        !strcmp(tag->chars(), "any") ||
dvander@54
   846
        !strcmp(tag->chars(), "bool"))
dvander@25
   847
    {
dvander@25
   848
        cc_.reportError(node->pos(), Message_InvalidEnumName);
dvander@25
   849
        return;
dvander@25
   850
    }
dvander@3
   851
dvander@40
   852
    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
dvander@2
   853
    if (!type)
dvander@2
   854
        return;
dvander@2
   855
dvander@2
   856
    int value = 0;
dvander@57
   857
    for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@2
   858
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@2
   859
dvander@2
   860
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@2
   861
        if (entry.expr) {
dvander@2
   862
            entry.expr->accept(this);
dvander@25
   863
            if (!EvaluateForConstant(entry.expr, &box)) {
dvander@25
   864
                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@25
   865
                return;
dvander@25
   866
            }
dvander@2
   867
dvander@2
   868
            assert(box.type() == PrimitiveType_Int32);
dvander@2
   869
            value = box.toInt();
dvander@2
   870
        }
dvander@2
   871
dvander@2
   872
        entry.name->set(type, box);
dvander@2
   873
        value++;
dvander@2
   874
    }
dvander@2
   875
}
dvander@4
   876
dvander@4
   877
void
dvander@21
   878
SemanticAnalysis::visit(StringLiteral *node)
dvander@21
   879
{
dvander@40
   880
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
dvander@21
   881
    if (!type)
dvander@21
   882
        return;
dvander@21
   883
dvander@30
   884
    type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
dvander@21
   885
    if (!type)
dvander@21
   886
        return;
dvander@21
   887
dvander@21
   888
    node->setType(type);
dvander@21
   889
}
dvander@21
   890
dvander@21
   891
void
dvander@4
   892
SemanticAnalysis::visit(FloatLiteral *node)
dvander@4
   893
{
dvander@40
   894
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
dvander@4
   895
    if (!type)
dvander@4
   896
        return;
dvander@4
   897
dvander@4
   898
    node->setType(type);
dvander@4
   899
}
dvander@10
   900
dvander@10
   901
void
dvander@10
   902
SemanticAnalysis::visit(BreakStatement *node)
dvander@10
   903
{
dvander@25
   904
    if (loopDepth_ == 0)
dvander@25
   905
        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
dvander@10
   906
}
dvander@10
   907
dvander@10
   908
void
dvander@10
   909
SemanticAnalysis::visit(ContinueStatement *node)
dvander@10
   910
{
dvander@25
   911
    if (loopDepth_ == 0)
dvander@25
   912
        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
dvander@10
   913
}