src/OldSema.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 18:41:01 2012 -0800 (2012-11-17)
changeset 195 c1ba166f3fc4
child 263 ba85a47ee414
permissions -rw-r--r--
Massive SemA/BC refactoring to support better type systems. Read on for more.

The previous compiler had a simple pipeline, best outlined as:
(1) Parsing and name binding -> AST
(2) Storage allocation -> AST
(3) Semantic Analysis (SemA) -> AST
(4) Bytecode Compilation (BC) -> Code

This pipeline, unfortunately, had two problems. First, name binding cannot be performed in one pass if we wish to have multi-file support in the form of modules. Name binding must be two-pass.

Second, because SemA was only capable of annotating AST nodes with a single type, most coercion work had to be duplicated in the BC phase, as coercion was not explicit in the SemA output. This made introducing new type rules extremely difficult, and all but precluded concepts like operator overloading (or overloading at all).

This patch rewrites most of Keima's backend. Of interest are the following changes:
(1) CompileContext has been refactored around future multi-file support.
(2) Parsing no longer performs any name binding.
(3) The grammar for type-and-name has been changed from:
(Label | Identifier)? Identifier
to:
Type? Identifier
where:
Type ::= OldType | NewType
OldType ::= Label
NewType ::= Identifier (. NewType)*


Although we do not implement the full production for Type yet, this
distinction is important. A type identifier is now affixed to the AST
as an Expression (right now, always a NameProxy), so it can fully
participate in name binding.

(4) Immediately after parsing, the AST goes through a NamePopulation phase.
This phase creates Scope objects for every scope which declares a name,
and if those names are declaring types or functions, a Symbol is created
and entered into the scope. Symbols entirely replace the old BoundName
classes.

(5) After NamePopulation comes NameBinding. This phase performs three steps:
(a) Links Scope objects together, to form a tree.
(b) Binds any free name to an existing name in the scope chain.
(c) Creates and registers any Symbols for names which have not yet been
added to the scope (for example, local variables).

In accordance, all "allocation" and "binding" concepts have been removed
from Scopes, which are now lightweight container classes.

(6) SemA now generates bytecode for each statement in the AST. Expression
compilation is performed via a separate mechanism called HIR (High-level
Intermediate Representation). To analyze an expression, SemA will walk
the AST, and produce a HIR object for each node. HIR is typed, and SemA
may insert coercion nodes, or even expand an AST node into multiple HIR
nodes. The result of evaluating an expression in SemA is therefore the
the root of a HIR tree, which SemA then sends to the HIRTranslator, which
performs bytecode generation.

As before, SemA still performs full semantic analysis. However, not it
also produces each function's bytecode.

This split allows us to decompose potentially complex semantics into
a more fine-grained, AST-like structure, which can have very simple
code-generation logic. For example, (1.0 + 5) might look like:

HAdd(HFloat(1.0), HConvert(HInteger(5), <Float>))

As part of this decomposition, many opcodes have been removed. Rather than
using typed jumps, we now expand jumps into longer tests. For example:
jge.f <label>
becomes:
ge.f
cvt.f2b
jt <label>

This simplifies the pipeline, and JITs should be able to melt the added
work away.

HIR is not used at a statement level, and HIR does not have any concept
of control-flow.

(7) The old BytecodeCompiler has been removed, as its work is now split
between SemA and HIRTranslator.


In addition, some minor refactorings have taken place:

(1) Opcodes.tbl no longer hardcodes numbers (aaah).
(2) Type has been split into smaller, typed structs.
(3) BytecodeEmitter no longer relies on Pools or RootScopes.
(4) SemA is now responsible for variable/storage allocation.
(5) Native table are now global, rather than per-module. As such, native
declarations now result in a Native object (which still requires a
CALLNATIVE opcode), which is an index into the global table. Natives
must be bound globally. This is in preparation for module support.
(6) Publics are no longer tracked, but rather registered via a global
callback upon module load. This callback can be set by embedders. This
is in preparation for multi-file support.
(7) The BytecodeEmitter now performs Symbol allocations itself, and it
also generates Code objects itself, which removes a good deal of
complexity.

Finally, a test harness has been added. This harness is a python script which finds *.test files, recursively, in the tests folder. For each file it runs the corresponding .sp. The contents of the .test file must match stdout+stderr.
dvander@195
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@195
     2
 *
dvander@195
     3
 * Copyright (C) 2012 David Anderson
dvander@195
     4
 *
dvander@195
     5
 * This file is part of JITCraft.
dvander@195
     6
 *
dvander@195
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@195
     8
 * the terms of the GNU General Public License as published by the Free
dvander@195
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@195
    10
 * any later version.
dvander@195
    11
 * 
dvander@195
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@195
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@195
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@195
    15
 *
dvander@195
    16
 * You should have received a copy of the GNU General Public License along with
dvander@195
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@195
    18
 */
dvander@195
    19
#include <string.h>
dvander@195
    20
#include "SemanticAnalysis.h"
dvander@195
    21
#include "../Types.h"
dvander@195
    22
#include "../Zone.h"
dvander@195
    23
#include "../TypeManager.h"
dvander@195
    24
#include "../Strings.h"
dvander@195
    25
#include "../Box.h"
dvander@195
    26
#include "../Array.h"
dvander@195
    27
#include "../Heap-inl.h"
dvander@195
    28
#include "Scopes.h"
dvander@195
    29
#include "NameBinding.h"
dvander@195
    30
dvander@195
    31
using namespace ke;
dvander@195
    32
dvander@195
    33
SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
dvander@195
    34
  : zone_(zone),
dvander@195
    35
    cc_(cc),
dvander@195
    36
    tree_(tree),
dvander@195
    37
    scope_(NULL),
dvander@195
    38
    loop_(NULL)
dvander@195
    39
{
dvander@195
    40
}
dvander@195
    41
dvander@195
    42
bool
dvander@195
    43
SemanticAnalysis::analyze()
dvander@195
    44
{
dvander@195
    45
    assert(false);
dvander@195
    46
    return false;
dvander@195
    47
}
dvander@195
    48
dvander@195
    49
dvander@195
    50
#if 0
dvander@195
    51
dvander@195
    52
static inline bool
dvander@195
    53
IsPrimitiveType(Type *type, PrimitiveType primitive)
dvander@195
    54
{
dvander@195
    55
    if (!type)
dvander@195
    56
        return false;
dvander@195
    57
dvander@195
    58
    if (!type->isPrimitive())
dvander@195
    59
        return false;
dvander@195
    60
dvander@195
    61
    return primitive == type->primitive();
dvander@195
    62
}
dvander@195
    63
dvander@195
    64
static inline bool
dvander@195
    65
EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
dvander@195
    66
                        BoxedPrimitive *out)
dvander@195
    67
{
dvander@195
    68
    switch (kind) {
dvander@195
    69
      case TOK_PLUS:
dvander@195
    70
        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
dvander@195
    71
        return true;
dvander@195
    72
dvander@195
    73
      case TOK_SHL:
dvander@195
    74
        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
dvander@195
    75
        return true;
dvander@195
    76
dvander@195
    77
      default:
dvander@195
    78
        return false;
dvander@195
    79
    }
dvander@195
    80
}
dvander@195
    81
dvander@195
    82
static inline bool
dvander@195
    83
EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
dvander@195
    84
{
dvander@195
    85
  switch (kind) {
dvander@195
    86
    case TOK_MINUS:
dvander@195
    87
      *out = BoxedPrimitive::Int(-inner.toInt());
dvander@195
    88
      return true;
dvander@195
    89
dvander@195
    90
    default:
dvander@195
    91
      return false;
dvander@195
    92
  }
dvander@195
    93
}
dvander@195
    94
dvander@195
    95
static bool
dvander@195
    96
EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
dvander@195
    97
{
dvander@195
    98
    switch (expression->kind()) {
dvander@195
    99
      case AstNode::kBinaryExpression:
dvander@195
   100
      {
dvander@195
   101
        BoxedPrimitive left;
dvander@195
   102
        BoxedPrimitive right;
dvander@195
   103
        BinaryExpression *b = expression->toBinaryExpression();
dvander@195
   104
        if (!EvaluateForConstant(b->left(), &left) ||
dvander@195
   105
            !EvaluateForConstant(b->right(), &right))
dvander@195
   106
        {
dvander@195
   107
            return false;
dvander@195
   108
        }
dvander@195
   109
        return EvaluateBinaryOperation(b->token(), left, right, out);
dvander@195
   110
      }
dvander@195
   111
dvander@195
   112
      case AstNode::kUnaryExpression:
dvander@195
   113
      {
dvander@195
   114
        BoxedPrimitive inner;
dvander@195
   115
        UnaryExpression *u = expression->toUnaryExpression();
dvander@195
   116
        if (!EvaluateForConstant(u->expression(), &inner))
dvander@195
   117
            return false;
dvander@195
   118
        return EvaluateUnaryOperation(u->token(), inner, out);
dvander@195
   119
      }
dvander@195
   120
dvander@195
   121
      case AstNode::kNameProxy:
dvander@195
   122
      {
dvander@195
   123
        NameProxy *proxy = expression->toNameProxy();
dvander@195
   124
        if (proxy->binding()->kind() != BoundName::CONSTANT)
dvander@195
   125
            return false;
dvander@195
   126
dvander@195
   127
        NamedConstant *c = proxy->binding()->toNamedConstant();
dvander@195
   128
        if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
dvander@195
   129
            return false;
dvander@195
   130
dvander@195
   131
        *out = c->value();
dvander@195
   132
        return true;
dvander@195
   133
      }
dvander@195
   134
dvander@195
   135
      case AstNode::kBooleanLiteral:
dvander@195
   136
        *out = BoxedPrimitive::Int(expression->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0);
dvander@195
   137
        return true;
dvander@195
   138
dvander@195
   139
      case AstNode::kIntegerLiteral:
dvander@195
   140
        *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
dvander@195
   141
        return true;
dvander@195
   142
dvander@195
   143
      default:
dvander@195
   144
        return false;
dvander@195
   145
    }
dvander@195
   146
}
dvander@195
   147
dvander@195
   148
SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
dvander@195
   149
  : zone_(zone),
dvander@195
   150
    cc_(cc),
dvander@195
   151
    tree_(tree),
dvander@195
   152
    scope_(NULL),
dvander@195
   153
    loop_(NULL)
dvander@195
   154
{
dvander@195
   155
}
dvander@195
   156
dvander@195
   157
bool
dvander@195
   158
SemanticAnalysis::analyze()
dvander@195
   159
{
dvander@195
   160
    if (cc_.failures())
dvander@195
   161
        return false;
dvander@195
   162
dvander@195
   163
    scope_ = tree_->globalScope();
dvander@195
   164
    assert(scope_->kind() == Scope::GLOBAL);
dvander@195
   165
dvander@195
   166
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@195
   167
        Statement *statement = tree_->statements()->at(i);
dvander@195
   168
        if (statement->isFunctionStatement()) {
dvander@195
   169
            FunctionStatement *funstmt = statement->toFunctionStatement();
dvander@195
   170
            if (!preanalyze(funstmt))
dvander@195
   171
                return false;
dvander@195
   172
        } else if (statement->isEnumStatement()) {
dvander@195
   173
            EnumStatement *enumstmt = statement->toEnumStatement();
dvander@195
   174
dvander@195
   175
            // We pre-fill global enum types, since they may occur in function
dvander@195
   176
            // signatures. This should probably be somewhere else...
dvander@195
   177
            enumstmt->accept(this);
dvander@195
   178
        } else if (statement->isStructureStatement()) {
dvander@195
   179
            StructureStatement *node = statement->toStructureStatement();
dvander@195
   180
            node->accept(this);
dvander@195
   181
            if (!node->decl()->type())
dvander@195
   182
                return false;
dvander@195
   183
        } else if (statement->isFunctionTypeStatement()) {
dvander@195
   184
            FunctionTypeStatement *node = statement->toFunctionTypeStatement();
dvander@195
   185
            node->accept(this);
dvander@195
   186
            if (!node->decl()->type())
dvander@195
   187
                return false;
dvander@195
   188
        }
dvander@195
   189
    }
