jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 01 18:21:15 2012 -0700 (2012-07-01)
changeset 23 8a31742781c1
parent 22 765ab1b672a3
child 25 23e8b3d8e4e6
permissions -rw-r--r--
Implement ++ and -- operators.
dvander@0
     1
/*
dvander@0
     2
 * Copyright (C) 2012 David Anderson
dvander@0
     3
 *
dvander@0
     4
 * This file is part of JITCraft.
dvander@0
     5
 *
dvander@0
     6
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     7
 * the terms of the GNU General Public License as published by the Free
dvander@0
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
     9
 * any later version.
dvander@0
    10
 * 
dvander@0
    11
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    14
 *
dvander@0
    15
 * You should have received a copy of the GNU General Public License along with
dvander@0
    16
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    17
 */
dvander@0
    18
#include "SemanticAnalysis.h"
dvander@0
    19
#include "Types.h"
dvander@11
    20
#include "Zone.h"
dvander@11
    21
#include "TypeManager.h"
dvander@12
    22
#include "Scopes.h"
dvander@0
    23
dvander@0
    24
using namespace jc;
dvander@0
    25
dvander@2
    26
static inline bool
dvander@2
    27
IsPrimitiveType(Type *type, PrimitiveType primitive)
dvander@2
    28
{
dvander@2
    29
    if (!type)
dvander@2
    30
        return false;
dvander@2
    31
dvander@2
    32
    if (!type->isPrimitive())
dvander@2
    33
        return false;
dvander@2
    34
dvander@2
    35
    return primitive == type->primitive();
dvander@2
    36
}
dvander@2
    37
dvander@2
    38
static inline bool
dvander@2
    39
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@2
    40
                        BoxedPrimitive *out)
dvander@2
    41
{
dvander@2
    42
    switch (kind) {
dvander@2
    43
      case TOK_PLUS:
dvander@2
    44
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@2
    45
        return true;
dvander@2
    46
dvander@2
    47
      case TOK_SHL:
dvander@2
    48
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@2
    49
        return true;
dvander@2
    50
    }
dvander@2
    51
dvander@2
    52
    return true;
dvander@2
    53
}
dvander@2
    54
dvander@2
    55
static bool
dvander@2
    56
EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
dvander@2
    57
{
dvander@2
    58
    switch (expression->kind()) {
dvander@2
    59
      case AstNode::kBinaryExpression:
dvander@2
    60
      {
dvander@2
    61
        BoxedPrimitive left;
dvander@2
    62
        BoxedPrimitive right;
dvander@2
    63
        BinaryExpression *b = expression->toBinaryExpression();
dvander@2
    64
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@2
    65
            !EvaluateForConstant(b->right(), &right))
dvander@2
    66
        {
dvander@2
    67
            return false;
dvander@2
    68
        }
dvander@2
    69
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@2
    70
      }
dvander@2
    71
dvander@2
    72
      case AstNode::kNameProxy:
dvander@2
    73
      {
dvander@2
    74
        NameProxy *proxy = expression->toNameProxy();
dvander@2
    75
        if (proxy->binding()->kind() != BoundName::CONSTANT)
dvander@2
    76
            return false;
dvander@2
    77
dvander@2
    78
        NamedConstant *c = proxy->binding()->toNamedConstant();
dvander@2
    79
        if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
dvander@2
    80
            return false;
dvander@2
    81
dvander@2
    82
        *out = c->value();
dvander@2
    83
        return true;
dvander@2
    84
      }
dvander@2
    85
dvander@4
    86
      case AstNode::kIntegerLiteral:
dvander@4
    87
        *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
dvander@2
    88
        return true;
dvander@2
    89
dvander@2
    90
      default:
dvander@2
    91
        return false;
dvander@2
    92
    }
dvander@2
    93
}
dvander@2
    94
dvander@0
    95
SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
dvander@10
    96
  : tree_(tree),
dvander@12
    97
    loopDepth_(0),
dvander@12
    98
    scope_(NULL)
dvander@0
    99
{
dvander@0
   100
}
dvander@0
   101
dvander@0
   102
bool
dvander@0
   103
SemanticAnalysis::analyze()
dvander@0
   104
{
dvander@0
   105
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@0
   106
        Statement *statement = tree_->statements()->at(i);
dvander@0
   107
        statement->accept(this);
dvander@0
   108
    }
dvander@0
   109
dvander@0
   110
    return true;
dvander@0
   111
}
dvander@0
   112
dvander@0
   113
void
dvander@0
   114
