src/compiler/NameBinding.cpp
author David Anderson <dvander@alliedmods.net>
Mon Nov 19 01:13:44 2012 -0800 (2012-11-19)
changeset 220 5df4a112967d
parent 217 c22e983b3b6e
child 222 0cde1379b29f
permissions -rw-r--r--
Re-added parameter support.
dvander@137
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@137
     2
 *
dvander@0
     3
 * Copyright (C) 2012 David Anderson
dvander@0
     4
 *
dvander@137
     5
 * This file is part of SourcePawn.
dvander@0
     6
 *
dvander@137
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@0
     8
 * the terms of the GNU General Public License as published by the Free
dvander@0
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
    10
 * any later version.
dvander@0
    11
 * 
dvander@137
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    15
 *
dvander@0
    16
 * You should have received a copy of the GNU General Public License along with
dvander@137
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@0
    18
 */
dvander@195
    19
#include "../Strings.h"
dvander@195
    20
#include "../Zone.h"
dvander@195
    21
#include "../TypeManager.h"
dvander@0
    22
#include "NameBinding.h"
dvander@85
    23
#include "Scopes.h"
dvander@209
    24
#include "ConstantEvaluator.h"
dvander@195
    25
#include "../Spaces-inl.h"
dvander@195
    26
#include "../Heap-inl.h"
dvander@0
    27
dvander@59
    28
using namespace ke;
dvander@0
    29
dvander@195
    30
// Create symbol tables and symbols for every scope and declaration. For type
dvander@195
    31
// declarations and methods, we also pre-allocate a Type object, so that
dvander@195
    32
// circular dependencies between types will work.
dvander@195
    33
class NamePopulator : public AstVisitor
dvander@0
    34
{
dvander@195
    35
  private:
dvander@195
    36
    // This class is analagous to a Scope, however, it allows us to create
dvander@195
    37
    // scopes lazily. If a scope is requested, and the current environment
dvander@195
    38
    // has no scope, then a scope is created. If no scope is ever requested,
dvander@195
    39
    // a scope does not need to be created.
dvander@195
    40
    class SymbolEnv
dvander@195
    41
    {
dvander@195
    42
      public:
dvander@195
    43
        SymbolEnv(SymbolEnv **prevp, Scope *scope = NULL)
dvander@195
    44
          : envp_(prevp),
dvander@195
    45
            prev_(*prevp),
dvander@195
    46
            scope_(scope)
dvander@195
    47
        {
dvander@195
    48
            *envp_ = this;
dvander@195
    49
        }
dvander@195
    50
        ~SymbolEnv() {
dvander@195
    51
            *envp_ = prev_;
dvander@195
    52
        }
dvander@195
    53
dvander@195
    54
        Scope *scope() {
dvander@195
    55
            return scope_;
dvander@195
    56
        }
dvander@195
    57
        void setScope(Scope *scope) {
dvander@195
    58
            assert(!scope_);
dvander@195
    59
            scope_ = scope;
dvander@195
    60
        }
dvander@195
    61
        SymbolEnv *prev() const {
dvander@195
    62
            return prev_;
dvander@195
    63
        }
dvander@195
    64
dvander@195
    65
      private:
dvander@195
    66
        SymbolEnv **envp_;
dvander@195
    67
        SymbolEnv *prev_;
dvander@195
    68
        Scope *scope_;
dvander@195
    69
    };
dvander@195
    70
dvander@195
    71
    enum ReturnStatus {
dvander@195
    72
        NoReturn,
dvander@195
    73
        VoidReturn,
dvander@195
    74
        ValueReturn
dvander@195
    75
    };
dvander@195
    76
dvander@195
    77
    class FunctionScope
dvander@195
    78
    {
dvander@195
    79
      public:
dvander@195
    80
        FunctionScope(FunctionScope **prevp)
dvander@195
    81
          : prevp_(prevp),
dvander@195
    82
            prev_(*prevp),
dvander@195
    83
            status_(NoReturn)
dvander@195
    84
        {
dvander@195
    85
            *prevp_ = this;
dvander@195
    86
        }
dvander@195
    87
        ~FunctionScope() {
dvander@195
    88
            *prevp_ = prev_;
dvander@195
    89
        }
dvander@195
    90
        ReturnStatus returns() const {
dvander@195
    91
            return status_;
dvander@195
    92
        }
dvander@195
    93
        void returns(ReturnStatus status) {
dvander@195
    94
            if (status > status_)
dvander@195
    95
                status_ = status;
dvander@195
    96
        }
dvander@195
    97
      private:
dvander@195
    98
        FunctionScope **prevp_;
dvander@195
    99
        FunctionScope *prev_;
dvander@195
   100
        ReturnStatus status_;
dvander@195
   101
    };
dvander@195
   102
dvander@195
   103
  public:
dvander@195
   104
    NamePopulator(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@195
   105
      : zone_(zone),
dvander@195
   106
        pool_(zone->pool()),
dvander@195
   107
        cc_(cc),
dvander@195
   108
        unit_(unit),
dvander@195
   109
        env_(NULL),
dvander@195
   110
        fun_(NULL)
dvander@195
   111
    {
dvander@195
   112
    }
dvander@195
   113
dvander@195
   114
    bool analyze() {
dvander@195
   115
        ImportScope *importScope = ImportScope::New(pool_);
dvander@195
   116
        if (!importScope)
dvander@195
   117
            return false;
dvander@195
   118
dvander@195
   119
        // At the import level, we declare system types.
dvander@195
   120
        if (!declareSystemTypes(importScope))
dvander@195
   121
            return false;
dvander@195
   122
dvander@195
   123
        GlobalScope *globalScope = GlobalScope::New(pool_, importScope);
dvander@195
   124
        if (!globalScope)
dvander@195
   125
            return false;
dvander@195
   126
dvander@195
   127
        unit_->setImportScope(importScope);
dvander@195
   128
        unit_->setGlobalScope(globalScope);
dvander@195
   129
dvander@195
   130
        SymbolEnv env(&env_, globalScope);
dvander@195
   131
dvander@195
   132
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
dvander@195
   133
            Statement *stmt = unit_->tree()->statements()->at(i);
dvander@195
   134
            stmt->accept(this);
dvander@195
   135
        }
dvander@195
   136
dvander@195
   137
        return true;
dvander@195
   138
    }
dvander@195
   139
dvander@195
   140
    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
dvander@195
   141
        Local<String> tag(zone_, zone_->makeSymbol(name));
dvander@195
   142
        if (!tag)
dvander@195
   143
            return false;
dvander@195
   144
dvander@195
   145
        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
dvander@195
   146
        return scope->addSymbol(sym);
dvander@195
   147
    }