dvander@195
   190
dvander@195
   191
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@195
   192
        Statement *statement = tree_->statements()->at(i);
dvander@195
   193
dvander@195
   194
        // We can't double-process these. Maybe put this check somewhere else.
dvander@195
   195
        if (statement->isEnumStatement())
dvander@195
   196
            continue;
dvander@195
   197
dvander@195
   198
        statement->accept(this);
dvander@195
   199
    }
dvander@195
   200
dvander@195
   201
    if (!determineLiveFunctions())
dvander@195
   202
        return false;
dvander@195
   203
dvander@195
   204
    return !cc_.failures();
dvander@195
   205
}
dvander@195
   206
dvander@195
   207
bool
dvander@195
   208
SemanticAnalysis::determineLiveFunctions()
dvander@195
   209
{
dvander@195
   210
    Vector<NamedFunction *> worklist;
dvander@195
   211
dvander@195
   212
    // Add the root set.
dvander@195
   213
    for (size_t i = 0; i < tree_->statements()->length(); i++) {
dvander@195
   214
        Statement *statement = tree_->statements()->at(i);
dvander@195
   215
        if (!statement->isFunctionStatement())
dvander@195
   216
            continue;
dvander@195
   217
dvander@195
   218
        FunctionStatement *stmt = statement->toFunctionStatement();
dvander@195
   219
        NamedFunction  *fun = stmt->fun();
dvander@195
   220
        if (!fun->used())
dvander@195
   221
            continue;
dvander@195
   222
dvander@195
   223
        for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
dvander@195
   224
            NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
dvander@195
   225
dvander@195
   226
            // Names in these lists are always unused, however, we mark them
dvander@195
   227
            // as used while inserting into the work queue, to avoid double-
dvander@195
   228
            // insertion.
dvander@195
   229
            if (name->used())
dvander@195
   230
                continue;
dvander@195
   231
dvander@195
   232
            if (!worklist.append(name))
dvander@195
   233
                return false;
dvander@195
   234
dvander@195
   235
            name->setUsed();
dvander@195
   236
        }
dvander@195
   237
    }
dvander@195
   238
dvander@195
   239
    while (!worklist.empty()) {
dvander@195
   240
        NamedFunction *fun = worklist.popCopy();
dvander@195
   241
dvander@195
   242
        for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
dvander@195
   243
            NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
dvander@195
   244
            if (name->used())
dvander@195
   245
                continue;
dvander@195
   246
            if (!worklist.append(name))
dvander@195
   247
                return false;
dvander@195
   248
            name->setUsed();
dvander@195
   249
        }
dvander@195
   250
    }
dvander@195
   251
dvander@195
   252
    return true;
dvander@195
   253
}
dvander@195
   254
dvander@195
   255
Type *
dvander@195
   256
SemanticAnalysis::bindType(const SourcePosition &pos, BoundName *name)
dvander@195
   257
{
dvander@195
   258
    if (!name)
dvander@195
   259
        return zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
   260
dvander@195
   261
    if (name->kind() == BoundName::UNBOUND) {
dvander@195
   262
        cc_.reportError(pos, Message_TypeNotFound, name->name()->chars());
dvander@195
   263
        return NULL;
dvander@195
   264
    }
dvander@195
   265
dvander@195
   266
    if (name->kind() != BoundName::TYPE) {
dvander@195
   267
        cc_.reportError(pos, Message_IdentifierIsNotAType, name->name()->chars());
dvander@195
   268
        return NULL;
dvander@195
   269
    }
dvander@195
   270
dvander@195
   271
    if (!name->type())
dvander@195
   272
        return NULL;
dvander@195
   273
dvander@195
   274
    return name->type();
dvander@195
   275
}
dvander@195
   276
dvander@195
   277
Type *
dvander@195
   278
SemanticAnalysis::visitAndApplyType(Expression *expression)
dvander@195
   279
{
dvander@195
   280
    expression->accept(this);
dvander@195
   281
    return expression->type();
dvander@195
   282
}
dvander@195
   283
dvander@195
   284
Type *
dvander@195
   285
SemanticAnalysis::visitForLoad(Expression *expression)
dvander@195
   286
{
dvander@195
   287
    Local<Type> type(zone_, visitAndApplyType(expression));
dvander@195
   288
    if (!type)
dvander@195
   289
        return NULL;
dvander@195
   290
dvander@195
   291
    if (type->isReference()) {
dvander@195
   292
        expression->setType(type->contained());
dvander@195
   293
    } else if (expression->isCallExpression()) {
dvander@195
   294
        if (type->isVoid()) {
dvander@195
   295
            CallExpression *call = expression->toCallExpression();
dvander@195
   296
            cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
dvander@195
   297
            return NULL;
dvander@195
   298
        }
dvander@195
   299
    }
dvander@195
   300
dvander@195
   301
    return expression->type();
dvander@195
   302
}
dvander@195
   303
dvander@195
   304
void
dvander@195
   305
SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
dvander@195
   306
{
dvander@195
   307
    const char *op = TokenNames[token];
dvander@195
   308
    const char *name = GetTypeName(type);
dvander@195
   309
dvander@195
   310
    cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
dvander@195
   311
}
dvander@195
   312
dvander@195
   313
void
dvander@195
   314
SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@195
   315
{
dvander@195
   316
    const char *op = TokenNames[token];
dvander@195
   317
    const char *leftName = GetTypeName(left);
dvander@195
   318
    const char *rightName = GetTypeName(right);
dvander@195
   319
dvander@195
   320
    cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
dvander@195
   321
}
dvander@195
   322
dvander@195
   323
Type *
dvander@195
   324
SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
dvander@195
   325
{
dvander@195
   326
    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
dvander@195
   327
        (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
dvander@195
   328
    {
dvander@195
   329
        // If either side is a float, the other side must be a float or int.
dvander@195
   330
        if (left->isFloat() || right->isFloat()) {
dvander@195
   331
            Type *floatType = left->isFloat() ? left : right;
dvander@195
   332
            Type *other = left->isFloat() ? right : left;
dvander@195
   333
            if (other->isFloat() || other->isInt32())
dvander@195
   334
                return floatType;
dvander@195
   335
        }
dvander@195
   336
    }
dvander@195
   337
dvander@195
   338
    if (token == TOK_OR || token == TOK_AND) {
dvander@195
   339
        if (!canTest(node, left) || !canTest(node, right))
dvander@195
   340
            return NULL;
dvander@195
   341
        return zone_->types()->getPrimitive(PrimitiveType_Bool);
dvander@195
   342
    }
dvander@195
   343
dvander@195
   344
    if (token >= TOK_EQUALS && token <= TOK_GE) {
dvander@195
   345
        if ((left->isFloat() || left->isInt32()) &&
dvander@195
   346
            (right->isFloat() || right->isInt32()))
dvander@195
   347
        {
dvander@195
   348
            return zone_->types()->getPrimitive(PrimitiveType_Bool);
dvander@195
   349
        }
dvander@195
   350
        binaryTypeError(node, token, left, right);
dvander@195
   351
        return NULL;
dvander@195
   352
    }
dvander@195
   353
dvander@195
   354
    if (!left->isInt32() || !right->isInt32()) {
dvander@195
   355
        binaryTypeError(node, token, left, right);
dvander@195
   356
        return NULL;
dvander@195
   357
    }
dvander@195
   358
dvander@195
   359
    return left;
dvander@195
   360
}
dvander@195
   361
dvander@195
   362
bool
dvander@195
   363
SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
dvander@195
   364
{
dvander@195
   365
    if (!type->isPrimitive() && !type->isEnum()) {
dvander@195
   366
        cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
dvander@195
   367
        return false;
dvander@195
   368
    }
dvander@195
   369
    return true;
dvander@195
   370
}
dvander@195
   371
dvander@195
   372
Type *
dvander@195
   373
SemanticAnalysis::visitForLValue(Expression *expression)
dvander@195
   374
{
dvander@195
   375
    if (expression->isIndexExpression()) {
dvander@195
   376
        Type *type = visitAndApplyType(expression);
dvander@195
   377
        if (!type)
dvander@195
   378
            return NULL;
dvander@195
   379
dvander@195
   380
        // if (type->isConst()) {
dvander@195
   381
        //     cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@195
   382
        //     return NULL;
dvander@195
   383
        // }
dvander@195
   384
dvander@195
   385
        return type;
dvander@195
   386
    }
dvander@195
   387
dvander@195
   388
    if (expression->isFieldExpression()) {
dvander@195
   389
        Type *type = visitAndApplyType(expression);
dvander@195
   390
        if (!type)
dvander@195
   391
            return NULL;
dvander@195
   392
dvander@195
   393
        // if (expression->toFieldExpression()->left()->type()->isConst()) {
dvander@195
   394
        //     cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@195
   395
        //     return NULL;
dvander@195
   396
        // }
dvander@195
   397
dvander@195
   398
        return type;
dvander@195
   399
    }
dvander@195
   400
dvander@195
   401
    if (!expression->isNameProxy()) {
dvander@195
   402
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@195
   403
        return NULL;
dvander@195
   404
    }
dvander@195
   405
dvander@195
   406
    NameProxy *proxy = expression->toNameProxy();
dvander@195
   407
    if (!proxy->binding()->kind() == BoundName::VARIABLE) {
dvander@195
   408
        cc_.reportError(expression->pos(), Message_ExpectedLValue);
dvander@195
   409
        return NULL;
dvander@195
   410
    }
dvander@195
   411
dvander@195
   412
    Variable *var = proxy->binding()->toVariable();
dvander@195
   413
    if (!var->type())
dvander@195
   414
        return NULL;
dvander@195
   415
dvander@195
   416
    if  (var->type()->isReference()) {
dvander@195
   417
        if (var->type()->isConst()) {
dvander@195
   418
            cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
dvander@195
   419
            return NULL;
dvander@195
   420
        }
dvander@195
   421
        return var->type()->contained();
dvander@195
   422
    }
dvander@195
   423
    return var->type();
dvander@195
   424
}
dvander@195
   425
dvander@195
   426
SemanticAnalysis::ControlStatus
dvander@195
   427
SemanticAnalysis::visitForControl(Statement *statement)
dvander@195
   428
{
dvander@195
   429
    ControlScope scope(&control_);
dvander@195
   430
    statement->accept(this);
dvander@195
   431
    return scope.status();
dvander@195
   432
}
dvander@195
   433
dvander@195
   434
void
dvander@195
   435
SemanticAnalysis::visit(NameProxy *name)
dvander@195
   436
{
dvander@195
   437
    BoundName *binding = name->binding();
dvander@195
   438
dvander@195
   439
    if (binding->scope()->kind() == Scope::GLOBAL) {
dvander@195
   440
        if (!function_ || function_->isPublic()) {
dvander@195
   441
            // Whatever we're referencing must be kept alive no matter what.
dvander@195
   442
            // As such, we simply mark it used, and don't do anything special.
dvander@195
   443
            binding->setUsed();
dvander@195
   444
        } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
dvander@195
   445
            // Otherwise, we're inside a normal stock or function. Since we
dvander@195
   446
            // don't really know if we've been used yet, we shouldn't
dvander@195
   447
            // prematurely references as alive. Instead, we keep a list of
dvander@195
   448
            // which names have been used, so we can mark them later if needed.
dvander@195
   449
            //
dvander@195
   450
            // Note that we skip this step if the binding is already in the
dvander@195
   451
            // root set.
dvander@195
   452
            if (!function_->addUsedGlobal(binding))
dvander@195
   453
                return;
dvander@195
   454
        }
dvander@195
   455
    }
dvander@195
   456
dvander@195
   457
    name->setType(binding->type());
dvander@195
   458
}
dvander@195
   459