SemanticAnalysis::visit(NameProxy *name)
dvander@0
   115
{
dvander@0
   116
    name->setType(name->binding()->type());
dvander@0
   117
}
dvander@0
   118
dvander@7
   119
Type *
dvander@7
   120
SemanticAnalysis::visitForLoad(Expression *expression)
dvander@7
   121
{
dvander@7
   122
    expression->accept(this);
dvander@21
   123
    if (!expression->type())
dvander@21
   124
        return NULL;
dvander@21
   125
dvander@21
   126
    // :TODO: use Local
dvander@21
   127
    Type *type = expression->type();
dvander@21
   128
    if (type->isReference()) {
dvander@21
   129
        expression->setType(type->contained());
dvander@21
   130
    } else if (expression->isIndexExpression()) {
dvander@21
   131
        if (type->isArray())
dvander@14
   132
            expression->setType(type->contained());
dvander@14
   133
    }
dvander@7
   134
    return expression->type();
dvander@7
   135
}
dvander@7
   136
dvander@7
   137
Type *
dvander@7
   138
SemanticAnalysis::visitForRef(Expression *expression)
dvander@7
   139
{
dvander@7
   140
    expression->accept(this);
dvander@7
   141
    return expression->type();
dvander@7
   142
}
dvander@7
   143
dvander@4
   144
static inline bool
dvander@4
   145
TypeCheck(Type *left, Type *right)
dvander@4
   146
{
dvander@4
   147
    if (!left || !right)
dvander@4
   148
        return false;
dvander@4
   149
dvander@4
   150
    if (left->isPrimitive()) {
dvander@4
   151
        if (!right->isPrimitive())
dvander@4
   152
            return false;
dvander@4
   153
        return left->primitive() == right->primitive();
dvander@4
   154
    }
dvander@4
   155
dvander@4
   156
    return false;
dvander@4
   157
}
dvander@4
   158
dvander@21
   159
static inline bool
dvander@21
   160
TypeCheckAssignment(Type *left, Type *right)
dvander@21
   161
{
dvander@21
   162
    if (!left || !right)
dvander@21
   163
        return false;
dvander@21
   164
dvander@21
   165
    if (left->isPrimitive()) {
dvander@21
   166
        if (!right->isPrimitive())
dvander@21
   167
            return false;
dvander@21
   168
        return left->primitive() == right->primitive();
dvander@21
   169
    }
dvander@21
   170
dvander@21
   171
    if (left->isArray() != right->isArray())
dvander@21
   172
        return false;
dvander@21
   173
dvander@21
   174
    if (left->levels() != 1 || right->levels() != 1)
dvander@21
   175
        return false;
dvander@21
   176
dvander@21
   177
    if (left->elements() == -1 || right->elements() == -1)
dvander@21
   178
        return false;
dvander@21
   179
dvander@21
   180
    if (!TypeCheckAssignment(left->contained(), right->contained()))
dvander@21
   181
        return false;
dvander@21
   182
dvander@21
   183
    if (left->elements() != right->elements()) {
dvander@21
   184
        if (left->isCharArray() && (left->elements() >= right->elements()))
dvander@21
   185
            return true;
dvander@21
   186
        return false;
dvander@21
   187
    }
dvander@21
   188
dvander@21
   189
    return false;
dvander@21
   190
}
dvander@21
   191
dvander@22
   192
static inline Type *
dvander@22
   193
TypeCheckBinary(TokenKind token, Type *left, Type *right)
dvander@22
   194
{
dvander@22
   195
    if (!left || !right)
dvander@22
   196
        return NULL;
dvander@22
   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@22
   203
            assert(left->isFloat() || left->isInt32());
dvander@22
   204
            assert(right->isFloat() || right->isInt32());
dvander@22
   205
            return left->isFloat() ? left : right;
dvander@22
   206
        }
dvander@22
   207
    }
dvander@22
   208
dvander@22
   209
    assert(left->isInt32() && right->isInt32());
dvander@22
   210
    assert(!left->tag() && !right->tag());
dvander@22
   211
    return left;
dvander@22
   212
}
dvander@22
   213
dvander@23
   214
Type *
dvander@23
   215