dvander@195
   148
dvander@195
   149
    bool declareSystemType(ImportScope *scope, const char *name, PrimitiveType prim) {
dvander@195
   150
        Local<Type> primitive(zone_, zone_->types()->getPrimitive(prim));
dvander@195
   151
        assert(primitive);
dvander@195
   152
        return declareSystemType(scope, name, primitive);
dvander@195
   153
    }
dvander@195
   154
dvander@195
   155
    bool declareSystemTypes(ImportScope *scope) {
dvander@195
   156
        if (!declareSystemType(scope, "float", PrimitiveType_Float))
dvander@195
   157
            return false;
dvander@195
   158
        if (!declareSystemType(scope, "_", PrimitiveType_Int32))
dvander@195
   159
            return false;
dvander@195
   160
        if (!declareSystemType(scope, "int", PrimitiveType_Int32))
dvander@195
   161
            return false;
dvander@195
   162
        if (!declareSystemType(scope, "bool", PrimitiveType_Bool))
dvander@195
   163
            return false;
dvander@195
   164
        if (!declareSystemType(scope, "char", PrimitiveType_Char))
dvander@195
   165
            return false;
dvander@195
   166
dvander@195
   167
        Local<Type> voidType(zone_, zone_->types()->getVoid());
dvander@195
   168
        if (!declareSystemType(scope, "void", voidType))
dvander@195
   169
            return false;
dvander@195
   170
dvander@195
   171
        return true;
dvander@195
   172
    }
dvander@195
   173
dvander@195
   174
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@195
   175
        Scope *scope = env_->scope();
dvander@195
   176
        if (!scope || scope->kind() != Scope::GLOBAL) {
dvander@195
   177
            if ((scope = getOrCreateBlockScope()) == NULL)
dvander@195
   178
                return;
dvander@195
   179
        }
dvander@195
   180
dvander@195
   181
        if (scope->kind() == Scope::GLOBAL) {
dvander@195
   182
            // The symbol must be added now, since it could be an export.
dvander@195
   183
            VariableSymbol *sym = new (pool_) VariableSymbol(scope, node->name(), node->pos());
dvander@195
   184
            node->setSymbol(sym);
dvander@195
   185
dvander@195
   186
            if (!registerName(scope, sym))
dvander@195
   187
                return;
dvander@195
   188
        } else {
dvander@195
   189
            // We ensure the scope will exist at the name binding phase, but
dvander@195
   190
            // we don't actually register the variable symbol yet. Otherwise,
dvander@195
   191
            // when binding the initializer, we could encounter:
dvander@195
   192
            //    new x = x;
dvander@195
   193
            //
dvander@195
   194
            // And we don't necessarily want this to bind.
dvander@195
   195
        }
dvander@195
   196
dvander@212
   197
        if (node->initialization())
dvander@212
   198
            node->initialization()->accept(this);
dvander@195
   199
    }
dvander@195
   200
    void visitEnumStatement(EnumStatement *node) {
dvander@195
   201
        assert(false);
dvander@195
   202
    }