dvander@195
   460
void
dvander@195
   461
SemanticAnalysis::visit(Assignment *node)
dvander@195
   462
{
dvander@195
   463
    Local<Type> exprType(zone_, visitForLoad(node->expression()));
dvander@195
   464
    if (!exprType)
dvander@195
   465
        return ;
dvander@195
   466
dvander@195
   467
    Local<Type> type(zone_, visitForLValue(node->lvalue()));
dvander@195
   468
    if (!type)
dvander@195
   469
        return;
dvander@195
   470
dvander@195
   471
    if (node->token() != TOK_ASSIGN) {
dvander@195
   472
        if (!typeCheckBinary(node, node->token(), type, exprType))
dvander@195
   473
            return;
dvander@195
   474
    }
dvander@195
   475
dvander@195
   476
    if (!typeCheckAssignment(node->pos(), exprType, type, true))
dvander@195
   477
        return;
dvander@195
   478
dvander@195
   479
    node->setType(type);
dvander@195
   480
}
dvander@195
   481
dvander@195
   482
void
dvander@195
   483
SemanticAnalysis::visit(IncDecExpression *node)
dvander@195
   484
{
dvander@195
   485
    Local<Type> type(zone_, visitForLValue(node->expression()));
dvander@195
   486
    if (!type)
dvander@195
   487
        return;
dvander@195
   488
dvander@195
   489
    assert(!type->isReference());
dvander@195
   490
dvander@195
   491
    if (!type->isInt32() && !type->isFloat()) {
dvander@195
   492
        unaryTypeError(node, node->token(), type);
dvander@195
   493
        return;
dvander@195
   494
    }
dvander@195
   495
dvander@195
   496
    node->setType(type);
dvander@195
   497
}
dvander@195
   498
dvander@195
   499
void
dvander@195
   500
SemanticAnalysis::visit(UnaryExpression *node)
dvander@195
   501
{
dvander@195
   502
    Local<Type> type(zone_, visitForLoad(node->expression()));
dvander@195
   503
    if (!type)
dvander@195
   504
        return;
dvander@195
   505
dvander@195
   506
    switch (node->token())
dvander@195
   507
    {
dvander@195
   508
      case TOK_NOT:
dvander@195
   509
        if (!canTest(node->expression(), type))
dvander@195
   510
            return;
dvander@195
   511
        type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
   512
        if (!type)
dvander@195
   513
            return;
dvander@195
   514
        node->setType(type);
dvander@195
   515
        break;
dvander@195
   516
dvander@195
   517
      case TOK_MINUS:
dvander@195
   518
        if (!type->isFloat() && !type->isInt32()) {
dvander@195
   519
            unaryTypeError(node, node->token(), type);
dvander@195
   520
            return;
dvander@195
   521
        }
dvander@195
   522
        node->setType(type);
dvander@195
   523
        break;
dvander@195
   524
dvander@195
   525
      case TOK_LABEL:
dvander@195
   526
      {
dvander@195
   527
        Local<Type> to(zone_, bindType(node->pos(), node->type()));
dvander@195
   528
        if (!to)
dvander@195
   529
            return;
dvander@195
   530
dvander@195
   531
        if ((!type->isFloat() && !type->isInt32OrEnum()) ||
dvander@195
   532
            (!to->isFloat() && !to->isInt32OrEnum()))
dvander@195
   533
        {
dvander@195
   534
            unaryTypeError(node, node->token(), type);
dvander@195
   535
            return;
dvander@195
   536
        }
dvander@195
   537
dvander@195
   538
        node->setType(to);
dvander@195
   539
        break;
dvander@195
   540
      }
dvander@195
   541
dvander@195
   542
      case TOK_SIZEOF:
dvander@195
   543
      {
dvander@195
   544
        if (!type->isArray()) {
dvander@195
   545
            cc_.reportError(node->pos(), Message_SizeofNeedsArray);
dvander@195
   546
            return;
dvander@195
   547
        }
dvander@195
   548
        node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@195
   549
        break;
dvander@195
   550
      }
dvander@195
   551
dvander@195
   552
      default:
dvander@195
   553
        assert(node->token() == TOK_TILDE);
dvander@195
   554
        if (!type->isInt32()) {
dvander@195
   555
            unaryTypeError(node, node->token(), type);
dvander@195
   556
            return;
dvander@195
   557
        }
dvander@195
   558
        node->setType(type);
dvander@195
   559
        break;
dvander@195
   560
    }
dvander@195
   561
}
dvander@195
   562
dvander@195
   563
void
dvander@195
   564
SemanticAnalysis::visit(TernaryExpression *node)
dvander@195
   565
{
dvander@195
   566
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@195
   567
    if (!type)
dvander@195
   568
        return;
dvander@195
   569
dvander@195
   570
    if (!canTest(node->condition(), type))
dvander@195
   571
        return;
dvander@195
   572
dvander@195
   573
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@195
   574
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@195
   575
    if (!left || !right)
dvander@195
   576
        return;
dvander@195
   577
dvander@195
   578
    if (left != right) {
dvander@195
   579
        binaryTypeError(node, TOK_QMARK, left, right);
dvander@195
   580
        return;
dvander@195
   581
    }
dvander@195
   582
}
dvander@195
   583
dvander@195
   584
void
dvander@195
   585
SemanticAnalysis::visit(BinaryExpression *node)
dvander@195
   586
{
dvander@195
   587
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@195
   588
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@195
   589
    if (!left || !right)
dvander@195
   590
        return;
dvander@195
   591
dvander@195
   592
    Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
dvander@195
   593
    if (!result)
dvander@195
   594
        return;
dvander@195
   595
dvander@195
   596
    node->setType(result);
dvander@195
   597
}
dvander@195
   598
dvander@195
   599
void
dvander@195
   600
SemanticAnalysis::visit(ReturnStatement *node)
dvander@195
   601
{
dvander@195
   602
    // Set this early, so if we error we don't get more errors.
dvander@195
   603
    control_->returns(Returns_Always);
dvander@195
   604
dvander@195
   605
    if (!node->expression()) {
dvander@195
   606
        if (!function_->type()->returnType()->isVoid())
dvander@195
   607
            cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
dvander@195
   608
        return;
dvander@195
   609
    }
dvander@195
   610
dvander@195
   611
    Local<Type> type(zone_, visitForLoad(node->expression()));
dvander@195
   612
    if (!type)
dvander@195
   613
        return;
dvander@195
   614
dvander@195
   615
    Local<Type> returnType(zone_, function_->type()->returnType());
dvander@195
   616
    if (!typeCheckAssignment(node->pos(), type, returnType, true))
dvander@195
   617
        return;
dvander@195
   618
}
dvander@195
   619
dvander@195
   620
void
dvander@195
   621
SemanticAnalysis::visit(ForStatement *node)
dvander@195
   622
{
dvander@195
   623
    LoopScope loop(&loop_);
dvander@195
   624
dvander@195
   625
    if (node->scope())
dvander@195
   626
        scope_ = node->scope();
dvander@195
   627
dvander@195
   628
    if (node->initialization())
dvander@195
   629
        node->initialization()->accept(this);
dvander@195
   630
dvander@195
   631
    if (node->condition()) {
dvander@195
   632
        Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@195
   633
        if (!type || !canTest(node->condition(), type)) {
dvander@195
   634
            return;
dvander@195
   635
        }
dvander@195
   636
    }
dvander@195
   637
dvander@195
   638
    if (node->update())
dvander@195
   639
        node->update()->accept(this);
dvander@195
   640
dvander@195
   641
    ControlStatus status = visitForControl(node->body());
dvander@195
   642
dvander@195
   643
    // If there is a condition, we treat this like a while loop. Otherwise,
dvander@195
   644
    // join point is only reachable if the loop contains a break. The
dvander@195
   645
    // termination status doesn't tell us anything yet.
dvander@195
   646
    if (node->condition() || loop.breaks())
dvander@195
   647
        control_->merge(status, ControlStatus(false, Returns_Never));
dvander@195
   648
    else
dvander@195
   649
        control_->terminate(status.returns());
dvander@195
   650
dvander@195
   651
    if (node->scope())
dvander@195
   652
        scope_ = scope_->enclosing();
dvander@195
   653
}
dvander@195
   654
dvander@195
   655
void 
dvander@195
   656
SemanticAnalysis::visit(WhileStatement *node)
dvander@195
   657
{
dvander@195
   658
    LoopScope loop(&loop_);
dvander@195
   659
dvander@195
   660
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@195
   661
    if (!type || !canTest(node->condition(), type)) {
dvander@195
   662
        return;
dvander@195
   663
    }
dvander@195
   664
dvander@195
   665
    ControlStatus status = visitForControl(node->body());
dvander@195
   666
dvander@195
   667
    // Detect loops that will always have a fork in the control-flow graph.
dvander@195
   668
    // This will be a |while| loop, or a |do-while| loop whose body does
dvander@195
   669
    // not terminate.
dvander@195
   670
    //
dvander@195
   671
    // For now, we treat these as an |if| regardless of the direction the
dvander@195
   672
    // branch can take. That means the control-flow is always conditional.
dvander@195
   673
    if (node->token() == TOK_WHILE ||
dvander@195
   674
        !status.terminates() ||
dvander@195
   675
        loop.breaks())
dvander@195
   676
    {
dvander@195
   677
        control_->merge(status, ControlStatus(false, Returns_Never));
dvander@195
   678
    } else {
dvander@195
   679
        // At this point, we've got a do-while loop with a |return| or
dvander@195
   680
        // |continue|, meaning that the rest of the block is unreachable.
dvander@195
   681
        control_->terminate(status.returns());
dvander@195
   682
    }
dvander@195
   683
}
dvander@195
   684
dvander@195
   685
void
dvander@195
   686
SemanticAnalysis::visit(BlockStatement *node)
dvander@195
   687
{
dvander@195
   688
    if (node->scope())
dvander@195
   689
        scope_ = node->scope();
dvander@195
   690
    for (size_t i = 0; i < node->statements()->length(); i++) {
dvander@195
   691
        Statement *statement = node->statements()->at(i);
dvander@195
   692
        statement->accept(this);
dvander@195
   693
    }
dvander@195
   694
    if (node->scope())
dvander@195
   695
        scope_ = scope_->enclosing();
dvander@195
   696
}
dvander@195
   697
dvander@195
   698
static inline bool
dvander@195
   699