SemanticAnalysis::visitForLValue(Expression *expression)
dvander@23
   216
{
dvander@23
   217
    if (expression->isIndexExpression()) {
dvander@23
   218
        expression->accept(this);
dvander@23
   219
        if (!expression->type())
dvander@23
   220
            return NULL;
dvander@23
   221
        return expression->type()->contained();
dvander@23
   222
    }
dvander@23
   223
dvander@23
   224
    if (!expression->isNameProxy()) {
dvander@23
   225
        assert(false);
dvander@23
   226
        return NULL;
dvander@23
   227
    }
dvander@23
   228
dvander@23
   229
    NameProxy *proxy = expression->toNameProxy();
dvander@23
   230
    if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@23
   231
        fprintf(stderr, "error\n");
dvander@23
   232
        return NULL;
dvander@23
   233
    }
dvander@23
   234
dvander@23
   235
    Variable *var = proxy->binding()->toVariable();
dvander@23
   236
    if (!var->type())
dvander@23
   237
        return NULL;
dvander@23
   238
dvander@23
   239
    if  (var->type()->isReference())
dvander@23
   240
        return var->type()->contained();
dvander@23
   241
    return var->type();
dvander@23
   242
}
dvander@23
   243
dvander@0
   244
void
dvander@0
   245
SemanticAnalysis::visit(Assignment *node)
dvander@0
   246
{
dvander@7
   247
    visitForLoad(node->expression());
dvander@0
   248
dvander@23
   249
    // :TODO: use Local
dvander@23
   250
    Type *type = visitForLValue(node->lvalue());
dvander@23
   251
    if (!type)
dvander@23
   252
        return;
dvander@23
   253
    node->setType(type);
dvander@4
   254
dvander@22
   255
    if (node->token() != TOK_ASSIGN)
dvander@22
   256
        assert(TypeCheckBinary(node->token(), node->type(), node->expression()->type()));
dvander@22
   257
dvander@21
   258
    assert(TypeCheckAssignment(node->type(), node->expression()->type()));
dvander@0
   259
}
dvander@0
   260
dvander@0
   261
void
dvander@23
   262
SemanticAnalysis::visit(IncDecExpression *node)
dvander@23
   263
{
dvander@23
   264
    // :TODO: use Local
dvander@23
   265
    Type *type = visitForLValue(node->expression());
dvander@23
   266
    if (!type)
dvander@23
   267
        return;
dvander@23
   268
dvander@23
   269
    assert(!type->isReference());
dvander@23
   270
    if (type->isArray()) {
dvander@23
   271
        // can't a[]++
dvander@23
   272
        assert(false);
dvander@23
   273
        return;
dvander@23
   274
    }
dvander@23
   275
dvander@23
   276
    assert((type->isInt32() && !type->tag()) || type->isFloat());
dvander@23
   277
    node->setType(type);
dvander@23
   278
}
dvander@23
   279
dvander@23
   280
void
dvander@0
   281
SemanticAnalysis::visit(BinaryExpression *node)
dvander@0
   282
{
dvander@22
   283
    // :TODO: use Local
dvander@7
   284
    Type *left = visitForLoad(node->left());
dvander@7
   285
    Type *right = visitForLoad(node->right());
dvander@4
   286
dvander@22
   287
    Type *result = TypeCheckBinary(node->token(), left, right);
dvander@22
   288
    node->setType(result);
dvander@0
   289
}
dvander@0
   290
dvander@0
   291
void
dvander@0
   292
SemanticAnalysis::visit(ReturnStatement *node)
dvander@0
   293
{
dvander@7
   294
    visitForLoad(node->expression());
dvander@0
   295
dvander@0
   296
    // :TODO: type check
dvander@0
   297
}
dvander@0
   298
dvander@0
   299
void
dvander@0
   300
SemanticAnalysis::visit(ForStatement *node)
dvander@0
   301
{
dvander@10
   302
    loopDepth_++;
dvander@12
   303
    if (node->scope())
dvander@12
   304
        scope_ = node->scope();
dvander@22
   305
    if (node->initialization())
dvander@22
   306
        node->initialization()->accept(this);
dvander@0
   307
    if (node->condition())
dvander@7
   308
        visitForLoad(node->condition());
dvander@0
   309
    if (node->update())
dvander@0
   310
        node->update()->accept(this);
dvander@0
   311
    node->body()->accept(this);
dvander@12
   312
    if (node->scope())
dvander@12
   313
        scope_ = scope_->enclosing();
dvander@10
   314
    loopDepth_--;
dvander@0
   315
}
dvander@0
   316
dvander@9
   317
void 
dvander@9
   318
SemanticAnalysis::visit(WhileStatement *node)
dvander@9
   319
{
dvander@10
   320
    loopDepth_++;
dvander@9
   321
    node->condition()->accept(this);
dvander@9
   322
    node->body()->accept(this);
dvander@10
   323
    loopDepth_--;
dvander@9
   324
}
dvander@9
   325