dvander@195
   203
    void visitFunctionStatement(FunctionStatement *node) {
dvander@195
   204
        // We create function types ahead of time, not for any particular
dvander@195
   205
        // reason. It makes things consistent with FunctionTypeStatement,
dvander@195
   206
        // which actually does produce a type.
dvander@195
   207
        Local<FunctionType> type(zone_, FunctionType::New(zone_, node->token()));
dvander@195
   208
        if (!type)
dvander@195
   209
            return;
dvander@195
   210
dvander@195
   211
        assert(env_->scope());
dvander@195
   212
dvander@195
   213
        // Function statements are always named, so add the name to the outer scope.
dvander@195
   214
        FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
dvander@195
   215
        if (!registerName(env_->scope(), sym))
dvander@195
   216
            return;
dvander@195
   217
dvander@195
   218
        if (node->token() == TOK_PUBLIC ||
dvander@195
   219
            node->token() == TOK_FORWARD ||
dvander@195
   220
            node->token() == TOK_NATIVE)
dvander@195
   221
        {
dvander@195
   222
            // We're in the global scope, for sure.
dvander@195
   223
            assert(env_->scope()->kind() == Scope::GLOBAL);
dvander@195
   224
            GlobalScope *globals = (GlobalScope *)env_->scope();
dvander@195
   225
            if (!globals->addPublic(sym))
dvander@195
   226
                return;
dvander@195
   227
        }
dvander@195
   228
dvander@195
   229
        node->setSymbol(sym);
dvander@195
   230
dvander@195
   231
        // Scope for the function's arguments.
dvander@195
   232
        SymbolEnv argEnv(&env_);
dvander@195
   233
        if (!registerArguments(node->signature()))
dvander@195
   234
            return;
dvander@195
   235
dvander@195
   236
        // Scope for function body.
dvander@195
   237
        SymbolEnv localEnv(&env_);
dvander@195
   238
        FunctionScope fun(&fun_);
dvander@195
   239
        if (node->body())
dvander@195
   240
            node->body()->accept(this);
dvander@195
   241
dvander@195
   242
        // Function statements have quirky semantics around their return
dvander@195
   243
        // type. For reasonable compatibility with SP1, we use the following
dvander@195
   244
        // heuristics for when no explicit type is declared.
dvander@195
   245
        if (!node->signature().returnType()) {
dvander@195
   246
            Local<Type> type(zone_);
dvander@195
   247
            if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
dvander@195
   248
                // If the function type is a native or forward, we always
dvander@195
   249
                // assume it returns an int32.
dvander@195
   250
                type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
   251
            } else if (fun.returns() != ValueReturn) {
dvander@195
   252
                // This function never returns a value, so mark it as
dvander@195
   253
                // returning void.
dvander@195
   254
                type = zone_->types()->getVoid();
dvander@195
   255
            }
dvander@195
   256
            // No need to NULL check here, we'll catch OOM later.
dvander@195
   257
            node->sym()->type()->setReturnType(type);
dvander@195
   258
        }
dvander@195
   259
dvander@195
   260
        node->setScopes(argEnv.scope(), localEnv.scope());
dvander@195
   261
    }
dvander@195
   262
    void visitStructureStatement(StructureStatement *node) {
dvander@195
   263
        assert(false);
dvander@195
   264
    }
dvander@195
   265
    void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
dvander@195
   266
        assert(false);
dvander@195
   267
    }
dvander@195
   268
dvander@195
   269
    void visitNameProxy(NameProxy *name) {
dvander@195
   270
    }
dvander@195
   271
    void visitAssignment(Assignment *node) {
dvander@195
   272
        node->lvalue()->accept(this);
dvander@195
   273
        node->expression()->accept(this);
dvander@195
   274
    }
dvander@195
   275
    void visitBinaryExpression(BinaryExpression *node) {
dvander@195
   276
        node->left()->accept(this);
dvander@195
   277
        node->right()->accept(this);
dvander@195
   278
    }
dvander@195
   279
    void visitReturnStatement(ReturnStatement *node) {
dvander@195
   280
        if (node->expression())
dvander@195
   281
            fun_->returns(ValueReturn);
dvander@195
   282
        else
dvander@195
   283
            fun_->returns(VoidReturn);
dvander@195
   284
    }
dvander@195
   285
    void visitForStatement(ForStatement *node) {
dvander@195
   286
        SymbolEnv env(&env_);
dvander@195
   287
dvander@195
   288
        if (node->initialization())
dvander@195
   289
            node->initialization()->accept(this);
dvander@195
   290
        if (node->condition())
dvander@195
   291
            node->condition()->accept(this);
dvander@195
   292
        if (node->update())
dvander@195
   293
            node->update()->accept(this);
dvander@195
   294
        node->body()->accept(this);
dvander@195
   295
dvander@195
   296
        node->setScope(env.scope());
dvander@195
   297
    }
dvander@195
   298
    void visitBlockStatement(BlockStatement *node) {
dvander@195
   299
        SymbolEnv env(&env_);
dvander@195
   300
dvander@195
   301
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@195
   302
            node->statements()->at(i)->accept(this);
dvander@195
   303
dvander@195
   304
        node->setScope(env.scope());
dvander@195
   305
    }
dvander@195
   306
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@195
   307
    }
dvander@195
   308
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@195
   309
        node->expression()->accept(this);
dvander@195
   310
    }
dvander@195
   311
    void visitCallExpression(CallExpression *node) {
dvander@195
   312
        node->callee()->accept(this);
dvander@195
   313
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@195
   314
            node->arguments()->at(i)->accept(this);
dvander@195
   315
    }
dvander@195
   316
    void visitIfStatement(IfStatement *node) {
dvander@195
   317
        node->ifTrue()->accept(this);
dvander@195
   318
        if (node->ifFalse())
dvander@195
   319
            node->ifFalse()->accept(this);
dvander@195
   320
    }