IsScalarString(Type *type)
dvander@195
   700
{
dvander@195
   701
    if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
dvander@195
   702
        return true;
dvander@195
   703
    if (type->isReference())
dvander@195
   704
        return IsScalarString(type->contained());
dvander@195
   705
    return false;
dvander@195
   706
}
dvander@195
   707
dvander@195
   708
static const int INFER_ARRAY_SIZE = 0;
dvander@195
   709
static const int EVAL_ARRAY_SIZE = -1;
dvander@195
   710
static const int DYNAMIC_ARRAY_SIZE = -2;
dvander@195
   711
dvander@195
   712
bool
dvander@195
   713
SemanticAnalysis::evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH])
dvander@195
   714
{
dvander@195
   715
    bool hadEmptySize = false;
dvander@195
   716
dvander@195
   717
    for (size_t i = 0; i < exprs->length(); i++) {
dvander@195
   718
        Expression *expr = exprs->at(i);
dvander@195
   719
        if (!expr) {
dvander@195
   720
            dims[i] = INFER_ARRAY_SIZE;
dvander@195
   721
            hadEmptySize = true;
dvander@195
   722
            continue;
dvander@195
   723
        }
dvander@195
   724
dvander@195
   725
        BoxedPrimitive box;
dvander@195
   726
        if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@195
   727
            int size = box.toInt();
dvander@195
   728
            if (size <= 0) {
dvander@195
   729
                cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@195
   730
                return false;
dvander@195
   731
            }
dvander@195
   732
dvander@195
   733
            dims[i] = size;
dvander@195
   734
            continue;
dvander@195
   735
        }
dvander@195
   736
dvander@195
   737
        Local<Type> exprType(zone_, visitForLoad(expr));
dvander@195
   738
        if (!exprType)
dvander@195
   739
            return false;
dvander@195
   740
dvander@195
   741
        if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
dvander@195
   742
            cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
dvander@195
   743
            return false;
dvander@195
   744
        }
dvander@195
   745
dvander@195
   746
        if (hadEmptySize) {
dvander@195
   747
            cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
dvander@195
   748
            return false;
dvander@195
   749
        }
dvander@195
   750
dvander@195
   751
        dims[i] = EVAL_ARRAY_SIZE;
dvander@195
   752
    }
dvander@195
   753
dvander@195
   754
    return true;
dvander@195
   755
}
dvander@195
   756
dvander@195
   757
bool
dvander@195
   758
SemanticAnalysis::inferFixedArrayLiteral(ArrayLiteral *literal, Handle<Type> contained,
dvander@195
   759
                                         int dims[MAX_ARRAY_DEPTH],
dvander@195
   760
                                         unsigned dimcount, unsigned level)
dvander@195
   761
{
dvander@195
   762
    if (dims[level] == EVAL_ARRAY_SIZE) {
dvander@195
   763
        cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
dvander@195
   764
        return false;
dvander@195
   765
    }
dvander@195
   766
dvander@195
   767
    if (dims[level] == INFER_ARRAY_SIZE) {
dvander@195
   768
        // Strings always become dynamic arrays.
dvander@195
   769
        if (level != dimcount - 1 || !IsPrimitiveType(contained, PrimitiveType_Char))
dvander@195
   770
            dims[level] = literal->expressions()->length();
dvander@195
   771
    } else if (dims[level] == DYNAMIC_ARRAY_SIZE) {
dvander@195
   772
        cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
dvander@195
   773
        return false;
dvander@195
   774
    } else {
dvander@195
   775
        if (literal->expressions()->length() != unsigned(dims[level])) {
dvander@195
   776
            cc_.reportError(literal->pos(), Message_ArrayDimensionSizeMismatch, level + 1);
dvander@195
   777
            return false;
dvander@195
   778
        }
dvander@195
   779
    }
dvander@195
   780
dvander@195
   781
    if (level == dimcount - 2 && IsPrimitiveType(contained, PrimitiveType_Char)) {
dvander@195
   782
        for (size_t i = 0; i < literal->expressions()->length(); i++) {
dvander@195
   783
            Expression *expr = literal->expressions()->at(i);
dvander@195
   784
            if (!expr->isStringLiteral()) {
dvander@195
   785
                cc_.reportError(expr->pos(), Message_ExpectedStringLiteral);
dvander@195
   786
                return false;
dvander@195
   787
            }
dvander@195
   788
dvander@195
   789
            StringLiteral *lit = expr->toStringLiteral();
dvander@195
   790
            if (dims[level + 1] > 0 &&
dvander@195
   791
                unsigned(dims[level]) < lit->string()->length())
dvander@195
   792
            {
dvander@195
   793
                cc_.reportError(lit->pos(), Message_ArrayDimensionSizeMismatch, level + 2);
dvander@195
   794
                return false;
dvander@195
   795
            }
dvander@195
   796
            if (!visitAndApplyType(lit))
dvander@195
   797
                return false;
dvander@195
   798
        }
dvander@195
   799
    } else if (level == dimcount - 1) {
dvander@195
   800
        Local<Type> type(zone_);
dvander@195
   801
        for (size_t i = 0; i < literal->expressions()->length(); i++) {
dvander@195
   802
            Expression *expr = literal->expressions()->at(i);
dvander@195
   803
            if (expr->isArrayLiteral()) {
dvander@195
   804
                cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
dvander@195
   805
                return false;
dvander@195
   806
            }
dvander@195
   807
dvander@195
   808
            if ((type = visitAndApplyType(expr)) == NULL)
dvander@195
   809
                return false;
dvander@195
   810
dvander@195
   811
            if (!typeCheckAssignment(expr->pos(), type, contained, true))
dvander@195
   812
                return false;
dvander@195
   813
        }
dvander@195
   814
    } else {
dvander@195
   815
        for (size_t i = 0; i < literal->expressions()->length(); i++) {
dvander@195
   816
            Expression *expr = literal->expressions()->at(i);
dvander@195
   817
            if (!expr->isArrayLiteral()) {
dvander@195
   818
                cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
dvander@195
   819
                return false;
dvander@195
   820
            }
dvander@195
   821
dvander@195
   822
            assert(expr->toArrayLiteral()->isFixed());
dvander@195
   823
dvander@195
   824
            if (!inferFixedArrayLiteral(expr->toArrayLiteral(),
dvander@195
   825
                                        contained,
dvander@195
   826
                                        dims,
dvander@195
   827
                                        dimcount,
dvander@195
   828
                                        level + 1))
dvander@195
   829
            {
dvander@195
   830
                return false;
dvander@195
   831
            }
dvander@195
   832
        }
dvander@195
   833
    }
dvander@195
   834
dvander@195
   835
    return true;
dvander@195
   836
}
dvander@195
   837
dvander@195
   838
void
dvander@195
   839
SemanticAnalysis::visit(VariableDeclaration *node)
dvander@195
   840
{
dvander@195
   841
    Local<Type> type(zone_, bindType(node->pos(), node->type()));
dvander@195
   842
    if (!type)
dvander@195
   843
        return;
dvander@195
   844
dvander@195
   845
#if 0
dvander@195
   846
    if (node->postDimensions() || type->isArray()) {
dvander@195
   847
        // The type could be an array type, so sum the type and postDimensions
dvander@195
   848
        // together.
dvander@195
   849
        unsigned dimcount = node->postDimensions()->length();
dvander@195
   850
        if (type->isArray())
dvander@195
   851
            dimcount += type->levels();
dvander@195
   852
        if (dimcount > MAX_ARRAY_DEPTH) {
dvander@195
   853
            cc_.reportError(node->pos(), Message_MaximumArrayDepth);
dvander@195
   854
            return;
dvander@195
   855
        }
dvander@195
   856
dvander@195
   857
        // Take an initial guess at the array dimension sizes.
dvander@195
   858
        int dims[MAX_ARRAY_DEPTH];
dvander@195
   859
        if (!evaluateDimensions(node->postDimensions(), dims))
dvander@195
   860
            return;
dvander@195
   861
dvander@195
   862
        // Now add in the type's array dimensions.
dvander@195
   863
        Local<Type> contained(zone_, type);
dvander@195
   864
        for (size_t i = node->postDimensions()->length(); i < dimcount; i++) {
dvander@195
   865
            if (type->isFixedLength())
dvander@195
   866
                dims[i] = type->fixedLength();
dvander@195
   867
            else
dvander@195
   868
                dims[i] = DYNAMIC_ARRAY_SIZE;
dvander@195
   869
            contained = contained->contained();
dvander@195
   870
        }
dvander@195
   871
dvander@195
   872
        Expression *initializer = node->initialization();
dvander@195
   873
        if (initializer &&
dvander@195
   874
            initializer->isArrayLiteral() &&
dvander@195
   875
            initializer->toArrayLiteral()->isFixed())
dvander@195
   876
        {
dvander@195
   877
            // Fixed array initializers are special; we use them to infer any
dvander@195
   878
            // missing information in the original array. We do not evaluate
dvander@195
   879
            // the array initializer as an expression.
dvander@195
   880
            if (!inferFixedArrayLiteral(initializer->toArrayLiteral(),
dvander@195
   881
                                        contained,
dvander@195
   882
                                        dims,
dvander@195
   883
                                        dimcount,
dvander@195
   884
                                        0))
dvander@195
   885
            {
dvander@195
   886
                return;
dvander@195
   887
            }
dvander@195
   888
            initializer = NULL;
dvander@195
   889
        }
dvander@195
   890
dvander@195
   891
        // We now have enough information to build the actual array type.
dvander@195
   892
        // Start from the original dimcount, not the one computed for
dvander@195
   893
        // initializers.
dvander@195
   894
        for (size_t i = node->postDimensions()->length() - 1;
dvander@195
   895
             i < node->postDimensions()->length();
dvander@195
   896
             i--)
dvander@195
   897
        {
dvander@195
   898
            int size = dims[i] > 0
dvander@195
   899
                       ? dims[i]
dvander@195
   900
                       : Type::DYNAMIC_ARRAY_SIZE;
dvander@195
   901
dvander@195
   902
            type = zone_->types()->newArray(type, size, false);
dvander@195
   903
            if (!type)
dvander@195
   904
                return;
dvander@195
   905
        }
dvander@195
   906
dvander@195
   907
        // Finally, if we had a non-fixed initializer, make sure it type
dvander@195
   908
        // checks. 
dvander@195
   909
        if (initializer) {
dvander@195
   910
            Local<Type> right(zone_, visitForLoad(initializer));
dvander@195
   911
            if (!right)
dvander@195
   912
                return;
dvander@195
   913
dvander@195
   914
            if (!typeCheckAssignment(node->pos(), right, type, true))
dvander@195
   915
                return;
dvander@195
   916
        }
dvander@195
   917
    } else {
dvander@195
   918
        if (node->initialization()) {
dvander@195
   919
            Local<Type> right(zone_, visitForLoad(node->initialization()));
dvander@195
   920
            if (!right)
dvander@195
   921
                return;
dvander@195
   922
            if (!typeCheckAssignment(node->pos(), right, type, true))
dvander@195
   923
                return;
dvander@195
   924
        }
dvander@195
   925
dvander@195
   926
        if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
dvander@195
   927
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@195
   928
            return;
dvander@195
   929
        }
dvander@195
   930
    }
dvander@195
   931
#endif
dvander@195
   932
dvander@195
   933
#if 0
dvander@195
   934
    // If this variable is stack allocated, we could use the LIFO heap
dvander@195
   935
    // to allocate it. If that's the case, make sure to reserve a slot