dvander@0
   326
void
dvander@0
   327
SemanticAnalysis::visit(BlockStatement *node)
dvander@0
   328
{
dvander@12
   329
    if (node->scope())
dvander@12
   330
        scope_ = node->scope();
dvander@0
   331
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@0
   332
        Statement *statement = node->statements()->at(i);
dvander@0
   333
        statement->accept(this);
dvander@0
   334
    }
dvander@12
   335
    if (node->scope())
dvander@12
   336
        scope_ = scope_->enclosing();
dvander@0
   337
}
dvander@0
   338
dvander@0
   339
void
dvander@0
   340
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@0
   341
{
dvander@14
   342
    // :TODO: use locals
dvander@11
   343
    Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
dvander@0
   344
    if (!type)
dvander@0
   345
        return;
dvander@0
   346
dvander@0
   347
    if (node->postDimensions()) {
dvander@21
   348
        Type *init = NULL;
dvander@21
   349
        if (node->initialization()) {
dvander@21
   350
            node->initialization()->accept(this);
dvander@21
   351
            if ((init = node->initialization()->type()) == NULL)
dvander@21
   352
                return;
dvander@21
   353
        }
dvander@21
   354
dvander@0
   355
        if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
dvander@0
   356
            error();
dvander@0
   357
            return;
dvander@0
   358
        }
dvander@0
   359
dvander@21
   360
        // If we have an initializer, make sure it's the same type.
dvander@21
   361
        if (init) {
dvander@21
   362
            assert(init->levels() == node->postDimensions()->size());
dvander@21
   363
        }
dvander@21
   364
dvander@21
   365
        Type *check = init;
dvander@0
   366
        for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
dvander@0
   367
            Expression *expr = node->postDimensions()->at(i);
dvander@7
   368
            visitForLoad(expr);
dvander@0
   369
dvander@0
   370
            if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
dvander@0
   371
                typeError(expr, "integer");
dvander@0
   372
                return;
dvander@0
   373
            }
dvander@0
   374
dvander@0
   375
            int size = -1;
dvander@4
   376
            if (expr->isIntegerLiteral()) {
dvander@4
   377
                size = expr->toIntegerLiteral()->value();
dvander@0
   378
                if (size <= 0) {
dvander@0
   379
                    error();
dvander@0
   380
                    return;
dvander@0
   381
                }
dvander@0
   382
                if (size >= INT_MAX / sizeof(int)) {
dvander@0
   383
                    error();
dvander@0
   384
                    return;
dvander@0
   385
                }
dvander@21
   386
            } else {
dvander@21
   387
                assert(false);
dvander@0
   388
            }
dvander@0
   389
dvander@11
   390
            type = ZONE()->types()->unsafeArray(type, size);
dvander@21
   391
dvander@21
   392
            if (check) {
dvander@21
   393
                assert(check->elements() != -1);
dvander@21
   394
                assert(size != -1);
dvander@21
   395
                    
dvander@21
   396
                // If we're assigning a string, we're allowed to pad with
dvander@21
   397
                // zeroes.
dvander@21
   398
                if (check->isCharArray()) {
dvander@21
   399
                    assert(type->isCharArray());
dvander@21
   400
                    assert(type->elements() >= check->elements());
dvander@21
   401
                } else {
dvander@21
   402
                    assert(false);
dvander@21
   403
                }
dvander@21
   404
            }
dvander@21
   405
dvander@21
   406
            if (check)
dvander@21
   407
                check = check->contained();
dvander@0
   408
        }
dvander@12
   409
dvander@12
   410
        // Right now, any array is allowed on the LIFO heap. In case the
dvander@12
   411
        // runtime actually decides to use the LIFO heap, we must reserve
dvander@12
   412
        // a slot so we can unwind the heap when the current scope leaves.
dvander@12
   413
        scope_->setUsesLifoHeap();
dvander@8
   414
    } else {
dvander@10
   415
        if (node->initialization()) {
dvander@10
   416
            Type *right = visitForLoad(node->initialization());
dvander@10
   417
            assert(TypeCheck(type, right));
dvander@10
   418
        }
dvander@21
   419
        if (type->primitive() == PrimitiveType_Char) {
dvander@21
   420
            assert(false);
dvander@21
   421
            return;
dvander@21
   422
        }
dvander@0
   423
    }
dvander@0
   424
dvander@0
   425
    node->variable()->setType(type);