dvander@195
   321
    void visitIndexExpression(IndexExpression *node) {
dvander@212
   322
        node->left()->accept(this);
dvander@212
   323
        node->right()->accept(this);
dvander@195
   324
    }
dvander@195
   325
    void visitFloatLiteral(FloatLiteral *node) {
dvander@195
   326
    }
dvander@195
   327
    void visitWhileStatement(WhileStatement *node) {
dvander@195
   328
        node->condition()->accept(this);
dvander@195
   329
        node->body()->accept(this);
dvander@195
   330
    }
dvander@195
   331
    void visitBreakStatement(BreakStatement *node) {
dvander@195
   332
    }
dvander@195
   333
    void visitContinueStatement(ContinueStatement *node) {
dvander@195
   334
    }
dvander@195
   335
    void visitStringLiteral(StringLiteral *node) {
dvander@195
   336
    }
dvander@195
   337
    void visitIncDecExpression(IncDecExpression *node) {
dvander@217
   338
        node->expression()->accept(this);
dvander@195
   339
    }
dvander@195
   340
    void visitUnaryExpression(UnaryExpression *node) {
dvander@195
   341
        assert(false);
dvander@195
   342
    }
dvander@195
   343
    void visitTernaryExpression(TernaryExpression *node) {
dvander@195
   344
        assert(false);
dvander@195
   345
    }
dvander@195
   346
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@195
   347
    }
dvander@195
   348
    void visitFieldExpression(FieldExpression *node) {
dvander@195
   349
    }
dvander@195
   350
    void visitSwitchStatement(SwitchStatement *node) {
dvander@195
   351
        if (node->defaultCase())
dvander@195
   352
            node->defaultCase()->accept(this);
dvander@195
   353
dvander@195
   354
        for (size_t i = 0; i < node->cases()->length(); i++)
dvander@195
   355
            node->cases()->at(i)->statement()->accept(this);
dvander@195
   356
    }
dvander@195
   357
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@195
   358
    }
dvander@195
   359
    void visitImportStatement(ImportStatement *node) {
dvander@195
   360
    }
dvander@195
   361
dvander@195
   362
  private:
dvander@195
   363
    Scope *getOrCreateBlockScope() {
dvander@195
   364
        if (env_->scope()) {
dvander@195
   365
            assert(env_->scope()->kind() == Scope::BLOCK);
dvander@195
   366
            return env_->scope();
dvander@195
   367
        }
dvander@195
   368
        
dvander@195
   369
        LocalScope *scope = LocalScope::New(pool_);
dvander@195
   370
        if (!scope)
dvander@195
   371
            return NULL;
dvander@195
   372
dvander@195
   373
        env_->setScope(scope);
dvander@195
   374
        return scope;
dvander@195
   375
    }
dvander@195
   376
dvander@195
   377
    bool registerName(Scope *scope, Symbol *sym) {
dvander@195
   378
        if (!scope)
dvander@195
   379
            return false;
dvander@195
   380
dvander@195
   381
        if (Symbol *other = scope->localLookup(sym->name())) {
dvander@195
   382
            // Report, but allow errors to continue.
dvander@195
   383
            cc_.reportError(sym->pos(), Message_RedeclaredName,
dvander@195
   384
                            sym->name()->chars(),
dvander@195
   385
                            other->pos().line,
dvander@195
   386
                            other->pos().col);
dvander@195
   387
            return true;
dvander@195
   388
        }
dvander@195
   389
dvander@195
   390
        return scope->addSymbol(sym);
dvander@195
   391
    }
dvander@195
   392
dvander@195
   393
    bool registerArguments(const FunctionSignature &sig) {
dvander@195
   394
        if (!sig.parameters()->length())
dvander@195
   395
            return true;
dvander@195
   396
dvander@195
   397
        ArgumentScope *argScope = ArgumentScope::New(pool_);
dvander@195
   398
        if (!argScope)
dvander@195
   399
            return false;
dvander@195
   400
        env_->setScope(argScope);
dvander@195
   401
dvander@195
   402
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
dvander@195
   403
            Parameter *param = sig.parameters()->at(i);
dvander@195
   404
            VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
dvander@195
   405
            if (!registerName(env_->scope(), sym))
dvander@195
   406
                return false;
dvander@195
   407
            param->setSymbol(sym);
dvander@195
   408
        }
dvander@195
   409
dvander@195
   410
        return true;
dvander@195
   411
    }
dvander@195
   412
dvander@195
   413
  private:
dvander@195
   414
    Zone *zone_;
dvander@195
   415
    PoolAllocator &pool_;
dvander@195
   416
    CompileContext &cc_;
dvander@195
   417
    TranslationUnit *unit_;
dvander@195
   418
    SymbolEnv *env_;
dvander@195
   419
    FunctionScope *fun_;
dvander@195
   420
};
dvander@195
   421
dvander@195
   422
bool
dvander@195
   423
ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@195
   424
{
dvander@195
   425
    NamePopulator populator(zone, cc, unit);
dvander@195
   426
    return populator.analyze();
dvander@0
   427
}
dvander@0
   428