dvander@195
   936
    // so we can unwind the LIFO heap at the end of this scope.
dvander@195
   937
    if (!node->variable()->needsHeapAllocation()) {
dvander@195
   938
        if (type->isArray() || type->isStruct())
dvander@195
   939
            scope_->setUsesLifoHeap();
dvander@195
   940
    }
dvander@195
   941
dvander@195
   942
    node->variable()->setType(type);
dvander@195
   943
#endif
dvander@195
   944
}
dvander@195
   945
dvander@195
   946
void
dvander@195
   947
SemanticAnalysis::visit(IntegerLiteral *node)
dvander@195
   948
{
dvander@195
   949
    node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@195
   950
}
dvander@195
   951
dvander@195
   952
void
dvander@195
   953
SemanticAnalysis::visit(BooleanLiteral *node)
dvander@195
   954
{
dvander@195
   955
    node->setType(zone_->types()->getPrimitive(PrimitiveType_Bool));
dvander@195
   956
}
dvander@195
   957
dvander@195
   958
void
dvander@195
   959
SemanticAnalysis::visit(ExpressionStatement *node)
dvander@195
   960
{
dvander@195
   961
    visitAndApplyType(node->expression());
dvander@195
   962
}
dvander@195
   963
dvander@195
   964
Box *
dvander@195
   965
SemanticAnalysis::evaluateDefaultParameter(Handle<Type> type, Parameter *parameter)
dvander@195
   966
{
dvander@195
   967
    Local<Type> given(zone_, visitForLoad(parameter->initializer()));
dvander@195
   968
dvander@195
   969
    BoxedPrimitive prim;
dvander@195
   970
    if (EvaluateForConstant(parameter->initializer(), &prim)) {
dvander@195
   971
        if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
dvander@195
   972
            return NULL;
dvander@195
   973
dvander@195
   974
        if (prim.type() == PrimitiveType_Int32)
dvander@195
   975
            return Box::New(zone_, given, prim.toInt());
dvander@195
   976
        return Box::New(zone_, given, prim.toFloat());
dvander@195
   977
    } else if (parameter->initializer()->isStringLiteral()) {
dvander@195
   978
        StringLiteral *literal = parameter->initializer()->toStringLiteral();
dvander@195
   979
dvander@195
   980
        if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
dvander@195
   981
            return NULL;
dvander@195
   982
dvander@195
   983
        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, given));
dvander@195
   984
        if (!map)
dvander@195
   985
            return NULL;
dvander@195
   986
dvander@195
   987
        Local<Array> array(zone_,
dvander@195
   988
            Array::NewString(zone_,
dvander@195
   989
                             map,
dvander@195
   990
                             literal->string()->raw(),
dvander@195
   991
                             literal->string()->length(),
dvander@195
   992
                             Heap::Tenure_Old));
dvander@195
   993
        if (!array)
dvander@195
   994
            return NULL;
dvander@195
   995
dvander@195
   996
        return Box::NewObj(zone_, given, array, Heap::Tenure_Old);
dvander@195
   997
    }
dvander@195
   998
dvander@195
   999
    cc_.reportError(parameter->initializer()->pos(), Message_MustBeConstant);
dvander@195
  1000
    return NULL;
dvander@195
  1001
}
dvander@195
  1002
dvander@195
  1003
bool
dvander@195
  1004
SemanticAnalysis::buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
dvander@195
  1005
                                    FixedArray **argsp, FixedArray **defaultsp)
dvander@195
  1006
{
dvander@195
  1007
    Local<FixedArray> args(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
dvander@195
  1008
    if (!args)
dvander@195
  1009
        return false;
dvander@195
  1010
dvander@195
  1011
    Local<FixedArray> defaults(zone_);
dvander@195
  1012
dvander@195
  1013
    // Apply types to arguments.
dvander@195
  1014
    for (size_t i = 0; i < sig.parameters()->length(); i++) {
dvander@195
  1015
        Parameter *parameter = sig.parameters()->at(i);
dvander@195
  1016
        
dvander@195
  1017
#if 0
dvander@195
  1018
        Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
dvander@195
  1019
        if (!type)
dvander@195
  1020
            return false;
dvander@195
  1021
dvander@195
  1022
        if (parameter->reference()) {
dvander@195
  1023
            if (parameter->dimensions()) {
dvander@195
  1024
                cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
dvander@195
  1025
                return false;
dvander@195
  1026
            }
dvander@195
  1027
dvander@195
  1028
            if (type->isStruct()) {
dvander@195
  1029
                cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
dvander@195
  1030
                return false;
dvander@195
  1031
            }
dvander@195
  1032
dvander@195
  1033
            type = zone_->types()->getReference(type, parameter->isConst());
dvander@195
  1034
            if (!type)
dvander@195
  1035
                return false;
dvander@195
  1036
        } else if (parameter->dimensions()) {
dvander@195
  1037
            type = buildArrayType(type, parameter->dimensions(), parameter->isConst());
dvander@195
  1038
            if (!type)
dvander@195
  1039
                return false;
dvander@195
  1040
dvander@195
  1041
            if (kind == TOK_NATIVE && type->levels() > 1) {
dvander@195
  1042
                cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
dvander@195
  1043
                return false;
dvander@195
  1044
            }
dvander@195
  1045
        }
dvander@195
  1046
dvander@195
  1047
        if (IsScalarString(type)) {
dvander@195
  1048
            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@195
  1049
            return false;
dvander@195
  1050
        }
dvander@195
  1051
dvander@195
  1052
        args->set(zone_, i, type);
dvander@195
  1053
        parameter->variable()->setType(type);
dvander@195
  1054
dvander@195
  1055
        if (parameter->initializer()) {
dvander@195
  1056
            if (!defaults) {
dvander@195
  1057
                defaults = FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old);
dvander@195
  1058
                if (!defaults)
dvander@195
  1059
                    return false;
dvander@195
  1060
            }
dvander@195
  1061
dvander@195
  1062
            Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
dvander@195
  1063
            if (!box)
dvander@195
  1064
                return false;
dvander@195
  1065
dvander@195
  1066
            defaults->set(zone_, i, box);
dvander@195
  1067
        }
dvander@195
  1068
#endif
dvander@195
  1069
    }
dvander@195
  1070
dvander@195
  1071
    *argsp = args;
dvander@195
  1072
    *defaultsp = defaults;
dvander@195
  1073
dvander@195
  1074
    return true;
dvander@195
  1075
}
dvander@195
  1076
dvander@195
  1077
void
dvander@195
  1078
SemanticAnalysis::visit(FunctionTypeStatement *node)
dvander@195
  1079
{
dvander@195
  1080
    if (node->decl()->type())
dvander@195
  1081
        return;
dvander@195
  1082
dvander@195
  1083
    Local<FixedArray> args(zone_);
dvander@195
  1084
    Local<FixedArray> defaults(zone_);
dvander@195
  1085
dvander@195
  1086
    const FunctionSignature &sig= node->signature();
dvander@195
  1087
    if (!buildFunctionArgs(node,
dvander@195
  1088
                           TOK_STOCK,
dvander@195
  1089
                           sig,
dvander@195
  1090
                           args.address(),
dvander@195
  1091
                           defaults.address()))
dvander@195
  1092
    {
dvander@195
  1093
        return;
dvander@195
  1094
    }
dvander@195
  1095
dvander@195
  1096
#if 0
dvander@195
  1097
    Local<Type> returnType(zone_);
dvander@195
  1098
    if (sig.returnType())
dvander@195
  1099
        returnType = bindType(node->pos(), sig.returnType());
dvander@195
  1100
    else
dvander@195
  1101
        returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
  1102
dvander@195
  1103
    if (!returnType)
dvander@195
  1104
        return;
dvander@195
  1105
dvander@195
  1106
    Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args, defaults));
dvander@195
  1107
    if (!funtype)
dvander@195
  1108
        return;
dvander@195
  1109
dvander@195
  1110
    node->decl()->setType(funtype);
dvander@195
  1111
#endif
dvander@195
  1112
}
dvander@195
  1113
dvander@195
  1114
Type *
dvander@195
  1115
SemanticAnalysis::buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst)
dvander@195
  1116
{
dvander@195
  1117
    Local<Type> arrayType(zone_, type);
dvander@195
  1118
dvander@195
  1119
    unsigned dimcount = dimensions->length();
dvander@195
  1120
    if (type->isArray())
dvander@195
  1121
        dimcount += type->levels();
dvander@195
  1122
dvander@195
  1123
    if (dimcount > MAX_ARRAY_DEPTH) {
dvander@195
  1124
        cc_.reportError(dimensions->at(dimensions->length() - 1)->pos(),
dvander@195
  1125
                        Message_MaximumArrayDepth);
dvander@195
  1126
        return false;
dvander@195
  1127
    }
dvander@195
  1128
dvander@195
  1129
    // Note: constness is sort of bogus. Fix this sometime.
dvander@195
  1130
    for (size_t i = dimensions->length() - 1; i < dimensions->length(); i--) {
dvander@195
  1131
        Expression *expr = dimensions->at(i);
dvander@195
  1132
        if (!expr) {
dvander@195
  1133
            arrayType = zone_->types()->newArray(arrayType, Type::DYNAMIC_ARRAY_SIZE, isConst);
dvander@195
  1134
            if (!arrayType)
dvander@195
  1135
                return NULL;
dvander@195
  1136
dvander@195
  1137
            continue;
dvander@195
  1138
        }
dvander@195
  1139
dvander@195
  1140
        BoxedPrimitive box;
dvander@195
  1141
        if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
dvander@195
  1142
            cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
dvander@195
  1143
            return NULL;
dvander@195
  1144
        }
dvander@195
  1145
dvander@195
  1146
        if (box.toInt() <= 0) {
dvander@195
  1147
            cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@195
  1148
            return NULL;
dvander@195
  1149
        }
dvander@195
  1150
dvander@195
  1151
        arrayType = zone_->types()->newArray(arrayType, box.toInt(), isConst);
dvander@195
  1152
        if (!arrayType)
dvander@195
  1153
            return NULL;
dvander@195
  1154
    }
dvander@195
  1155
dvander@195
  1156
    return arrayType;
dvander@195
  1157
}
dvander@195
  1158
dvander@195
  1159
bool
dvander@195
  1160