dvander@0
   426
}
dvander@0
   427
dvander@0
   428
void
dvander@4
   429
SemanticAnalysis::visit(IntegerLiteral *node)
dvander@0
   430
{
dvander@11
   431
    node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
dvander@0
   432
}
dvander@0
   433
dvander@0
   434
void
dvander@0
   435
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@0
   436
{
dvander@0
   437
    node->expression()->accept(this);
dvander@0
   438
}
dvander@0
   439
dvander@14
   440
bool
dvander@14
   441
SemanticAnalysis::preanalyze(FunctionStatement *node)
dvander@14
   442
{
dvander@14
   443
    // :TODO: use Local
dvander@14
   444
dvander@14
   445
    FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
dvander@14
   446
    if (!args)
dvander@14
   447
        return false;
dvander@14
   448
dvander@14
   449
    // Apply types to arguments.
dvander@14
   450
    for (size_t i = 0; i < node->parameters()->size(); i++) {
dvander@14
   451
        Parameter *parameter = node->parameters()->at(i);
dvander@14
   452
        
dvander@14
   453
        Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
dvander@14
   454
        if (!type)
dvander@14
   455
            return false;
dvander@14
   456
dvander@14
   457
        if (parameter->reference()) {
dvander@14
   458
            type = ZONE()->types()->getReference(type);
dvander@14
   459
            if (!type)
dvander@14
   460
                return false;
dvander@14
   461
        }
dvander@14
   462
dvander@14
   463
        args->set(ZONE(), i, type);
dvander@14
   464
        parameter->variable()->setType(type);
dvander@14
   465
    }
dvander@14
   466
dvander@14
   467
    Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
dvander@14
   468
    if (!returnType)
dvander@14
   469
        return false;
dvander@14
   470
dvander@14
   471
    Type *funtype = ZONE()->types()->newFunction(returnType, args);
dvander@14
   472
    if (!funtype)
dvander@14
   473
        return false;
dvander@14
   474
dvander@14
   475
    node->fun()->setType(funtype);
dvander@14
   476
    return true;
dvander@14
   477
}
dvander@14
   478
dvander@0
   479
void
dvander@0
   480
SemanticAnalysis::visit(FunctionStatement *node)
dvander@0
   481
{
dvander@12
   482
    scope_ = node->scope();
dvander@14
   483
dvander@14
   484
    // :TODO: call this ahead of time.
dvander@14
   485
    if (!preanalyze(node))
dvander@14
   486
        return;
dvander@14
   487
dvander@0
   488
    node->body()->accept(this);
dvander@12
   489
    scope_ = NULL;
dvander@0
   490
}
dvander@0
   491
dvander@14
   492
// :TODO: use handles
dvander@14
   493
static inline bool
dvander@14
   494
TypeCheckParameter(Type *given, Type *actual)
dvander@14
   495
{
dvander@14
   496
    if (actual->isReference()) {
dvander@14
   497
        if (given->isReference())
dvander@14
   498
            given = given->contained();
dvander@14
   499
        return TypeCheck(given, actual->contained());
dvander@14
   500
    }
dvander@14
   501
dvander@14
   502
    return TypeCheck(given, actual);
dvander@14
   503
}
dvander@14
   504
dvander@0
   505
void
dvander@0
   506
SemanticAnalysis::visit(CallExpression *node)
dvander@0
   507
{
dvander@14
   508
    visitForLoad(node->callee());
dvander@14
   509
dvander@14
   510
    // :TODO: use locals
dvander@14
   511
    Type *type = node->callee()->type();
dvander@14
   512
    if (!type)
dvander@14
   513
        return;
dvander@14
   514
dvander@14
   515
    assert(type->isFunction());
dvander@14
   516
    assert(node->arguments()->size() == type->parameters()->length());
dvander@14
   517
dvander@14
   518
    for (unsigned i = 0; i < node->arguments()->size(); i++) {
dvander@17
   519
        // Note: we don't compute references unless the callee needs a
dvander@17
   520
        // reference type.
dvander@14
   521
        Expression *expression = node->arguments()->at(i);
dvander@14
   522
        expression->accept(this);
dvander@14
   523
dvander@14
   524
        Type *given = expression->type();
dvander@14
   525
        if (!given)
dvander@14
   526
            return;
dvander@14
   527
dvander@17
   528
        // If it's an IndexExpression, we special case the ability to compute
dvander@17
   529
        // a reference. Maybe we should compute actual Ref types for
dvander@17
   530
        // IndexExpression?
dvander@17
   531
        if (expression->isIndexExpression())
dvander@17
   532
            given = given->contained();
dvander@17
   533
dvander@14
   534
        Type *actual = Type::cast(type->parameters()->at(i));
dvander@14
   535
        assert(TypeCheckParameter(given, actual));
dvander@14
   536
dvander@14
   537
        // If the actual is a reference, and the given is not, we'll need to
dvander@14
   538
        // compute a reference, which may be allocated on the stack.
dvander@14
   539
        if (actual->isReference() && !given->isReference())
dvander@14
   540
            scope_->setUsesLifoHeap();
dvander@14
   541
    }
dvander@0
   542
}
dvander@0
   543