dvander@212
   429
static const int INFER_ARRAY_SIZE = 0;
dvander@212
   430
static const int EVAL_ARRAY_SIZE = -1;
dvander@212
   431
static const int DYNAMIC_ARRAY_SIZE = -2;
dvander@212
   432
dvander@195
   433
class NameBinder : public AstVisitor
dvander@0
   434
{
dvander@195
   435
  public:
dvander@195
   436
    class AutoLinkScope
dvander@195
   437
    {
dvander@195
   438
      public:
dvander@195
   439
        AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
dvander@195
   440
          : prevp_(prevp),
dvander@195
   441
            prev_(*prevp),
dvander@195
   442
            scope_(scope)
dvander@195
   443
        {
dvander@195
   444
            if (scope_) {
dvander@195
   445
                *prevp_ = this;
dvander@195
   446
                if (prev_)
dvander@195
   447
                    scope_->setParent(prev_->scope());
dvander@195
   448
            }
dvander@195
   449
        }
dvander@195
   450
        ~AutoLinkScope() {
dvander@195
   451
            if (scope_) {
dvander@195
   452
                assert(*prevp_ == this);
dvander@195
   453
                *prevp_ = prev_;
dvander@195
   454
            }
dvander@195
   455
        }
dvander@195
   456
        Scope *scope() const {
dvander@195
   457
            return scope_;
dvander@195
   458
        }
dvander@195
   459
dvander@195
   460
      private:
dvander@195
   461
        AutoLinkScope **prevp_;
dvander@195
   462
        AutoLinkScope *prev_;
dvander@195
   463
        Scope *scope_;
dvander@195
   464
    };
dvander@195
   465
dvander@195
   466
  public:
dvander@195
   467
    NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@195
   468
      : zone_(zone),
dvander@195
   469
        pool_(zone->pool()),
dvander@195
   470
        cc_(cc),
dvander@195
   471
        unit_(unit),
dvander@195
   472
        link_(NULL)
dvander@195
   473
    {
dvander@195
   474
    }
dvander@195
   475
dvander@195
   476
    bool bind() {
dvander@195
   477
        // Start with the import scope, and collect all imported names.
dvander@195
   478
        AutoLinkScope importScope(&link_, unit_->importScope());
dvander@195
   479
dvander@195
   480
        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
dvander@195
   481
            unit_->tree()->imports()->at(i)->accept(this);
dvander@195
   482
dvander@195
   483
        // Next, enter the global scope and walk all statements.
dvander@195
   484
        AutoLinkScope globalScope(&link_, unit_->globalScope());
dvander@195
   485
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
dvander@195
   486
            Statement *stmt = unit_->tree()->statements()->at(i);
dvander@195
   487
            stmt->accept(this);
dvander@195
   488
        }
dvander@195
   489
dvander@195
   490
        return true;
dvander@195
   491
    }
dvander@195
   492
dvander@195
   493
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@195
   494
        // Bind the initializer before registering the declaration, so that we
dvander@195
   495
        // can error on bogus initializers (new x = x).
dvander@212
   496
        if (node->initialization())
dvander@212
   497
            node->initialization()->accept(this);
dvander@195
   498
dvander@195
   499
        Local<Type> type(zone_, bindType(node->type()));
dvander@195
   500
        if (!type)
dvander@195
   501
            return;
dvander@195
   502
dvander@212
   503
        if (node->dims() || type->isArray()) {
dvander@212
   504
            int dims[MAX_ARRAY_DEPTH];
dvander@212
   505
            int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
dvander@212
   506
            if (levels < 0)
dvander@212
   507
                return;
dvander@212
   508
dvander@212
   509
            // Do some extra inference based on the initializer, if present.
dvander@212
   510
            Expression *init = node->initialization();
dvander@212
   511
            if (init &&
dvander@212
   512
                init->isArrayLiteral() &&
dvander@212
   513
                init->toArrayLiteral()->isFixed())
dvander@212
   514
            {
dvander@212
   515
                Local<Type> contained(zone_, type->isArray()
dvander@212
   516
                                             ? ArrayType::cast(type)->contained()
dvander@212
   517
                                             : type);
dvander@212
   518
                if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
dvander@212
   519
                    return;
dvander@212
   520
            }
dvander@212
   521
dvander@212
   522
            // If we got extra dimensions, we need to build a new type.
dvander@212
   523
            if (node->dims()) {
dvander@212
   524
                if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL)
dvander@212
   525
                    return;
dvander@212
   526
            }
dvander@209
   527
        }
dvander@209
   528
dvander@195
   529
        // If the node already has a symbol (meaning it was a global), then
dvander@195
   530
        // we don't have to do anything more.
dvander@195
   531
        if (node->sym()) {
dvander@195
   532
            assert(node->sym()->scope()->kind() == Scope::GLOBAL);
dvander@209
   533
            node->sym()->setType(type);
dvander@195
   534
            return;
dvander@195
   535
        }
dvander@195
   536
dvander@195
   537
        VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
dvander@195
   538
        node->setSymbol(sym);
dvander@195
   539
       