SemanticAnalysis::preanalyze(FunctionStatement *node)
dvander@195
  1161
{
dvander@195
  1162
    Local<FixedArray> args(zone_);
dvander@195
  1163
    Local<FixedArray> defaults(zone_);
dvander@195
  1164
dvander@195
  1165
    const FunctionSignature &sig = node->signature();
dvander@195
  1166
    if (!buildFunctionArgs(node,
dvander@195
  1167
                           node->fun()->token(),
dvander@195
  1168
                           sig,
dvander@195
  1169
                           args.address(),
dvander@195
  1170
                           defaults.address()))
dvander@195
  1171
    {
dvander@195
  1172
        return false;
dvander@195
  1173
    }
dvander@195
  1174
dvander@195
  1175
#if 0
dvander@195
  1176
    Local<Type> returnType(zone_);
dvander@195
  1177
    if (sig.returnType() ||
dvander@195
  1178
        node->hasExplicitReturn() ||
dvander@195
  1179
        node->fun()->isNative())
dvander@195
  1180
    {
dvander@195
  1181
        returnType = bindType(node->pos(), sig.returnType());
dvander@195
  1182
    } else {
dvander@195
  1183
        returnType = zone_->types()->getVoid();
dvander@195
  1184
    }
dvander@195
  1185
    if (!returnType)
dvander@195
  1186
        return false;
dvander@195
  1187
dvander@195
  1188
    if (sig.returnDimensions()) {
dvander@195
  1189
        returnType = buildArrayType(returnType, sig.returnDimensions(), false);
dvander@195
  1190
        if (!returnType)
dvander@195
  1191
            return false;
dvander@195
  1192
    }
dvander@195
  1193
dvander@195
  1194
    if (IsScalarString(returnType)) {
dvander@195
  1195
        cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
dvander@195
  1196
        return false;
dvander@195
  1197
    }
dvander@195
  1198
dvander@195
  1199
    Local<Type> funtype(zone_);
dvander@195
  1200
    if (node->fun()->isNative())
dvander@195
  1201
        funtype = zone_->types()->newNative(returnType, args, defaults, node->fun()->isNativeVariadic());
dvander@195
  1202
    else
dvander@195
  1203
        funtype = zone_->types()->newFunction(returnType, args, defaults);
dvander@195
  1204
    if (!funtype)
dvander@195
  1205
        return false;
dvander@195
  1206
    
dvander@195
  1207
    // If the function already has a type, it was forward declared before, and
dvander@195
  1208
    // now this is our chance to type check the second declaration.
dvander@195
  1209
    if (node->fun()->type()) {
dvander@195
  1210
        Local<Type> forward(zone_, node->fun()->type());
dvander@195
  1211
        if (!Type::Compare(funtype, forward)) {
dvander@195
  1212
            cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
dvander@195
  1213
            return false;
dvander@195
  1214
        }
dvander@195
  1215
        node->fun()->setForwardType(forward);
dvander@195
  1216
    }
dvander@195
  1217
dvander@195
  1218
    node->fun()->setType(funtype);
dvander@195
  1219
#endif
dvander@195
  1220
dvander@195
  1221
    return true;
dvander@195
  1222
}
dvander@195
  1223
dvander@195
  1224
void
dvander@195
  1225
SemanticAnalysis::visit(FunctionStatement *node)
dvander@195
  1226
{
dvander@195
  1227
    function_ = node->fun();
dvander@195
  1228
    scope_ = node->scope();
dvander@195
  1229
dvander@195
  1230
    ControlScope control(&control_);
dvander@195
  1231
    if (node->body()) {
dvander@195
  1232
        node->body()->accept(this);
dvander@195
  1233
dvander@195
  1234
        ControlStatus status = control.status();
dvander@195
  1235
        if (status.returns() == Returns_Sometimes) {
dvander@195
  1236
            cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
dvander@195
  1237
        } else if (status.returns() == Returns_Never) {
dvander@195
  1238
            if (!function_->type()->returnType()->isVoid())
dvander@195
  1239
                cc_.reportError(node->pos(), Message_MissingReturnValue);
dvander@195
  1240
        }
dvander@195
  1241
    }
dvander@195
  1242
dvander@195
  1243
    scope_ = NULL;
dvander@195
  1244
    function_ = NULL;
dvander@195
  1245
}
dvander@195
  1246
dvander@195
  1247
void
dvander@195
  1248
SemanticAnalysis::typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given)
dvander@195
  1249
{
dvander@195
  1250
    cc_.reportError(pos, Message_TypeMismatch,
dvander@195
  1251
                    GetTypeName(actual),
dvander@195
  1252
                    GetTypeName(given));
dvander@195
  1253
}
dvander@195
  1254
dvander@195
  1255
bool
dvander@195
  1256
SemanticAnalysis::typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> argGiven,
dvander@195
  1257
                                           Handle<Type> argActual, bool forAssign)
dvander@195
  1258
{
dvander@195
  1259
    Local<Type> actual(zone_, argActual);
dvander@195
  1260
    Local<Type> given(zone_, argGiven);
dvander@195
  1261
dvander@195
  1262
    if (!given->isArray()) {
dvander@195
  1263
        cc_.reportError(pos, Message_ExpectedArray);
dvander@195
  1264
        return false;
dvander@195
  1265
    }
dvander@195
  1266
    if (given->levels() != actual->levels()) {
dvander@195
  1267
        cc_.reportError(pos, Message_ArrayDimensionsMismatch);
dvander@195
  1268
        return false;
dvander@195
  1269
    }
dvander@195
  1270
dvander@195
  1271
    unsigned level = 1;
dvander@195
  1272
    while (given->isArray()) {
dvander@195
  1273
        if (actual->isFixedLength()) {
dvander@195
  1274
            if (forAssign) {
dvander@195
  1275
                if (!given->isFixedLength()) {
dvander@195
  1276
                    cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
dvander@195
  1277
                    return false;
dvander@195
  1278
                }
dvander@195
  1279
dvander@195
  1280
                if (actual->isCharArray()) {
dvander@195
  1281
                    // String assignment can have a truncated |given|.
dvander@195
  1282
                    if (given->fixedLength() > actual->fixedLength()) {
dvander@195
  1283
                        cc_.reportError(pos, Message_ArrayAssignmentTooBig);
dvander@195
  1284
                        return false;
dvander@195
  1285
                    }
dvander@195
  1286
                } else {
dvander@195
  1287
                    if (given->fixedLength() != actual->fixedLength()) {
dvander@195
  1288
                        cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
dvander@195
  1289
                        return false;
dvander@195
  1290
                    }
dvander@195
  1291
                }
dvander@195
  1292
            }
dvander@195
  1293
        } else if (given->isFixedLength()) {
dvander@195
  1294
            // We do not allow assignments in the form:
dvander@195
  1295
            //    [][] = [][Y]
dvander@195
  1296
            //
dvander@195
  1297
            // Otherwise, the following code could break the size guarantees
dvander@195
  1298
            // of the right-hand side:
dvander@195
  1299
            //
dvander@195
  1300
            //   new x[][5];
dvander@195
  1301
            //   new y[][];
dvander@195
  1302
            //   new z[3];
dvander@195
  1303
            //
dvander@195
  1304
            //   y = x;
dvander@195
  1305
            //   y[0] = z;
dvander@195
  1306
            //   
dvander@195
  1307
            // Now |x[0]| contains a 4-length array.
dvander@195
  1308
            if (level > 1) {
dvander@195
  1309
                cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
dvander@195
  1310
                return false;
dvander@195
  1311
            }
dvander@195
  1312
        }
dvander@195
  1313
        given = given->contained();
dvander@195
  1314
        actual = actual->contained();
dvander@195
  1315
        level++;
dvander@195
  1316
    }
dvander@195
  1317
dvander@195
  1318
    return typeCheckAssignment(pos, given, actual, forAssign);
dvander@195
  1319
}
dvander@195
  1320
dvander@195
  1321
bool
dvander@195
  1322
SemanticAnalysis::typeCheckAssignment(const SourcePosition &pos, Handle<Type> argGiven,
dvander@195
  1323
                                      Handle<Type> argActual, bool forAssign)
dvander@195
  1324
{
dvander@195
  1325
    Local<Type> actual(zone_, argActual);
dvander@195
  1326
    Local<Type> given(zone_, argGiven);
dvander@195
  1327
dvander@195
  1328
    if (actual->isArray())
dvander@195
  1329
        return typeCheckArrayAssignment(pos, given, actual, forAssign);
dvander@195
  1330
dvander@195
  1331
    if (given->isArray()) {
dvander@195
  1332
        cc_.reportError(pos, Message_CannotAssignArrayToScalar);
dvander@195
  1333
        return false;
dvander@195
  1334
    }
dvander@195
  1335
dvander@195
  1336
    // The given type may not have been dereferenced.
dvander@195
  1337
    if (given->isReference())
dvander@195
  1338
        given = given->contained();
dvander@195
  1339
    if (actual->isReference())
dvander@195
  1340
        actual = actual->contained();
dvander@195
  1341
dvander@195
  1342
    // We coerce unchecked to a few things.
dvander@195
  1343
    if (actual->isUnchecked() || given->isUnchecked()) {
dvander@195
  1344
        Type *check = actual->isUnchecked() ? given : actual;
dvander@195
  1345
        if (check->isUnchecked() ||
dvander@195
  1346
            check->isEnum() ||
dvander@195
  1347
            check->isInt32() ||
dvander@195
  1348
            check->isBool() ||
dvander@195
  1349
            check->isFloat())
dvander@195
  1350
        {
dvander@195
  1351
            return true;
dvander@195
  1352
        }
dvander@195
  1353
        typeMismatch(pos, actual, given);
dvander@195
  1354
        return false;
dvander@195
  1355
    }
dvander@195
  1356
dvander@195
  1357
    if (given->isFunction() && actual->isFunction()) {
dvander@195
  1358
        if (!Type::Compare(given, actual)) {
dvander@195
  1359
            typeMismatch(pos, actual, given);
dvander@195
  1360
            return false;
dvander@195
  1361
        }
dvander@195
  1362
        return true;
dvander@195
  1363
    }
dvander@195
  1364
dvander@195
  1365
    if (actual->isEnum()) {
dvander@195
  1366
        if (!given->isEnum() || actual != given) {
dvander@195
  1367
            typeMismatch(pos, actual, given);
dvander@195
  1368
            return false;
dvander@195
  1369
        }
dvander@195
  1370
        return true;
dvander@195
  1371
    }
dvander@195
  1372
dvander@195
  1373
    if (actual->isStruct()) {
dvander@195
  1374
        if (!given->isStruct() || actual != given) {
dvander@195
  1375
            typeMismatch(pos, actual, given);
dvander@195
  1376
            return false;
dvander@195
  1377
        }
dvander@195
  1378
        return true;
dvander@195
  1379
    }
dvander@195
  1380
dvander@195
  1381
    if (given->isEnum() || given->isFunction() || given->isStruct()) {
dvander@195
  1382
        typeMismatch(pos, actual, given);
dvander@195
  1383
        return false;
dvander@195
  1384
    }
dvander@195
  1385
dvander@195
  1386
    // This coercion is trivial.
dvander@195
  1387
    if (given->isBool() && actual->isInt32())
dvander@195
  1388
        return true;
dvander@195
  1389
dvander@195
  1390
    if (given->primitive() != actual->primitive()) {
dvander@195
  1391
        typeMismatch(pos, actual, given);
dvander@195
  1392
        return false;
dvander@195
  1393
    }
dvander@195
  1394
dvander@195
  1395
    return true;
dvander@195
  1396
}
dvander@195
  1397
dvander@195
  1398
bool
dvander@195
  1399
SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
dvander@195
  1400
{
dvander@195
  1401
    return typeCheckAssignment(node->pos(), given, actual, false);
dvander@195
  1402
}
dvander@195
  1403
dvander@195
  1404
bool
dvander@195
  1405
SemanticAnalysis::checkArgumentCount(Handle<Type> type, unsigned actual)
dvander@195
  1406
{
dvander@195
  1407
    if (type->parameters()->length() == actual)
dvander@195
  1408
        return true;
dvander@195
  1409
dvander@195
  1410
    if (actual > type->parameters()->length()) {
dvander@195
  1411
        if (!type->isNative() || !type->isNativeVariadic())
dvander@195
  1412
            return false;
dvander@195
  1413
        return true;
dvander@195
  1414
    }
dvander@195
  1415
dvander@195
  1416
    if (!type->defaults())
dvander@195
  1417
        return false;
dvander@195
  1418
dvander@195
  1419
    // Missing arguments. See if there's a default argument for each missing
dvander@195
  1420
    // actual.
dvander@195
  1421
    for (unsigned i = actual; i < type->parameters()->length(); i++) {
dvander@195
  1422
        if (!type->defaults()->at(i))
dvander@195
  1423
            return false;
dvander@195
  1424
    }
dvander@195
  1425
dvander@195
  1426
    return true;
dvander@195
  1427
}
dvander@195
  1428