dvander@0
   544
void
dvander@0
   545
SemanticAnalysis::visit(IfStatement *node)
dvander@0
   546
{
dvander@10
   547
    visitForLoad(node->condition());
dvander@10
   548
    node->ifTrue()->accept(this);
dvander@10
   549
    if (node->ifFalse())
dvander@10
   550
        node->ifFalse()->accept(this);
dvander@0
   551
}
dvander@0
   552
dvander@0
   553
void
dvander@0
   554
SemanticAnalysis::visit(IndexExpression *node)
dvander@0
   555
{
dvander@14
   556
    // :TODO: use locals
dvander@7
   557
    Type *left = visitForRef(node->left());
dvander@7
   558
    Type *right = visitForLoad(node->right());
dvander@0
   559
dvander@20
   560
    if (!right || !right->isInt32()) {
dvander@0
   561
        typeError(node->right(), "integer");
dvander@0
   562
        return;
dvander@0
   563
    }
dvander@7
   564
    if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
dvander@0
   565
        typeError(node->left(), "array");
dvander@0
   566
        return;
dvander@0
   567
    }
dvander@7
   568
    node->setType(left);
dvander@0
   569
}
dvander@2
   570
dvander@2
   571
void
dvander@2
   572
SemanticAnalysis::visit(EnumStatement *node)
dvander@2
   573
{
dvander@4
   574
    // :TODO: test "enum Float { ..."
dvander@4
   575
    Name *tag = node->name();
dvander@3
   576
dvander@11
   577
    Type *type = ZONE()->types()->getPrimitiveForTag(tag);
dvander@2
   578
    if (!type)
dvander@2
   579
        return;
dvander@2
   580
dvander@2
   581
    int value = 0;
dvander@2
   582
    for (size_t i = 0; i < node->entries()->size(); i++) {
dvander@2
   583
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@2
   584
dvander@2
   585
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@2
   586
        if (entry.expr) {
dvander@2
   587
            entry.expr->accept(this);
dvander@2
   588
            if (!EvaluateForConstant(entry.expr, &box))
dvander@3
   589
                fprintf(stderr, "expected constant integer expression\n");
dvander@2
   590
dvander@2
   591
            assert(box.type() == PrimitiveType_Int32);
dvander@2
   592
            value = box.toInt();
dvander@2
   593
        }
dvander@2
   594
dvander@2
   595
        entry.name->set(type, box);
dvander@2
   596
        value++;
dvander@2
   597
    }
dvander@2
   598
}
dvander@4
   599
dvander@4
   600
void
dvander@21
   601
SemanticAnalysis::visit(StringLiteral *node)
dvander@21
   602
{
dvander@21
   603
    Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
dvander@21
   604
    if (!type)
dvander@21
   605
        return;
dvander@21
   606
dvander@21
   607
    type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
dvander@21
   608
    if (!type)
dvander@21
   609
        return;
dvander@21
   610
dvander@21
   611
    node->setType(type);
dvander@21
   612
}
dvander@21
   613
dvander@21
   614
void
dvander@4
   615
SemanticAnalysis::visit(FloatLiteral *node)
dvander@4
   616
{
dvander@11
   617
    Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
dvander@4
   618
    if (!type)
dvander@4
   619
        return;
dvander@4
   620
dvander@4
   621
    node->setType(type);
dvander@4
   622
}
dvander@10
   623
dvander@10
   624
void
dvander@10
   625
SemanticAnalysis::visit(BreakStatement *node)
dvander@10
   626
{
dvander@10
   627
    assert(loopDepth_ > 0);
dvander@10
   628
}
dvander@10
   629
dvander@10
   630
void
dvander@10
   631
SemanticAnalysis::visit(ContinueStatement *node)
dvander@10
   632
{
dvander@10
   633
    assert(loopDepth_ > 0);
dvander@10
   634
}