dvander@195
   540
        if (Symbol *other = link_->scope()->localLookup(sym->name())) {
dvander@195
   541
            // Report, but allow errors to continue.
dvander@195
   542
            cc_.reportError(sym->pos(), Message_RedeclaredName,
dvander@195
   543
                            sym->name()->chars(),
dvander@195
   544
                            other->pos().line,
dvander@195
   545
                            other->pos().col);
dvander@195
   546
            return;
dvander@195
   547
        }
dvander@195
   548
        
dvander@195
   549
        if (link_->scope()->addSymbol(sym))
dvander@195
   550
            return;
dvander@195
   551
    }
dvander@195
   552
    void visitEnumStatement(EnumStatement *node) {
dvander@195
   553
        assert(false);
dvander@195
   554
    }
dvander@195
   555
    void visitFunctionStatement(FunctionStatement *node) {
dvander@195
   556
        AutoLinkScope argScope(&link_, node->argScope());
dvander@195
   557
        AutoLinkScope varScope(&link_, node->varScope());
dvander@195
   558
dvander@195
   559
        Local<FunctionType> type(zone_, node->sym()->type());
dvander@195
   560
        if (!fillFunctionType(type, node->signature()))
dvander@195
   561
            return;
dvander@195
   562
dvander@195
   563
        if (node->body())
dvander@195
   564
            node->body()->accept(this);
dvander@195
   565
    }
dvander@195
   566
    void visitStructureStatement(StructureStatement *node) {
dvander@195
   567
        assert(false);
dvander@195
   568
    }
dvander@195
   569
    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
dvander@195
   570
        assert(false);
dvander@195
   571
    }
dvander@195
   572
dvander@195
   573
    void visitNameProxy(NameProxy *proxy) {
dvander@195
   574
        Scope *scope = link_->scope();
dvander@195
   575
        Symbol *sym = scope->lookup(proxy->name());
dvander@195
   576
        if (!sym)
dvander@195
   577
            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
dvander@195
   578
        proxy->bind(sym);
dvander@195
   579
    }
dvander@195
   580
    void visitAssignment(Assignment *node) {
dvander@195
   581
        node->lvalue()->accept(this);
dvander@195
   582
        node->expression()->accept(this);
dvander@195
   583
    }
dvander@195
   584
    void visitBinaryExpression(BinaryExpression *node) {
dvander@195
   585
        node->left()->accept(this);
dvander@195
   586
        node->right()->accept(this);
dvander@195
   587
    }
dvander@195
   588
    void visitReturnStatement(ReturnStatement *node) {
dvander@195
   589
        node->expression()->accept(this);
dvander@195
   590
    }
dvander@195
   591
    void visitForStatement(ForStatement *node) {
dvander@195
   592
        AutoLinkScope scope(&link_, node->scope());
dvander@0
   593
dvander@195
   594
        if (node->initialization())
dvander@195
   595
            node->initialization()->accept(this);
dvander@195
   596
        if (node->condition())
dvander@195
   597
            node->condition()->accept(this);
dvander@195
   598
        if (node->update())
dvander@195
   599
            node->update()->accept(this);
dvander@195
   600
        node->body()->accept(this);
dvander@195
   601
    }
dvander@195
   602
    void visitBlockStatement(BlockStatement *node) {
dvander@195
   603
        AutoLinkScope scope(&link_, node->scope());
dvander@195
   604
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@195
   605
            node->statements()->at(i)->accept(this);
dvander@195
   606
    }
dvander@195
   607
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@195
   608
    }
dvander@195
   609
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@195
   610
        node->expression()->accept(this);
dvander@195
   611
    }
dvander@195
   612
    void visitCallExpression(CallExpression *node) {
dvander@195
   613
        node->callee()->accept(this);
dvander@195
   614
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@195
   615
            node->arguments()->at(i)->accept(this);
dvander@195
   616
    }
dvander@195
   617
    void visitIfStatement(IfStatement *node) {
dvander@195
   618
        node->condition()->accept(this);
dvander@195
   619
        node->ifTrue()->accept(this);
dvander@208
   620
        if (node->ifFalse())
dvander@208
   621
            node->ifFalse()->accept(this);
dvander@195
   622
    }
dvander@195
   623
    void visitIndexExpression(IndexExpression *node) {
dvander@195
   624
        node->left()->accept(this);
dvander@195
   625
        node->right()->accept(this);
dvander@195
   626
    }
dvander@195
   627
    void visitFloatLiteral(FloatLiteral *node) {
dvander@195
   628
    }
dvander@195
   629
    void visitWhileStatement(WhileStatement *node) {
dvander@195
   630
        node->condition()->accept(this);
dvander@195
   631
        node->body()->accept(this);
dvander@195
   632
    }
dvander@195
   633
    void visitBreakStatement(BreakStatement *node) {
dvander@195
   634
    }
dvander@195
   635
    void visitContinueStatement(ContinueStatement *node) {
dvander@195
   636
    }
dvander@195
   637
    void visitStringLiteral(StringLiteral *node) {
dvander@195
   638
    }
dvander@195
   639
    void visitIncDecExpression(IncDecExpression *node) {
dvander@195
   640
        node->expression()->accept(this);
dvander@195
   641
    }