dvander@195
  1429
void
dvander@195
  1430
SemanticAnalysis::visit(CallExpression *node)
dvander@195
  1431
{
dvander@195
  1432
    Local<Type> type(zone_, visitForLoad(node->callee()));
dvander@195
  1433
    if (!type)
dvander@195
  1434
        return;
dvander@195
  1435
dvander@195
  1436
    if (!type->isFunction()) {
dvander@195
  1437
        cc_.reportError(node->pos(), Message_CalleeNotFunction);
dvander@195
  1438
        return;
dvander@195
  1439
    }
dvander@195
  1440
dvander@195
  1441
    if (!checkArgumentCount(type, node->arguments()->length())) {
dvander@195
  1442
        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
dvander@195
  1443
        return;
dvander@195
  1444
    }
dvander@195
  1445
dvander@195
  1446
    // NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
dvander@195
  1447
    // if (fun->isForward()) {
dvander@195
  1448
    //     cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
dvander@195
  1449
    //     return;
dvander@195
  1450
    // }
dvander@195
  1451
dvander@195
  1452
    for (unsigned i = 0; i < node->arguments()->length(); i++) {
dvander@195
  1453
        // Note: we don't compute references unless the callee needs a
dvander@195
  1454
        // reference type.
dvander@195
  1455
        Expression *expression = node->arguments()->at(i);
dvander@195
  1456
        Local<Type> given(zone_, visitAndApplyType(expression));
dvander@195
  1457
        if (!given)
dvander@195
  1458
            return;
dvander@195
  1459
dvander@195
  1460
        // Since we skip a load, check for a call expression that returns void.
dvander@195
  1461
        if (given->isVoid()) {
dvander@195
  1462
            assert(expression->isCallExpression());
dvander@195
  1463
            CallExpression *call = expression->toCallExpression();
dvander@195
  1464
            cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
dvander@195
  1465
            return;
dvander@195
  1466
        }
dvander@195
  1467
        
dvander@195
  1468
        bool mustComputeReference;
dvander@195
  1469
        if (i >= type->parameters()->length()) {
dvander@195
  1470
            // Special handling for natives. Arguments past the formal must
dvander@195
  1471
            // always have references computed. However, arrays are already
dvander@195
  1472
            // references for natives.  
dvander@195
  1473
            assert(type->isNative() && type->isNativeVariadic());
dvander@195
  1474
            mustComputeReference = !given->isReference() && !given->isArray();
dvander@195
  1475
        } else {
dvander@195
  1476
            Local<Type> actual(zone_, type->parameterAt(i));
dvander@195
  1477
dvander@195
  1478
            if (expression->isIndexExpression()) {
dvander@195
  1479
                // Disabled until we can make it work.
dvander@195
  1480
#if 0
dvander@195
  1481
                if (actual->isArray()) {
dvander@195
  1482
                    // We special case the ability to pass x[y] into x[], which
dvander@195
  1483
                    // creates an array slice. We only do this if we know the
dvander@195
  1484
                    // assignment would otherwise not type-check.
dvander@195
  1485
                    IndexExpression *index = expression->toIndexExpression();
dvander@195
  1486
                    if (index->left()->type()->levels() == actual->levels())
dvander@195
  1487
                        given = index->left()->type();
dvander@195
  1488
                } else
dvander@195
  1489
#endif
dvander@195
  1490
                if (actual->isReference()) {
dvander@195
  1491
                    cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
dvander@195
  1492
                    return;
dvander@195
  1493
                }
dvander@195
  1494
            }
dvander@195
  1495
dvander@195
  1496
            if (!typeCheckParameter(expression, given, actual))
dvander@195
  1497
                return;
dvander@195
  1498
            mustComputeReference = actual->isReference() && !given->isReference();
dvander@195
  1499
        }
dvander@195
  1500
dvander@195
  1501
        // If the actual is a reference, and the given is not, we'll need to
dvander@195
  1502
        // compute a reference, which may be allocated on the stack.
dvander@195
  1503
        if (mustComputeReference)
dvander@195
  1504
            scope_->setUsesLifoHeap();
dvander@195
  1505
    }
dvander@195
  1506
dvander@195
  1507
    node->setType(type->returnType());
dvander@195
  1508
}
dvander@195
  1509
dvander@195
  1510
void
dvander@195
  1511
SemanticAnalysis::ControlScope::inherit(const ControlStatus &other)
dvander@195
  1512
{
dvander@195
  1513
    if (other.returns() < status().returns())
dvander@195
  1514
        return;
dvander@195
  1515
dvander@195
  1516
    if (other.terminates())
dvander@195
  1517
        terminate(other.returns());
dvander@195
  1518
    else
dvander@195
  1519
        returns(other.returns());
dvander@195
  1520
}
dvander@195
  1521
dvander@195
  1522
void
dvander@195
  1523
SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
dvander@195
  1524
{
dvander@195
  1525
    // If both sides terminate in a return, we consider this a return as well.
dvander@195
  1526
    if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
dvander@195
  1527
        terminate(Returns_Always);
dvander@195
  1528
        return;
dvander@195
  1529
    }
dvander@195
  1530
dvander@195
  1531
    ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
dvander@195
  1532
                          ? Returns_Never
dvander@195
  1533
                          : Returns_Sometimes;
dvander@195
  1534
dvander@195
  1535
    if (left.terminates() && right.terminates())
dvander@195
  1536
        terminate(status);
dvander@195
  1537
    else
dvander@195
  1538
        returns(status);
dvander@195
  1539
}
dvander@195
  1540
dvander@195
  1541
void
dvander@195
  1542
SemanticAnalysis::visit(IfStatement *node)
dvander@195
  1543
{
dvander@195
  1544
    Local<Type> type(zone_, visitForLoad(node->condition()));
dvander@195
  1545
    if (!type)
dvander@195
  1546
        return;
dvander@195
  1547
dvander@195
  1548
    if (!canTest(node, type))
dvander@195
  1549
        return;
dvander@195
  1550
dvander@195
  1551
    ControlStatus trueBranch = visitForControl(node->ifTrue());
dvander@195
  1552
    ControlStatus falseBranch = ControlStatus(false, Returns_Never);
dvander@195
  1553
dvander@195
  1554
    if (node->ifFalse())
dvander@195
  1555
        falseBranch = visitForControl(node->ifFalse());
dvander@195
  1556
dvander@195
  1557
    control_->merge(trueBranch, falseBranch);
dvander@195
  1558
}
dvander@195
  1559
dvander@195
  1560
void
dvander@195
  1561
SemanticAnalysis::visit(IndexExpression *node)
dvander@195
  1562
{
dvander@195
  1563
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@195
  1564
    Local<Type> right(zone_, visitForLoad(node->right()));
dvander@195
  1565
dvander@195
  1566
    if (!left || !right)
dvander@195
  1567
        return;
dvander@195
  1568
dvander@195
  1569
    if (!right->isInt32() && !right->isEnum()) {
dvander@195
  1570
        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
dvander@195
  1571
        return;
dvander@195
  1572
    }
dvander@195
  1573
    if (!left->isArray()) {
dvander@195
  1574
        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
dvander@195
  1575
        return;
dvander@195
  1576
    }
dvander@195
  1577
dvander@195
  1578
    // Note: char arrays are automatically up-casted to return an int32.
dvander@195
  1579
    if (left->isCharArray())
dvander@195
  1580
        node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
dvander@195
  1581
    else
dvander@195
  1582
        node->setType(left->contained());
dvander@195
  1583
}
dvander@195
  1584
dvander@195
  1585
void
dvander@195
  1586
SemanticAnalysis::visit(FieldExpression *node)
dvander@195
  1587
{
dvander@195
  1588
    Local<Type> left(zone_, visitForLoad(node->left()));
dvander@195
  1589
    if (!left)
dvander@195
  1590
        return;
dvander@195
  1591
dvander@195
  1592
    if (!left->isStruct()) {
dvander@195
  1593
        cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
dvander@195
  1594
                        GetTypeName(left));
dvander@195
  1595
        return;
dvander@195
  1596
    }
dvander@195
  1597
dvander@195
  1598
    Local<String> field(zone_, node->field());
dvander@195
  1599
dvander@195
  1600
    unsigned offset;
dvander@195
  1601
    Local<Descriptor> desc(zone_, left->lookupField(field, &offset));
dvander@195
  1602
    if (!desc) {
dvander@195
  1603
        cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
dvander@195
  1604
                        GetTypeName(left));
dvander@195
  1605
        return;
dvander@195
  1606
    }
dvander@195
  1607
dvander@195
  1608
    node->setFieldIndex(offset);
dvander@195
  1609
    node->setType(desc->type());
dvander@195
  1610
}
dvander@195
  1611
dvander@195
  1612
void
dvander@195
  1613
SemanticAnalysis::visit(EnumStatement *node)
dvander@195
  1614
{
dvander@195
  1615
    Local<String> name(zone_, node->name());
dvander@195
  1616
    Local<Type> type(zone_);
dvander@195
  1617
    if (name)
dvander@195
  1618
        type = zone_->types()->newEnum(name);
dvander@195
  1619
    else
dvander@195
  1620
        type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
  1621
dvander@195
  1622
    if (!type)
dvander@195
  1623
        return;
dvander@195
  1624
dvander@195
  1625
    if (node->decl())
dvander@195
  1626
        node->decl()->setType(type);
dvander@195
  1627
dvander@195
  1628
    int value = 0;
dvander@195
  1629
    for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@195
  1630
        EnumStatement::Entry &entry = node->entries()->at(i);
dvander@195
  1631
dvander@195
  1632
        BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@195
  1633
        if (entry.expr) {
dvander@195
  1634
            entry.expr->accept(this);
dvander@195
  1635
            if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
dvander@195
  1636
                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@195
  1637
                return;
dvander@195
  1638
            }
dvander@195
  1639
dvander@195
  1640
            assert(box.type() == PrimitiveType_Int32);
dvander@195
  1641
            value = box.toInt();
dvander@195
  1642
        }
dvander@195
  1643
dvander@195
  1644
#if 0
dvander@195
  1645
        entry.name->set(type, box);
dvander@195
  1646
#endif
dvander@195
  1647
        value++;
dvander@195
  1648
    }
dvander@195
  1649
}
dvander@195
  1650
dvander@195
  1651
static int
dvander@195
  1652
SortCaseIntValues(const void *p1, const void *p2)
dvander@195
  1653
{
dvander@195
  1654
    CaseValue *v1 = (CaseValue *)p1;
dvander@195
  1655
    CaseValue *v2 = (CaseValue *)p2;
dvander@195
  1656
dvander@195
  1657
    return v1->box.toInt() - v2->box.toInt();
dvander@195
  1658
}
dvander@195
  1659
dvander@195
  1660
void
dvander@195
  1661