dvander@195
   642
    void visitUnaryExpression(UnaryExpression *node) {
dvander@195
   643
        if (node->tag())
dvander@195
   644
            node->tag()->accept(this);
dvander@195
   645
        node->expression()->accept(this);
dvander@195
   646
    }
dvander@195
   647
    void visitTernaryExpression(TernaryExpression *node) {
dvander@195
   648
        node->condition()->accept(this);
dvander@195
   649
        node->left()->accept(this);
dvander@195
   650
        node->right()->accept(this);
dvander@195
   651
    }
dvander@195
   652
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@195
   653
    }
dvander@195
   654
    void visitFieldExpression(FieldExpression *node) {
dvander@195
   655
        node->left()->accept(this);
dvander@195
   656
    }
dvander@195
   657
    void visitSwitchStatement(SwitchStatement *node) {
dvander@195
   658
        node->expression()->accept(this);
dvander@195
   659
        node->defaultCase()->accept(this);
dvander@195
   660
        for (size_t i = 0; i < node->cases()->length(); i++) {
dvander@195
   661
            // We don't test case expressions because they are literals.
dvander@195
   662
            Case *c = node->cases()->at(i);
dvander@195
   663
            c->statement()->accept(this);
dvander@195
   664
        }
dvander@195
   665
    }
dvander@195
   666
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@195
   667
        for (size_t i = 0; i < node->expressions()->length(); i++)
dvander@195
   668
            node->expressions()->at(i)->accept(this);
dvander@195
   669
    }
dvander@195
   670
    void visitImportStatement(ImportStatement *node) {
dvander@195
   671
        if (node->suffix() == TOK_STAR) {
dvander@195
   672
            // Import every name.
dvander@195
   673
            assert(false);
dvander@195
   674
        } else {
dvander@195
   675
            GlobalScope *other = node->source()->globalScope();
dvander@195
   676
            Symbol *sym = other->findPublic(node->name());
dvander@195
   677
            if (!sym) {
dvander@195
   678
                cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
dvander@195
   679
                return;
dvander@195
   680
            }
dvander@195
   681
            link_->scope()->addSymbol(sym);
dvander@195
   682
        }
dvander@195
   683
    }
dvander@195
   684
dvander@195
   685
  private:
dvander@212
   686
    int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
dvander@212
   687
        unsigned level = 0;
dvander@212
   688
        Local<Type> type(zone_, typeArg);
dvander@212
   689
        while (type->isArray()) {
dvander@212
   690
            ArrayType *atype = ArrayType::cast(type);
dvander@212
   691
            dims[level] = atype->isFixedLength()
dvander@212
   692
                          ? atype->fixedLength()
dvander@212
   693
                          : DYNAMIC_ARRAY_SIZE;
dvander@212
   694
            type = atype->contained();
dvander@212
   695
            level++;
dvander@212
   696
        }
dvander@212
   697
dvander@212
   698
        if (!exprs)
dvander@212
   699
            return level;
dvander@212
   700
dvander@212
   701
        if (level + exprs->length() > MAX_ARRAY_DEPTH) {
dvander@212
   702
            cc_.reportError(pos, Message_MaximumArrayDepth);
dvander@212
   703
            return -1;
dvander@212
   704
        }
dvander@212
   705
dvander@212
   706
        bool hadEmptySize = false;
dvander@212
   707
        for (size_t i = 0; i < exprs->length(); i++) {
dvander@212
   708
            Expression *expr = exprs->at(i);
dvander@212
   709
            if (!expr) {
dvander@212
   710
                dims[i] = INFER_ARRAY_SIZE;
dvander@212
   711
                hadEmptySize = true;
dvander@212
   712
                continue;
dvander@212
   713
            }
dvander@212
   714
dvander@212
   715
            BoxedPrimitive box;
dvander@212
   716
            if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@212
   717
                int size = box.toInt();
dvander@212
   718
                if (size <= 0) {
dvander@212
   719
                    cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@212
   720
                    return false;
dvander@212
   721
                }
dvander@212
   722
dvander@212
   723
                dims[i] = size;
dvander@212
   724
                continue;
dvander@212
   725
            }
dvander@212
   726
dvander@212
   727
            if (hadEmptySize) {
dvander@212
   728
                cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
dvander@212
   729
                return false;
dvander@212
   730
            }
dvander@212
   731
dvander@212
   732
            dims[i] = EVAL_ARRAY_SIZE;
dvander@212
   733
        }
dvander@212
   734
dvander@212
   735
        return level + exprs->length();
dvander@212
   736
    }
dvander@212
   737
dvander@212
   738
    // This function computes missing dimension sizes based on a literal
dvander@212
   739
    // initializer. We don't really handle any size rules here; we just
dvander@212
   740
    // do a really dumb inference.
dvander@212
   741
    bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
dvander@212
   742
        for (int i = 0; i < levels; i++) {
dvander@212
   743
            if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
dvander@212
   744
                // The following are invalid:
dvander@212
   745
                //   new x[<expr>] = {...}
dvander@212
   746
                //   new Type:x = {...}  // where Type is a non-fixed array type
dvander@212
   747
                cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
dvander@212
   748
                return false;
dvander@212
   749
            }
dvander@212
   750
dvander@212
   751
            if (dims[i] == INFER_ARRAY_SIZE) {
dvander@212
   752
                // Character arrays are always dynamic when inferred from string literals.
dvander@212
   753
                if (i == levels - 1 && contained->isChar())
dvander@212
   754
                    dims[i] = DYNAMIC_ARRAY_SIZE;
dvander@212
   755
                else
dvander@212
   756
                    dims[i] = lit->expressions()->length();
dvander@212
   757
            }
dvander@212
   758
dvander@212
   759
            if (i != levels - 1) {
dvander@212
   760
                // Fixed array literals are guaranteed to have at least one expression.
dvander@212
   761
                Expression *next = lit->expressions()->at(0);
dvander@212
   762
                if (!next->isArrayLiteral()) {
dvander@212
   763
                    // Whelp... this array is just malformed. Not the best error message
dvander@212
   764
                    // but whatever.
dvander@212
   765
                    cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
dvander@212
   766
                    return false;
dvander@212
   767
                }
dvander@212
   768
                lit = next->toArrayLiteral();
dvander@212
   769
            }
dvander@212
   770
        }
dvander@212
   771
dvander@212
   772
        return true;
dvander@212
   773
    }
dvander@212
   774
dvander@212
   775
    ArrayType *buildArrayType(Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
dvander@212
   776
        Local<Type> type(zone_, contained);
dvander@212
   777
        for (size_t i = postlevels - 1; i < postlevels; i--) {
dvander@212
   778
            int size = dims[i] > 0
dvander@212
   779
                       ? dims[i]
dvander@212
   780
                       : ArrayType::DYNAMIC_ARRAY_SIZE;
dvander@212
   781
            
dvander@212
   782
            type = zone_->types()->newArray(contained, size);
dvander@212
   783
            if (!type)
dvander@212
   784
                return NULL;
dvander@212
   785
        }
dvander@212
   786
        return ArrayType::cast(type);
dvander@212
   787
    }
dvander@212
   788
dvander@195
   789
    bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
dvander@195
   790
        Local<Type> type(zone_);
dvander@195
   791
        if (!fun->returnType()) {
dvander@195
   792
            if ((type = bindType(sig.returnType())) == NULL)
dvander@195
   793
                return false;
dvander@195
   794
            fun->setReturnType(type);
dvander@195
   795
        }
dvander@195
   796
dvander@195
   797
        Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
dvander@195
   798
        if (!params)
dvander@195
   799
            return false;
dvander@195
   800
dvander@195
   801
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
dvander@195
   802
            Parameter *param = sig.parameters()->at(i);
dvander@195
   803
            if ((type = bindType(param->type())) == NULL)
dvander@195
   804
                return false;
dvander@220
   805
dvander@220
   806
            if (type->isArray() || param->dims()) {
dvander@220
   807
                int dims[MAX_ARRAY_DEPTH];
dvander@220
   808
                int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
dvander@220
   809
                if (levels < 0)
dvander@220
   810
                    return false;
dvander@220
   811
dvander@220
   812
                // If we got extra dimensions, we need to build a new type.
dvander@220
   813
                // Unlike variables, we do not infer anything about array
dvander@220
   814
                // sizes from its default initializer.
dvander@220
   815
                if (param->dims()) {
dvander@220
   816
                    if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL)
dvander@220
   817
                        return false;
dvander@220
   818
                }
dvander@220
   819
            }
dvander@220
   820
dvander@195
   821
            params->set(zone_, i, type);
dvander@220
   822
            param->sym()->setType(type);
dvander@195
   823
        }
dvander@195
   824
dvander@195
   825
        fun->setParameterTypes(params);
dvander@195
   826
dvander@195
   827
        return true;
dvander@195
   828
    }
dvander@195
   829
dvander@195
   830
    Type *bindType(Expression *expr) {
dvander@195
   831
        if (!expr) {
dvander@195
   832
            // If no type was declared, we return int32.
dvander@195
   833
            return zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
   834
        }
dvander@195
   835
        
dvander@195
   836
        expr->accept(this);
dvander@195
   837
dvander@195
   838
        NameProxy *proxy = expr->asNameProxy();
dvander@195
   839
        assert(proxy);
dvander@195
   840
dvander@195
   841
        Symbol *sym = proxy->sym();
dvander@195
   842
        if (!sym)
dvander@195
   843
            return NULL;
dvander@195
   844
dvander@195
   845
        if (!sym->isType()) {
dvander@195
   846
            cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
dvander@195
   847
            return NULL;
dvander@195
   848
        }
dvander@195
   849
dvander@195
   850
        return sym->type();
dvander@195
   851
    }
dvander@195
   852
dvander@195
   853
  private:
dvander@195
   854
    Zone *zone_;
dvander@195
   855
    PoolAllocator &pool_;
dvander@195
   856
    CompileContext &cc_;
dvander@195
   857
    TranslationUnit *unit_;
dvander@195
   858
    AutoLinkScope *link_;
dvander@195
   859
};
dvander@85
   860
dvander@85
   861
bool
dvander@195
   862
ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@85
   863
{
dvander@195
   864
    NameBinder binder(zone, cc, unit);
dvander@195
   865
    return binder.bind();
dvander@85
   866
}