SemanticAnalysis::visit(SwitchStatement *node)
dvander@195
  1662
{
dvander@195
  1663
    Local<Type> caseType(zone_, visitForLoad(node->expression()));
dvander@195
  1664
    if (!caseType)
dvander@195
  1665
        return;
dvander@195
  1666
dvander@195
  1667
    if (!caseType->isEnum() && !caseType->isInt32()) {
dvander@195
  1668
        cc_.reportError(node->pos(), Message_CaseMustBeInteger);
dvander@195
  1669
        return;
dvander@195
  1670
    }
dvander@195
  1671
dvander@195
  1672
    PoolList<CaseValue> *values = new (zone_->pool()) PoolList<CaseValue>();
dvander@195
  1673
    ControlStatus status = ControlStatus(false, Returns_Never);
dvander@195
  1674
dvander@195
  1675
    Local<Type> check(zone_);
dvander@195
  1676
    for (size_t i = 0; i < node->cases()->length(); i++) {
dvander@195
  1677
        Case *c = node->cases()->at(i);
dvander@195
  1678
dvander@195
  1679
        check = visitForLoad(c->expression());
dvander@195
  1680
        if (!check)
dvander@195
  1681
            return;
dvander@195
  1682
dvander@195
  1683
        if (!typeCheckAssignment(c->expression()->pos(), check, caseType, false))
dvander@195
  1684
            return;
dvander@195
  1685
dvander@195
  1686
        CaseValue v(i);
dvander@195
  1687
        if (!EvaluateForConstant(c->expression(), &v.box)) {
dvander@195
  1688
            cc_.reportError(c->expression()->pos(), Message_CaseMustBeConstant);
dvander@195
  1689
            return;
dvander@195
  1690
        }
dvander@195
  1691
        if (!values->append(v))
dvander@195
  1692
            return;
dvander@195
  1693
dvander@195
  1694
        if (c->others()) {
dvander@195
  1695
            for (size_t j = 0; j < c->others()->length(); j++) {
dvander@195
  1696
                Expression *expr = c->others()->at(j);
dvander@195
  1697
                check = visitForLoad(expr);
dvander@195
  1698
                if (!check)
dvander@195
  1699
                    return;
dvander@195
  1700
dvander@195
  1701
                if (!typeCheckAssignment(expr->pos(), check, caseType, false))
dvander@195
  1702
                    return;
dvander@195
  1703
dvander@195
  1704
                CaseValue v(i);
dvander@195
  1705
                if (!EvaluateForConstant(expr, &v.box)) {
dvander@195
  1706
                    cc_.reportError(expr->pos(), Message_CaseMustBeConstant);
dvander@195
  1707
                    return;
dvander@195
  1708
                }
dvander@195
  1709
                if (!values->append(v))
dvander@195
  1710
                    return;
dvander@195
  1711
            }
dvander@195
  1712
        }
dvander@195
  1713
dvander@195
  1714
        ControlStatus latest = visitForControl(c->statement());
dvander@195
  1715
dvander@195
  1716
        if (i != 0)
dvander@195
  1717
            control_->merge(status, latest);
dvander@195
  1718
dvander@195
  1719
        status = latest;
dvander@195
  1720
    }
dvander@195
  1721
dvander@195
  1722
    if (node->defaultCase()) {
dvander@195
  1723
        ControlStatus latest = visitForControl(node->defaultCase());
dvander@195
  1724
dvander@195
  1725
        if (node->cases()->length()) {
dvander@195
  1726
            // If we had any other cases, we must merge.
dvander@195
  1727
            control_->merge(status, latest);
dvander@195
  1728
        } else {
dvander@195
  1729
            // Otherwise, control-flow always flows through here.
dvander@195
  1730
            control_->inherit(latest);
dvander@195
  1731
        }
dvander@195
  1732
    } else if (node->cases()->length()) {
dvander@195
  1733
        control_->merge(status, ControlStatus(false, Returns_Never));
dvander@195
  1734
    }
dvander@195
  1735
dvander@195
  1736
    if (values->length() > 1) {
dvander@195
  1737
        qsort(values->buffer(), values->length(), sizeof(CaseValue), SortCaseIntValues);
dvander@195
  1738
dvander@195
  1739
        for (size_t i = 1; i < values->length(); i++) {
dvander@195
  1740
            CaseValue &prev = values->at(i - 1);
dvander@195
  1741
            CaseValue &cur = values->at(i);
dvander@195
  1742
            if (prev.box.toInt() == cur.box.toInt()) {
dvander@195
  1743
                cc_.reportError(node->cases()->at(cur.statement)->expression()->pos(), Message_CaseHasSameValue);
dvander@195
  1744
                return;
dvander@195
  1745
            }
dvander@195
  1746
        }
dvander@195
  1747
    }
dvander@195
  1748
dvander@195
  1749
    node->setCaseValueList(values);
dvander@195
  1750
}
dvander@195
  1751
dvander@195
  1752
void
dvander@195
  1753
SemanticAnalysis::visit(StructureStatement *node)
dvander@195
  1754
{
dvander@195
  1755
#if 0
dvander@195
  1756
    // If this node already has a type, it was pre-analyzed, so skip it.
dvander@195
  1757
    if (node->decl()->type())
dvander@195
  1758
        return;
dvander@195
  1759
dvander@195
  1760
    FieldList *fields = node->fields();
dvander@195
  1761
    Local<FixedArray> desctable(zone_, FixedArray::New(zone_, fields->length(), Heap::Tenure_Old));
dvander@195
  1762
    if (!desctable)
dvander@195
  1763
        return;
dvander@195
  1764
dvander@195
  1765
    Vector<unsigned> composedList;
dvander@195
  1766
    StructureBufferBuilder builder;
dvander@195
  1767
dvander@195
  1768
    Local<Type> type(zone_);
dvander@195
  1769
    Local<String> name(zone_);
dvander@195
  1770
    Local<Descriptor> desc(zone_);
dvander@195
  1771
    for (size_t i = 0; i < fields->length(); i++) {
dvander@195
  1772
        StructureStatement::Field *field = fields->at(i);
dvander@195
  1773
dvander@195
  1774
        type = bindType(field->pos(), field->type());
dvander@195
  1775
        if (!type)
dvander@195
  1776
            return;
dvander@195
  1777
dvander@195
  1778
        if (field->dimensions()) {
dvander@195
  1779
            type = buildArrayType(type, field->dimensions(), false);
dvander@195
  1780
            if (!type)
dvander@195
  1781
                return;
dvander@195
  1782
dvander@195
  1783
            if (!ArrayMap::Attach(zone_, type))
dvander@195
  1784
                return;
dvander@195
  1785
        }
dvander@195
  1786
dvander@195
  1787
        if (IsScalarString(type)) {
dvander@195
  1788
            cc_.reportError(field->pos(), Message_CannotDeclareStringCell);
dvander@195
  1789
            return;
dvander@195
  1790
        }
dvander@195
  1791
dvander@195
  1792
        unsigned offset;
dvander@195
  1793
        if (!builder.add(type, &offset))
dvander@195
  1794
            return;
dvander@195
  1795
dvander@195
  1796
        name = field->name();
dvander@195
  1797
        desc = Descriptor::New(zone_, name, type, offset);
dvander@195
  1798
        if (!desc)
dvander@195
  1799
            return;
dvander@195
  1800
dvander@195
  1801
        desctable->set(zone_, i, desc);
dvander@195
  1802
dvander@195
  1803
        if (type->isStruct() || type->isArray()) {
dvander@195
  1804
            if (!composedList.append(i))
dvander@195
  1805
                return;
dvander@195
  1806
        }
dvander@195
  1807
    }
dvander@195
  1808
dvander@195
  1809
    Local<FixedArray> composed(zone_);
dvander@195
  1810
    if (composedList.length()) {
dvander@195
  1811
        composed = FixedArray::New(zone_, composedList.length(), Heap::Tenure_Old);
dvander@195
  1812
        if (!composed)
dvander@195
  1813
            return;
dvander@195
  1814
dvander@195
  1815
        for (unsigned i = 0; i < composedList.length(); i++)
dvander@195
  1816
            composed->set(zone_, i, desctable->at(i));
dvander@195
  1817
    }
dvander@195
  1818
dvander@195
  1819
    Local<StructMap> map(zone_, StructMap::New(zone_, builder, composed));
dvander@195
  1820
    if (!map)
dvander@195
  1821
        return;
dvander@195
  1822
dvander@195
  1823
    name = node->decl()->name();
dvander@195
  1824
    type = zone_->types()->newStruct(name, desctable, map);
dvander@195
  1825
    if (!type)
dvander@195
  1826
        return;
dvander@195
  1827
dvander@195
  1828
    map->setType(type);
dvander@195
  1829
    node->decl()->setType(type);
dvander@195
  1830
#endif
dvander@195
  1831
}
dvander@195
  1832
dvander@195
  1833
void
dvander@195
  1834
SemanticAnalysis::visit(StringLiteral *node)
dvander@195
  1835
{
dvander@195
  1836
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
dvander@195
  1837
    if (!type)
dvander@195
  1838
        return;
dvander@195
  1839
dvander@195
  1840
    type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
dvander@195
  1841
    if (!type)
dvander@195
  1842
        return;
dvander@195
  1843
dvander@195
  1844
    node->setType(type);
dvander@195
  1845
}
dvander@195
  1846
dvander@195
  1847
void
dvander@195
  1848
SemanticAnalysis::visit(FloatLiteral *node)
dvander@195
  1849
{
dvander@195
  1850
    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
dvander@195
  1851
    if (!type)
dvander@195
  1852
        return;
dvander@195
  1853
dvander@195
  1854
    node->setType(type);
dvander@195
  1855
}
dvander@195
  1856
dvander@195
  1857
void
dvander@195
  1858
SemanticAnalysis::visit(BreakStatement *node)
dvander@195
  1859
{
dvander@195
  1860
    if (!loop_) {
dvander@195
  1861
        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
dvander@195
  1862
        return;
dvander@195
  1863
    }
dvander@195
  1864
dvander@195
  1865
    // Note: ignore breaks that occur in unreachable control-flow.
dvander@195
  1866
    if (!control_->status().terminates())
dvander@195
  1867
        loop_->addBreak();
dvander@195
  1868
dvander@195
  1869
    control_->terminate(Returns_Never);
dvander@195
  1870
}
dvander@195
  1871
dvander@195
  1872
void
dvander@195
  1873
SemanticAnalysis::visit(ContinueStatement *node)
dvander@195
  1874
{
dvander@195
  1875
    if (!loop_) {
dvander@195
  1876
        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
dvander@195
  1877
        return;
dvander@195
  1878
    }
dvander@195
  1879
dvander@195
  1880
    // Note: ignore continues that occur in unreachable control-flow.
dvander@195
  1881
    if (!control_->status().terminates())
dvander@195
  1882
        loop_->addContinue();
dvander@195
  1883
dvander@195
  1884
    control_->terminate(Returns_Never);
dvander@195
  1885
}
dvander@195
  1886
dvander@195
  1887
void
dvander@195
  1888
SemanticAnalysis::visit(ArrayLiteral *node)
dvander@195
  1889
{
dvander@195
  1890
    // We should never visit this.
dvander@195
  1891
    cc_.reportError(node->pos(), Message_UnexpectedArrayLiteral);
dvander@195
  1892
}
dvander@195
  1893
dvander@195
  1894
void
dvander@195
  1895
SemanticAnalysis::visit(ImportStatement *node)
dvander@195
  1896
{
dvander@195
  1897
}
dvander@195
  1898
dvander@195
  1899
#endif