src/compiler/NameBinding.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jan 27 17:34:30 2013 -0800 (2013-01-27)
changeset 261 219b49bf4a03
parent 260 05de34f712fe
child 263 ba85a47ee414
permissions -rw-r--r--
Add support for importing enum types and enum values (as constexprs).
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@250
   114
    void analyze() {
dvander@195
   115
        ImportScope *importScope = ImportScope::New(pool_);
dvander@195
   116
        if (!importScope)
dvander@250
   117
            return;
dvander@195
   118
dvander@195
   119
        // At the import level, we declare system types.
dvander@195
   120
        if (!declareSystemTypes(importScope))
dvander@250
   121
            return;
dvander@195
   122
dvander@195
   123
        GlobalScope *globalScope = GlobalScope::New(pool_, importScope);
dvander@195
   124
        if (!globalScope)
dvander@250
   125
            return;
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@250
   137
        return;
dvander@195
   138
    }
dvander@195
   139
dvander@261
   140
    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> effective) {
dvander@195
   141
        Local<String> tag(zone_, zone_->makeSymbol(name));
dvander@195
   142
        if (!tag)
dvander@195
   143
            return false;
dvander@195
   144
dvander@261
   145
        Local<Type> type(zone_, zone_->types()->getType());
dvander@261
   146
dvander@261
   147
        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type, effective);
dvander@195
   148
        return scope->addSymbol(sym);
dvander@195
   149
    }
dvander@195
   150
dvander@195
   151
    bool declareSystemType(ImportScope *scope, const char *name, PrimitiveType prim) {
dvander@195
   152
        Local<Type> primitive(zone_, zone_->types()->getPrimitive(prim));
dvander@195
   153
        assert(primitive);
dvander@195
   154
        return declareSystemType(scope, name, primitive);
dvander@195
   155
    }
dvander@195
   156
dvander@195
   157
    bool declareSystemTypes(ImportScope *scope) {
dvander@195
   158
        if (!declareSystemType(scope, "float", PrimitiveType_Float))
dvander@195
   159
            return false;
dvander@195
   160
        if (!declareSystemType(scope, "_", PrimitiveType_Int32))
dvander@195
   161
            return false;
dvander@195
   162
        if (!declareSystemType(scope, "int", PrimitiveType_Int32))
dvander@195
   163
            return false;
dvander@195
   164
        if (!declareSystemType(scope, "bool", PrimitiveType_Bool))
dvander@195
   165
            return false;
dvander@195
   166
        if (!declareSystemType(scope, "char", PrimitiveType_Char))
dvander@195
   167
            return false;
dvander@195
   168
dvander@195
   169
        Local<Type> voidType(zone_, zone_->types()->getVoid());
dvander@195
   170
        if (!declareSystemType(scope, "void", voidType))
dvander@195
   171
            return false;
dvander@195
   172
dvander@195
   173
        return true;
dvander@195
   174
    }
dvander@195
   175
dvander@195
   176
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@195
   177
        Scope *scope = env_->scope();
dvander@195
   178
        if (!scope || scope->kind() != Scope::GLOBAL) {
dvander@195
   179
            if ((scope = getOrCreateBlockScope()) == NULL)
dvander@195
   180
                return;
dvander@195
   181
        }
dvander@195
   182
dvander@195
   183
        if (scope->kind() == Scope::GLOBAL) {
dvander@195
   184
            // The symbol must be added now, since it could be an export.
dvander@195
   185
            VariableSymbol *sym = new (pool_) VariableSymbol(scope, node->name(), node->pos());
dvander@195
   186
            node->setSymbol(sym);
dvander@195
   187
dvander@195
   188
            if (!registerName(scope, sym))
dvander@195
   189
                return;
dvander@195
   190
        } else {
dvander@195
   191
            // We ensure the scope will exist at the name binding phase, but
dvander@195
   192
            // we don't actually register the variable symbol yet. Otherwise,
dvander@195
   193
            // when binding the initializer, we could encounter:
dvander@195
   194
            //    new x = x;
dvander@195
   195
            //
dvander@195
   196
            // And we don't necessarily want this to bind.
dvander@195
   197
        }
dvander@195
   198
dvander@212
   199
        if (node->initialization())
dvander@212
   200
            node->initialization()->accept(this);
dvander@195
   201
    }
dvander@256
   202
dvander@195
   203
    void visitEnumStatement(EnumStatement *node) {
dvander@233
   204
        Local<String> name(zone_, node->name());
dvander@233
   205
        Local<Type> type(zone_);
dvander@233
   206
        if (name)
dvander@233
   207
            type = zone_->types()->newEnum(name);
dvander@233
   208
        else
dvander@233
   209
            type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@233
   210
dvander@233
   211
        if (!type)
dvander@233
   212
            return;
dvander@233
   213
dvander@233
   214
        Scope *scope = getGlobalOrCreateBlockScope();
dvander@233
   215
        if (!scope)
dvander@233
   216
            return;
dvander@233
   217
dvander@233
   218
        if (name) {
dvander@261
   219
            Local<Type> symType(zone_, zone_->types()->getType());
dvander@261
   220
            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, symType, type);
dvander@233
   221
            if (!registerName(scope, sym))
dvander@233
   222
                return;
dvander@258
   223
dvander@258
   224
            if (scope->kind() == Scope::GLOBAL) {
dvander@258
   225
                if (!unit_->globalScope()->exported()->append(sym))
dvander@258
   226
                    return;
dvander@258
   227
            }
dvander@233
   228
        }
dvander@233
   229
dvander@261
   230
        // We want each field of the expression to qualify as a constant expression.
dvander@261
   231
        if ((type = zone_->types()->qualify(type, TypeQual_ConstExpr)) == NULL)
dvander@261
   232
            return;
dvander@261
   233
        
dvander@233
   234
        int value = 0;
dvander@233
   235
        for (size_t i = 0; i < node->entries()->length(); i++) {
dvander@233
   236
            EnumStatement::Entry &entry = node->entries()->at(i);
dvander@233
   237
            BoxedPrimitive box = BoxedPrimitive::Int(value);
dvander@233
   238
            if (entry.expr) {
dvander@233
   239
                if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
dvander@233
   240
                    cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
dvander@233
   241
                    return;
dvander@233
   242
                }
dvander@233
   243
dvander@233
   244
                assert(box.type() == PrimitiveType_Int32);
dvander@233
   245
                value = box.toInt();
dvander@233
   246
            }
dvander@261
   247
         
dvander@233
   248
            ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
dvander@233
   249
            if (!registerName(scope, sym))
dvander@233
   250
                return;
dvander@258
   251
            if (scope->kind() == Scope::GLOBAL) {
dvander@258
   252
                if (!unit_->globalScope()->exported()->append(sym))
dvander@258
   253
                    return;
dvander@258
   254
            }
dvander@233
   255
dvander@261
   256
            entry.sym = sym;
dvander@233
   257
            value++;
dvander@233
   258
        }
dvander@195
   259
    }
dvander@256
   260
dvander@195
   261
    void visitFunctionStatement(FunctionStatement *node) {
dvander@195
   262
        // We create function types ahead of time, not for any particular
dvander@195
   263
        // reason. It makes things consistent with FunctionTypeStatement,
dvander@195
   264
        // which actually does produce a type.
dvander@233
   265
        Local<FunctionType> type(zone_, FunctionType::New(zone_, node->name(), node->token()));
dvander@195
   266
        if (!type)
dvander@195
   267
            return;
dvander@195
   268
dvander@195
   269
        assert(env_->scope());
dvander@195
   270
dvander@195
   271
        // Function statements are always named, so add the name to the outer scope.
dvander@195
   272
        FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
dvander@195
   273
        if (!registerName(env_->scope(), sym))
dvander@195
   274
            return;
dvander@195
   275
dvander@195
   276
        if (node->token() == TOK_PUBLIC ||
dvander@195
   277
            node->token() == TOK_FORWARD ||
dvander@195
   278
            node->token() == TOK_NATIVE)
dvander@195
   279
        {
dvander@195
   280
            // We're in the global scope, for sure.
dvander@195
   281
            assert(env_->scope()->kind() == Scope::GLOBAL);
dvander@258
   282
dvander@258
   283
            if (!unit_->globalScope()->exported()->append(sym))
dvander@258
   284
                return;
dvander@195
   285
        }
dvander@195
   286
dvander@195
   287
        node->setSymbol(sym);
dvander@195
   288
dvander@195
   289
        // Scope for the function's arguments.
dvander@195
   290
        SymbolEnv argEnv(&env_);
dvander@195
   291
        if (!registerArguments(node->signature()))
dvander@195
   292
            return;
dvander@195
   293
dvander@195
   294
        // Scope for function body.
dvander@195
   295
        SymbolEnv localEnv(&env_);
dvander@195
   296
        FunctionScope fun(&fun_);
dvander@195
   297
        if (node->body())
dvander@195
   298
            node->body()->accept(this);
dvander@195
   299
dvander@195
   300
        // Function statements have quirky semantics around their return
dvander@195
   301
        // type. For reasonable compatibility with SP1, we use the following
dvander@195
   302
        // heuristics for when no explicit type is declared.
dvander@195
   303
        if (!node->signature().returnType()) {
dvander@195
   304
            Local<Type> type(zone_);
dvander@195
   305
            if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
dvander@195
   306
                // If the function type is a native or forward, we always
dvander@195
   307
                // assume it returns an int32.
dvander@195
   308
                type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@195
   309
            } else if (fun.returns() != ValueReturn) {
dvander@195
   310
                // This function never returns a value, so mark it as
dvander@195
   311
                // returning void.
dvander@195
   312
                type = zone_->types()->getVoid();
dvander@195
   313
            }
dvander@195
   314
            // No need to NULL check here, we'll catch OOM later.
dvander@195
   315
            node->sym()->type()->setReturnType(type);
dvander@195
   316
        }
dvander@195
   317
dvander@195
   318
        node->setScopes(argEnv.scope(), localEnv.scope());
dvander@195
   319
    }
dvander@256
   320
dvander@195
   321
    void visitStructureStatement(StructureStatement *node) {
dvander@195
   322
        assert(false);
dvander@195
   323
    }
dvander@256
   324
dvander@195
   325
    void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
dvander@195
   326
        assert(false);
dvander@195
   327
    }
dvander@195
   328
dvander@195
   329
    void visitNameProxy(NameProxy *name) {
dvander@195
   330
    }
dvander@195
   331
    void visitAssignment(Assignment *node) {
dvander@195
   332
        node->lvalue()->accept(this);
dvander@195
   333
        node->expression()->accept(this);
dvander@195
   334
    }
dvander@195
   335
    void visitBinaryExpression(BinaryExpression *node) {
dvander@195
   336
        node->left()->accept(this);
dvander@195
   337
        node->right()->accept(this);
dvander@195
   338
    }
dvander@195
   339
    void visitReturnStatement(ReturnStatement *node) {
dvander@195
   340
        if (node->expression())
dvander@195
   341
            fun_->returns(ValueReturn);
dvander@195
   342
        else
dvander@195
   343
            fun_->returns(VoidReturn);
dvander@195
   344
    }
dvander@195
   345
    void visitForStatement(ForStatement *node) {
dvander@195
   346
        SymbolEnv env(&env_);
dvander@195
   347
dvander@195
   348
        if (node->initialization())
dvander@195
   349
            node->initialization()->accept(this);
dvander@195
   350
        if (node->condition())
dvander@195
   351
            node->condition()->accept(this);
dvander@195
   352
        if (node->update())
dvander@195
   353
            node->update()->accept(this);
dvander@195
   354
        node->body()->accept(this);
dvander@195
   355
dvander@195
   356
        node->setScope(env.scope());
dvander@195
   357
    }
dvander@195
   358
    void visitBlockStatement(BlockStatement *node) {
dvander@247
   359
        if (node->type() == TOK_NEW) {
dvander@247
   360
            // Don't create a symbol environment for this block, since it
dvander@247
   361
            // was created solely to house multiple variable decls.
dvander@247
   362
            for (size_t i = 0; i < node->statements()->length(); i++)
dvander@247
   363
                node->statements()->at(i)->accept(this);
dvander@247
   364
        } else {
dvander@247
   365
            assert(node->type() == TOK_LBRACE);
dvander@247
   366
dvander@247
   367
            SymbolEnv env(&env_);
dvander@195
   368
dvander@247
   369
            for (size_t i = 0; i < node->statements()->length(); i++)
dvander@247
   370
                node->statements()->at(i)->accept(this);
dvander@247
   371
        
dvander@247
   372
            if (node->type() == TOK_NEW) {
dvander@247
   373
                assert(!env.scope());
dvander@247
   374
                return;
dvander@247
   375
            }
dvander@195
   376
dvander@247
   377
            node->setScope(env.scope());
dvander@247
   378
        }
dvander@195
   379
    }
dvander@195
   380
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@195
   381
    }
dvander@195
   382
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@195
   383
        node->expression()->accept(this);
dvander@195
   384
    }
dvander@195
   385
    void visitCallExpression(CallExpression *node) {
dvander@195
   386
        node->callee()->accept(this);
dvander@195
   387
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@195
   388
            node->arguments()->at(i)->accept(this);
dvander@195
   389
    }
dvander@195
   390
    void visitIfStatement(IfStatement *node) {
dvander@195
   391
        node->ifTrue()->accept(this);
dvander@195
   392
        if (node->ifFalse())
dvander@195
   393
            node->ifFalse()->accept(this);
dvander@195
   394
    }
dvander@195
   395
    void visitIndexExpression(IndexExpression *node) {
dvander@212
   396
        node->left()->accept(this);
dvander@212
   397
        node->right()->accept(this);
dvander@195
   398
    }
dvander@195
   399
    void visitFloatLiteral(FloatLiteral *node) {
dvander@195
   400
    }
dvander@195
   401
    void visitWhileStatement(WhileStatement *node) {
dvander@195
   402
        node->condition()->accept(this);
dvander@195
   403
        node->body()->accept(this);
dvander@195
   404
    }
dvander@195
   405
    void visitBreakStatement(BreakStatement *node) {
dvander@195
   406
    }
dvander@195
   407
    void visitContinueStatement(ContinueStatement *node) {
dvander@195
   408
    }
dvander@195
   409
    void visitStringLiteral(StringLiteral *node) {
dvander@195
   410
    }
dvander@195
   411
    void visitIncDecExpression(IncDecExpression *node) {
dvander@217
   412
        node->expression()->accept(this);
dvander@195
   413
    }
dvander@195
   414
    void visitUnaryExpression(UnaryExpression *node) {
dvander@246
   415
        node->expression()->accept(this);
dvander@195
   416
    }
dvander@195
   417
    void visitTernaryExpression(TernaryExpression *node) {
dvander@195
   418
        assert(false);
dvander@195
   419
    }
dvander@195
   420
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@195
   421
    }
dvander@195
   422
    void visitFieldExpression(FieldExpression *node) {
dvander@195
   423
    }
dvander@195
   424
    void visitSwitchStatement(SwitchStatement *node) {
dvander@195
   425
        if (node->defaultCase())
dvander@195
   426
            node->defaultCase()->accept(this);
dvander@195
   427
dvander@195
   428
        for (size_t i = 0; i < node->cases()->length(); i++)
dvander@195
   429
            node->cases()->at(i)->statement()->accept(this);
dvander@195
   430
    }
dvander@195
   431
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@195
   432
    }
dvander@195
   433
    void visitImportStatement(ImportStatement *node) {
dvander@195
   434
    }
dvander@195
   435
dvander@195
   436
  private:
dvander@233
   437
    Scope *getGlobalOrCreateBlockScope() {
dvander@233
   438
        if (env_->scope()) {
dvander@233
   439
            assert(env_->scope()->kind() == Scope::BLOCK ||
dvander@233
   440
                   env_->scope()->kind() == Scope::GLOBAL);
dvander@233
   441
            return env_->scope();
dvander@233
   442
        }
dvander@233
   443
        return getOrCreateBlockScope();
dvander@233
   444
    }
dvander@195
   445
    Scope *getOrCreateBlockScope() {
dvander@195
   446
        if (env_->scope()) {
dvander@195
   447
            assert(env_->scope()->kind() == Scope::BLOCK);
dvander@195
   448
            return env_->scope();
dvander@195
   449
        }
dvander@195
   450
        
dvander@195
   451
        LocalScope *scope = LocalScope::New(pool_);
dvander@195
   452
        if (!scope)
dvander@195
   453
            return NULL;
dvander@195
   454
dvander@195
   455
        env_->setScope(scope);
dvander@195
   456
        return scope;
dvander@195
   457
    }
dvander@195
   458
dvander@195
   459
    bool registerName(Scope *scope, Symbol *sym) {
dvander@195
   460
        if (!scope)
dvander@195
   461
            return false;
dvander@195
   462
dvander@195
   463
        if (Symbol *other = scope->localLookup(sym->name())) {
dvander@195
   464
            // Report, but allow errors to continue.
dvander@195
   465
            cc_.reportError(sym->pos(), Message_RedeclaredName,
dvander@195
   466
                            sym->name()->chars(),
dvander@195
   467
                            other->pos().line,
dvander@195
   468
                            other->pos().col);
dvander@195
   469
            return true;
dvander@195
   470
        }
dvander@195
   471
dvander@195
   472
        return scope->addSymbol(sym);
dvander@195
   473
    }
dvander@195
   474
dvander@195
   475
    bool registerArguments(const FunctionSignature &sig) {
dvander@195
   476
        if (!sig.parameters()->length())
dvander@195
   477
            return true;
dvander@195
   478
dvander@195
   479
        ArgumentScope *argScope = ArgumentScope::New(pool_);
dvander@195
   480
        if (!argScope)
dvander@195
   481
            return false;
dvander@195
   482
        env_->setScope(argScope);
dvander@195
   483
dvander@195
   484
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
dvander@195
   485
            Parameter *param = sig.parameters()->at(i);
dvander@195
   486
            VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
dvander@195
   487
            if (!registerName(env_->scope(), sym))
dvander@195
   488
                return false;
dvander@195
   489
            param->setSymbol(sym);
dvander@195
   490
        }
dvander@195
   491
dvander@195
   492
        return true;
dvander@195
   493
    }
dvander@195
   494
dvander@195
   495
  private:
dvander@195
   496
    Zone *zone_;
dvander@195
   497
    PoolAllocator &pool_;
dvander@195
   498
    CompileContext &cc_;
dvander@195
   499
    TranslationUnit *unit_;
dvander@195
   500
    SymbolEnv *env_;
dvander@195
   501
    FunctionScope *fun_;
dvander@195
   502
};
dvander@195
   503
dvander@250
   504
void
dvander@195
   505
ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@195
   506
{
dvander@250
   507
    AutoEnterCompileContext enter(cc, unit);
dvander@195
   508
    NamePopulator populator(zone, cc, unit);
dvander@250
   509
    populator.analyze();
dvander@0
   510
}
dvander@0
   511
dvander@212
   512
static const int INFER_ARRAY_SIZE = 0;
dvander@212
   513
static const int EVAL_ARRAY_SIZE = -1;
dvander@212
   514
static const int DYNAMIC_ARRAY_SIZE = -2;
dvander@212
   515
dvander@256
   516
class NameBinderBase : public AstVisitor
dvander@0
   517
{
dvander@195
   518
  public:
dvander@256
   519
    NameBinderBase(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@195
   520
      : zone_(zone),
dvander@195
   521
        pool_(zone->pool()),
dvander@195
   522
        cc_(cc),
dvander@256
   523
        unit_(unit)
dvander@195
   524
    {
dvander@195
   525
    }
dvander@195
   526
dvander@256
   527
  protected:
dvander@256
   528
    Type *buildVariableType(VariableDeclaration *node) {
dvander@241
   529
        Local<Type> type(zone_, bindType(node->type(), node->quals()));
dvander@195
   530
        if (!type)
dvander@256
   531
            return NULL;
dvander@195
   532
dvander@241
   533
        // We don't allow array typedefs yet.
dvander@241
   534
        assert(!type->isArray());
dvander@241
   535
dvander@241
   536
        if (node->dims()) {
dvander@212
   537
            int dims[MAX_ARRAY_DEPTH];
dvander@212
   538
            int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
dvander@212
   539
            if (levels < 0)
dvander@256
   540
                return NULL;
dvander@212
   541
dvander@212
   542
            // Do some extra inference based on the initializer, if present.
dvander@212
   543
            Expression *init = node->initialization();
dvander@249
   544
            if (init) {
dvander@249
   545
                if (init->isArrayLiteral() && init->toArrayLiteral()->isFixed()) {
dvander@249
   546
                    Local<Type> contained(zone_, type->isArray()
dvander@249
   547
                                                 ? ArrayType::cast(type)->contained()
dvander@249
   548
                                                 : type);
dvander@249
   549
                    if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
dvander@256
   550
                        return NULL;
dvander@249
   551
                } else if (init->isStringLiteral()) {
dvander@249
   552
                    dims[levels - 1] = init->toStringLiteral()->string()->length() + 1;
dvander@249
   553
                }
dvander@212
   554
            }
dvander@212
   555
dvander@212
   556
            // If we got extra dimensions, we need to build a new type.
dvander@212
   557
            if (node->dims()) {
dvander@241
   558
                if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL)
dvander@256
   559
                    return NULL;
dvander@212
   560
            }
dvander@209
   561
        }
dvander@209
   562
dvander@256
   563
        return type;
dvander@195
   564
    }
dvander@195
   565
dvander@212
   566
    int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
dvander@212
   567
        unsigned level = 0;
dvander@212
   568
        Local<Type> type(zone_, typeArg);
dvander@212
   569
        while (type->isArray()) {
dvander@212
   570
            ArrayType *atype = ArrayType::cast(type);
dvander@212
   571
            dims[level] = atype->isFixedLength()
dvander@212
   572
                          ? atype->fixedLength()
dvander@212
   573
                          : DYNAMIC_ARRAY_SIZE;
dvander@212
   574
            type = atype->contained();
dvander@212
   575
            level++;
dvander@212
   576
        }
dvander@212
   577
dvander@212
   578
        if (!exprs)
dvander@212
   579
            return level;
dvander@212
   580
dvander@212
   581
        if (level + exprs->length() > MAX_ARRAY_DEPTH) {
dvander@212
   582
            cc_.reportError(pos, Message_MaximumArrayDepth);
dvander@212
   583
            return -1;
dvander@212
   584
        }
dvander@212
   585
dvander@212
   586
        bool hadEmptySize = false;
dvander@212
   587
        for (size_t i = 0; i < exprs->length(); i++) {
dvander@212
   588
            Expression *expr = exprs->at(i);
dvander@212
   589
            if (!expr) {
dvander@212
   590
                dims[i] = INFER_ARRAY_SIZE;
dvander@212
   591
                hadEmptySize = true;
dvander@212
   592
                continue;
dvander@212
   593
            }
dvander@212
   594
dvander@212
   595
            BoxedPrimitive box;
dvander@212
   596
            if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
dvander@212
   597
                int size = box.toInt();
dvander@212
   598
                if (size <= 0) {
dvander@212
   599
                    cc_.reportError(expr->pos(), Message_BadArraySize);
dvander@212
   600
                    return false;
dvander@212
   601
                }
dvander@212
   602
dvander@212
   603
                dims[i] = size;
dvander@212
   604
                continue;
dvander@212
   605
            }
dvander@212
   606
dvander@212
   607
            if (hadEmptySize) {
dvander@212
   608
                cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
dvander@212
   609
                return false;
dvander@212
   610
            }
dvander@212
   611
dvander@212
   612
            dims[i] = EVAL_ARRAY_SIZE;
dvander@212
   613
        }
dvander@212
   614
dvander@212
   615
        return level + exprs->length();
dvander@212
   616
    }
dvander@212
   617
dvander@212
   618
    // This function computes missing dimension sizes based on a literal
dvander@212
   619
    // initializer. We don't really handle any size rules here; we just
dvander@212
   620
    // do a really dumb inference.
dvander@212
   621
    bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
dvander@212
   622
        for (int i = 0; i < levels; i++) {
dvander@212
   623
            if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
dvander@212
   624
                // The following are invalid:
dvander@212
   625
                //   new x[<expr>] = {...}
dvander@212
   626
                //   new Type:x = {...}  // where Type is a non-fixed array type
dvander@212
   627
                cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
dvander@212
   628
                return false;
dvander@212
   629
            }
dvander@212
   630
dvander@212
   631
            if (dims[i] == INFER_ARRAY_SIZE) {
dvander@212
   632
                // Character arrays are always dynamic when inferred from string literals.
dvander@212
   633
                if (i == levels - 1 && contained->isChar())
dvander@212
   634
                    dims[i] = DYNAMIC_ARRAY_SIZE;
dvander@212
   635
                else
dvander@212
   636
                    dims[i] = lit->expressions()->length();
dvander@212
   637
            }
dvander@212
   638
dvander@212
   639
            if (i != levels - 1) {
dvander@212
   640
                // Fixed array literals are guaranteed to have at least one expression.
dvander@212
   641
                Expression *next = lit->expressions()->at(0);
dvander@212
   642
                if (!next->isArrayLiteral()) {
dvander@212
   643
                    // Whelp... this array is just malformed. Not the best error message
dvander@212
   644
                    // but whatever.
dvander@212
   645
                    cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
dvander@212
   646
                    return false;
dvander@212
   647
                }
dvander@212
   648
                lit = next->toArrayLiteral();
dvander@212
   649
            }
dvander@212
   650
        }
dvander@212
   651
dvander@212
   652
        return true;
dvander@212
   653
    }
dvander@212
   654
dvander@241
   655
    ArrayType *buildArrayType(Handle<Type> contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
dvander@212
   656
        Local<Type> type(zone_, contained);
dvander@241
   657
dvander@212
   658
        for (size_t i = postlevels - 1; i < postlevels; i--) {
dvander@212
   659
            int size = dims[i] > 0
dvander@212
   660
                       ? dims[i]
dvander@212
   661
                       : ArrayType::DYNAMIC_ARRAY_SIZE;
dvander@212
   662
            
dvander@241
   663
            if ((type = zone_->types()->newArray(contained, size)) == NULL)
dvander@241
   664
                return NULL;
dvander@241
   665
            if ((type = zone_->types()->qualify(type, quals)) == NULL)
dvander@212
   666
                return NULL;
dvander@212
   667
        }
dvander@212
   668
        return ArrayType::cast(type);
dvander@212
   669
    }
dvander@212
   670
dvander@195
   671
    bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
dvander@195
   672
        Local<Type> type(zone_);
dvander@195
   673
        if (!fun->returnType()) {
dvander@241
   674
            if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL)
dvander@195
   675
                return false;
dvander@195
   676
            fun->setReturnType(type);
dvander@195
   677
        }
dvander@195
   678
dvander@247
   679
        if (sig.variadic())
dvander@247
   680
            fun->setVariadic();
dvander@247
   681
dvander@195
   682
        Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
dvander@195
   683
        if (!params)
dvander@195
   684
            return false;
dvander@195
   685
dvander@195
   686
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
dvander@195
   687
            Parameter *param = sig.parameters()->at(i);
dvander@241
   688
            if ((type = bindType(param->type(), param->quals())) == NULL)
dvander@195
   689
                return false;
dvander@220
   690
dvander@241
   691
            assert(!type->isArray());
dvander@241
   692
dvander@241
   693
            if (param->dims()) {
dvander@220
   694
                int dims[MAX_ARRAY_DEPTH];
dvander@220
   695
                int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
dvander@220
   696
                if (levels < 0)
dvander@220
   697
                    return false;
dvander@220
   698
dvander@220
   699
                // If we got extra dimensions, we need to build a new type.
dvander@220
   700
                // Unlike variables, we do not infer anything about array
dvander@220
   701
                // sizes from its default initializer.
dvander@220
   702
                if (param->dims()) {
dvander@241
   703
                    if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL)
dvander@220
   704
                        return false;
dvander@220
   705
                }
dvander@237
   706
dvander@237
   707
                if (ArrayType::cast(type)->innermost()->isVoid()) {
dvander@237
   708
                    cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
dvander@237
   709
                    return false;
dvander@237
   710
                }
dvander@220
   711
            }
dvander@220
   712
dvander@224
   713
            if (param->reference()) {
dvander@224
   714
                if (!type->isPod()) {
dvander@224
   715
                    cc_.reportError(param->pos(), Message_ArrayCantBeReference);
dvander@224
   716
                    return false;
dvander@224
   717
                }
dvander@241
   718
                if (param->quals() & TypeQual_Const) {
dvander@241
   719
                    cc_.reportError(param->pos(), Message_CannotConstReference);
dvander@241
   720
                    return false;
dvander@241
   721
                }
dvander@224
   722
                if ((type = zone_->types()->getReference(type, false)) == NULL)
dvander@224
   723
                    return false;
dvander@224
   724
            }
dvander@241
   725
            if (param->quals() & TypeQual_Const) {
dvander@241
   726
                if (!type->isArray() && !type->isStruct()) {
dvander@241
   727
                    cc_.reportError(param->pos(), Message_InvalidConstOnFormal);
dvander@241
   728
                    return false;
dvander@241
   729
                }
dvander@241
   730
            }
dvander@222
   731
dvander@237
   732
            if (type->isVoid()) {
dvander@237
   733
                cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
dvander@237
   734
                return false;
dvander@237
   735
            }
dvander@237
   736
dvander@195
   737
            params->set(zone_, i, type);
dvander@220
   738
            param->sym()->setType(type);
dvander@195
   739
        }
dvander@195
   740
dvander@195
   741
        fun->setParameterTypes(params);
dvander@195
   742
dvander@195
   743
        return true;
dvander@195
   744
    }
dvander@195
   745
dvander@241
   746
    Type *bindType(Expression *expr, TypeQualifiers quals) {
dvander@241
   747
        Local<Type> type(zone_);
dvander@241
   748
dvander@195
   749
        if (!expr) {
dvander@195
   750
            // If no type was declared, we return int32.
dvander@241
   751
            type = zone_->types()->getPrimitive(PrimitiveType_Int32);
dvander@241
   752
        } else {
dvander@241
   753
            expr->accept(this);
dvander@195
   754
dvander@241
   755
            NameProxy *proxy = expr->asNameProxy();
dvander@241
   756
            assert(proxy);
dvander@195
   757
dvander@241
   758
            Symbol *sym = proxy->sym();
dvander@241
   759
            if (!sym)
dvander@241
   760
                return NULL;
dvander@195
   761
dvander@241
   762
            if (!sym->isType()) {
dvander@241
   763
                cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
dvander@241
   764
                return NULL;
dvander@241
   765
            }
dvander@241
   766
dvander@261
   767
            type = sym->toType()->effective();
dvander@195
   768
        }
dvander@195
   769
dvander@241
   770
        return zone_->types()->qualify(type, quals);
dvander@195
   771
    }
dvander@195
   772
dvander@256
   773
  protected:
dvander@195
   774
    Zone *zone_;
dvander@195
   775
    PoolAllocator &pool_;
dvander@195
   776
    CompileContext &cc_;
dvander@195
   777
    TranslationUnit *unit_;
dvander@256
   778
};
dvander@256
   779
dvander@256
   780
class GlobalBuilder : public NameBinderBase
dvander@256
   781
{
dvander@261
   782
    typedef ScopedRoot<Descriptor> ScopedDescriptor;
dvander@261
   783
    struct PrimitiveFill {
dvander@261
   784
        ScopedDescriptor *desc;
dvander@261
   785
        BoxedPrimitive prim;
dvander@261
   786
dvander@261
   787
        PrimitiveFill(ScopedDescriptor *desc, BoxedPrimitive prim)
dvander@261
   788
          : desc(desc),
dvander@261
   789
            prim(prim)
dvander@261
   790
        {
dvander@261
   791
        }
dvander@261
   792
    };
dvander@261
   793
dvander@256
   794
  public:
dvander@256
   795
    GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@258
   796
      : NameBinderBase(zone, cc, unit),
dvander@258
   797
        globalScope_(unit->globalScope())
dvander@256
   798
    {
dvander@256
   799
    }
dvander@256
   800
dvander@256
   801
    Struct *build() {
dvander@256
   802
        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
dvander@256
   803
            unit_->tree()->imports()->at(i)->accept(this);
dvander@256
   804
dvander@256
   805
        // Next, enter the global scope and walk all statements.
dvander@256
   806
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
dvander@256
   807
            Statement *stmt = unit_->tree()->statements()->at(i);
dvander@256
   808
            stmt->accept(this);
dvander@256
   809
        }
dvander@256
   810
dvander@261
   811
        Local<Struct> globals(zone_, createGlobals());
dvander@261
   812
        if (!globals)
dvander@261
   813
            return NULL;
dvander@261
   814
dvander@261
   815
        populate(globals);
dvander@261
   816
dvander@261
   817
        return globals;
dvander@261
   818
    }
dvander@261
   819
dvander@261
   820
  private:
dvander@261
   821
    Struct *createGlobals() {
dvander@256
   822
        Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
dvander@256
   823
        if (!descs)
dvander@256
   824
            return NULL;
dvander@256
   825
dvander@256
   826
        for (unsigned i = 0; i < descriptors_.length(); i++)
dvander@256
   827
            descs->set(zone_, i, *descriptors_[i]);
dvander@256
   828
dvander@256
   829
        Local<String> name(zone_, unit_->module()->name());
dvander@256
   830
        Local<StructType> type(zone_, StructType::New(zone_, name, descs));
dvander@256
   831
        if (!type)
dvander@256
   832
            return NULL;
dvander@256
   833
dvander@256
   834
        Local<StructMap> map(zone_, type->newMap());
dvander@256
   835
        return Struct::New(zone_, map, Heap::Tenure_Old);
dvander@256
   836
    }
dvander@256
   837
dvander@261
   838
    void populate(Handle<Struct> globals) {
dvander@261
   839
        // This is a huge hack, but it's probably better than a full extra
dvander@261
   840
        // pass. The problem is that until we have all the descriptors, we
dvander@261
   841
        // can't start setting constexprs in the struct, and we need to set
dvander@261
   842
        // them now so they're available during full semantic analysis. To
dvander@261
   843
        // work around this, we build up the list of values we need to set
dvander@261
   844
        // as we build up descriptors, and then populate the global struct
dvander@261
   845
        // with this set.
dvander@261
   846
        //
dvander@261
   847
        // Note, this code is also kind of dead until we support linking. We
dvander@261
   848
        // handle constexprs explicitly in importFrom(), by sniffing out the
dvander@261
   849
        // symbol type. That code will go away later.
dvander@261
   850
        for (size_t i = 0; i < primitiveFills_.length(); i++) {
dvander@261
   851
            const PrimitiveFill &fill = primitiveFills_[i];
dvander@261
   852
            assert(fill.prim.type() == PrimitiveType_Int32);
dvander@261
   853
            globals->set(*fill.desc, fill.prim.toInt());
dvander@261
   854
        }
dvander@261
   855
    }
dvander@261
   856
dvander@261
   857
  public:
dvander@256
   858
    void visitEnumStatement(EnumStatement *stmt) {
dvander@261
   859
        if (stmt->visibility() != TOK_PUBLIC || !stmt->name())
dvander@261
   860
            return;
dvander@261
   861
dvander@261
   862
        Local<Type> type(zone_, zone_->types()->getType());
dvander@261
   863
        Descriptor *desc = Descriptor::New(zone_, stmt->name(), type, Descriptor::Public);
dvander@261
   864
        if (!desc)
dvander@261
   865
            return;
dvander@261
   866
        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
dvander@261
   867
            return;
dvander@261
   868
dvander@261
   869
        for (size_t i = 0; i < stmt->entries()->length(); i++) {
dvander@261
   870
            EnumStatement::Entry &e = stmt->entries()->at(i);
dvander@261
   871
            ScopedDescriptor *desc = new (pool_) ScopedDescriptor(Descriptor::New(zone_, e.name, e.sym->type(), Descriptor::Public));
dvander@261
   872
            if (!desc || !descriptors_.append(desc))
dvander@261
   873
                return;
dvander@261
   874
dvander@261
   875
            // Save the value so we can export it immediately.
dvander@261
   876
            if (!primitiveFills_.append(PrimitiveFill(desc, e.sym->value())))
dvander@261
   877
                return;
dvander@261
   878
        }
dvander@256
   879
    }
dvander@256
   880
dvander@256
   881
    void visitNameProxy(NameProxy *proxy) {
dvander@256
   882
        Scope *scope = unit_->globalScope();
dvander@256
   883
        Symbol *sym = scope->lookup(proxy->name());
dvander@258
   884
        if (!sym)
dvander@258
   885
            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
dvander@256
   886
        proxy->bind(sym);
dvander@256
   887
    }
dvander@256
   888
dvander@256
   889
    void visitFunctionStatement(FunctionStatement *node) {
dvander@256
   890
        Local<FunctionType> type(zone_, node->sym()->type());
dvander@256
   891
        if (!fillFunctionType(type, node->signature()))
dvander@256
   892
            return;
dvander@256
   893
dvander@256
   894
        unsigned offset;
dvander@256
   895
        if (!builder_.add(type, &offset))
dvander@256
   896
            return;
dvander@256
   897
dvander@256
   898
        Descriptor::Visibility visibility = (node->token() == TOK_NATIVE || node->token() == TOK_FORWARD)
dvander@256
   899
                                            ? Descriptor::Public
dvander@256
   900
                                            : Descriptor::Private;
dvander@256
   901
dvander@256
   902
        Descriptor *desc = Descriptor::New(zone_, node->name(), type, visibility);
dvander@256
   903
        if (!desc)
dvander@256
   904
            return;
dvander@256
   905
        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
dvander@256
   906
            return;
dvander@256
   907
    }
dvander@256
   908
dvander@256
   909
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@256
   910
        Local<Type> type(zone_, buildVariableType(node));
dvander@256
   911
        if (!type)
dvander@256
   912
            return;
dvander@256
   913
dvander@256
   914
        // If we're in global scope, and we received a |const| qualifier, then
dvander@256
   915
        // we extend this to array references as well. This is to sort of mimic
dvander@256
   916
        // SP1 functionality, but also means that you cannot have changeable
dvander@256
   917
        // const pointers in global scope.
dvander@256
   918
        if ((node->quals() & TypeQual_Const) && type->isArray()) {
dvander@256
   919
            if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
dvander@256
   920
                return;
dvander@256
   921
        }
dvander@256
   922
dvander@256
   923
        node->sym()->setType(type);
dvander@256
   924
dvander@256
   925
        unsigned offset;
dvander@256
   926
        if (!builder_.add(type, &offset))
dvander@256
   927
            return;
dvander@256
   928
dvander@256
   929
        Descriptor *desc = Descriptor::New(zone_, node->name(), type, Descriptor::Private);
dvander@256
   930
        if (!desc)
dvander@256
   931
            return;
dvander@256
   932
        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
dvander@256
   933
            return;
dvander@256
   934
    }
dvander@256
   935
dvander@256
   936
    void visitImportStatement(ImportStatement *node) {
dvander@258
   937
        if (!node->names()) {
dvander@256
   938
            PathComponent *path = node->path();
dvander@256
   939
            while (path->next)
dvander@256
   940
                path = path->next;
dvander@256
   941
dvander@256
   942
            // Imports automatically go into the importScope. For now, we
dvander@256
   943
            // error if there are any duplicate symbols entered into the
dvander@256
   944
            // importScope.
dvander@257
   945
            if (unit_->importScope()->localLookup(path->name)) {
dvander@256
   946
                cc_.reportError(node->pos(), Message_DuplicateImport, path->name->chars());
dvander@256
   947
                return;
dvander@256
   948
            }
dvander@256
   949
dvander@256
   950
            Local<Type> type(zone_, zone_->types()->getImportable());
dvander@256
   951
            ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex());
dvander@256
   952
            if (!unit_->importScope()->addSymbol(sym))
dvander@256
   953
                return;
dvander@258
   954
        } else if (node->importAllNames()) {
dvander@258
   955
            Local<Importable> importable(zone_, unit_->module()->getImportAt(node->importIndex()));
dvander@258
   956
            if (importable->isPackage()) {
dvander@258
   957
                assert(false);
dvander@258
   958
            } else {
dvander@258
   959
                Local<Module> module(zone_, Module::cast(importable));
dvander@258
   960
                if (!module->globals())
dvander@259
   961
                    importAllFromTranslationUnit(node, module->translationUnit());
dvander@259
   962
                else
dvander@259
   963
                    assert(false);
dvander@259
   964
            }
dvander@259
   965
        } else {
dvander@259
   966
            Local<Importable> importable(zone_, unit_->module()->getImportAt(node->importIndex()));
dvander@259
   967
            if (importable->isPackage()) {
dvander@259
   968
                assert(false);
dvander@259
   969
            } else {
dvander@259
   970
                Local<Module> module(zone_, Module::cast(importable));
dvander@260
   971
dvander@260
   972
                // Always grab from the translation unit if we can, for now.
dvander@260
   973
                if (module->translationUnit())
dvander@259
   974
                    importFromTranslationUnit(node, module->translationUnit());
dvander@258
   975
                else
dvander@258
   976
                    assert(false);
dvander@258
   977
            }
dvander@258
   978
        }
dvander@258
   979
    }
dvander@258
   980
dvander@258
   981
  private:
dvander@259
   982
    bool importFrom(ImportStatement *node, Symbol *import) {
dvander@259
   983
        assert(import->type());
dvander@259
   984
dvander@259
   985
        // Check for duplicate import names.
dvander@259
   986
        if (unit_->importScope()->localLookup(import->name())) {
dvander@259
   987
            cc_.reportError(node->pos(), Message_DuplicateImport, import->name()->chars());
dvander@259
   988
            return false;
dvander@259
   989
        }
dvander@259
   990
dvander@261
   991
        Symbol *sym;
dvander@261
   992
        if (import->isType()) {
dvander@261
   993
            // Fuck it, make a TypeSymbol instead of an ImplicitSymbol. This
dvander@261
   994
            // makes bindType() much simpler. We may run into problems
dvander@261
   995
            // implementing linking, but it seems unlikely, as long as we are
dvander@261
   996
            // exporting Types in module structs.
dvander@261
   997
            Local<Type> type(zone_, zone_->types()->getType());
dvander@261
   998
            sym = new (pool_) TypeSymbol(unit_->importScope(),
dvander@261
   999
                                         import->name(),
dvander@261
  1000
                                         type,
dvander@261
  1001
                                         import->toType()->effective());
dvander@261
  1002
        } else if (import->isConstant()) {
dvander@261
  1003
            // Same deal. No reason to lookup in the module globals if we
dvander@261
  1004
            // already have a symbol.
dvander@261
  1005
            sym = new (pool_) ConstantSymbol(unit_->importScope(),
dvander@261
  1006
                                             import->name(),
dvander@261
  1007
                                             node->pos(),
dvander@261
  1008
                                             import->type(),
dvander@261
  1009
                                             import->toConstant()->value());
dvander@261
  1010
        } else {
dvander@261
  1011
            sym = new (pool_) ImplicitSymbol(unit_->importScope(),
dvander@261
  1012
                                             import->name(),
dvander@261
  1013
                                             node->pos(),
dvander@261
  1014
                                             import->type(),
dvander@261
  1015
                                             node->importIndex());
dvander@261
  1016
        }
dvander@261
  1017
dvander@259
  1018
        if (!unit_->importScope()->addSymbol(sym))
dvander@259
  1019
            return false;
dvander@259
  1020
dvander@259
  1021
        return true;
dvander@259
  1022
    }
dvander@259
  1023
dvander@259
  1024
    void importFromTranslationUnit(ImportStatement *node, TranslationUnit *other) {
dvander@259
  1025
        assert(!other->failed());
dvander@259
  1026
dvander@259
  1027
        for (size_t i = 0; i < node->names()->length(); i++) {
dvander@259
  1028
            Handle<String> name = *node->names()->at(i);
dvander@259
  1029
dvander@259
  1030
            // See if the name exists in the other translation unit.
dvander@259
  1031
            Symbol *import = other->globalScope()->findExported(name);
dvander@259
  1032
            if (!import) {
dvander@259
  1033
                FixedArray *path = unit_->module()->importPathAt(node->importIndex());
dvander@259
  1034
                cc_.reportError(node->pos(), Message_NotFoundInImportable,
dvander@259
  1035
                                name->chars(),
dvander@259
  1036
                                String::cast(path->at(path->length() - 1))->chars());
dvander@259
  1037
                return;
dvander@259
  1038
            }
dvander@259
  1039
dvander@259
  1040
            if (!importFrom(node, import))
dvander@259
  1041
                return;
dvander@259
  1042
        }
dvander@259
  1043
    }
dvander@259
  1044
dvander@259
  1045
    void importAllFromTranslationUnit(ImportStatement *node, TranslationUnit *other) {
dvander@258
  1046
        assert(!other->failed());
dvander@258
  1047
dvander@258
  1048
        for (size_t i = 0; i < other->globalScope()->exported()->length(); i++) {
dvander@258
  1049
            Symbol *import = other->globalScope()->exported()->at(i);
dvander@259
  1050
            if (!importFrom(node, import))
dvander@258
  1051
                return;
dvander@256
  1052
        }
dvander@256
  1053
    }
dvander@256
  1054
dvander@256
  1055
  private:
dvander@256
  1056
    StructureBufferBuilder builder_;
dvander@256
  1057
    Vector<ScopedRoot<Descriptor> *> descriptors_;
dvander@258
  1058
    GlobalScope *globalScope_;
dvander@261
  1059
    Vector<PrimitiveFill> primitiveFills_;
dvander@256
  1060
};
dvander@256
  1061
    
dvander@256
  1062
class NameBinder : public NameBinderBase
dvander@256
  1063
{
dvander@256
  1064
  public:
dvander@256
  1065
    class AutoLinkScope
dvander@256
  1066
    {
dvander@256
  1067
      public:
dvander@256
  1068
        AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
dvander@256
  1069
          : prevp_(prevp),
dvander@256
  1070
            prev_(*prevp),
dvander@256
  1071
            scope_(scope)
dvander@256
  1072
        {
dvander@256
  1073
            if (scope_) {
dvander@256
  1074
                *prevp_ = this;
dvander@256
  1075
                if (prev_)
dvander@256
  1076
                    scope_->setParent(prev_->scope());
dvander@256
  1077
            }
dvander@256
  1078
        }
dvander@256
  1079
        ~AutoLinkScope() {
dvander@256
  1080
            if (scope_) {
dvander@256
  1081
                assert(*prevp_ == this);
dvander@256
  1082
                *prevp_ = prev_;
dvander@256
  1083
            }
dvander@256
  1084
        }
dvander@256
  1085
        Scope *scope() const {
dvander@256
  1086
            return scope_;
dvander@256
  1087
        }
dvander@256
  1088
dvander@256
  1089
      private:
dvander@256
  1090
        AutoLinkScope **prevp_;
dvander@256
  1091
        AutoLinkScope *prev_;
dvander@256
  1092
        Scope *scope_;
dvander@256
  1093
    };
dvander@256
  1094
dvander@256
  1095
  public:
dvander@256
  1096
    NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@256
  1097
      : NameBinderBase(zone, cc, unit),
dvander@256
  1098
        link_(NULL)
dvander@256
  1099
    {
dvander@256
  1100
    }
dvander@256
  1101
dvander@256
  1102
    void bind() {
dvander@256
  1103
        // Start with the import scope, and collect all imported names.
dvander@256
  1104
        AutoLinkScope importScope(&link_, unit_->importScope());
dvander@256
  1105
dvander@256
  1106
        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
dvander@256
  1107
            unit_->tree()->imports()->at(i)->accept(this);
dvander@256
  1108
dvander@256
  1109
        // Next, enter the global scope and walk all statements.
dvander@256
  1110
        AutoLinkScope globalScope(&link_, unit_->globalScope());
dvander@256
  1111
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
dvander@256
  1112
            Statement *stmt = unit_->tree()->statements()->at(i);
dvander@256
  1113
            stmt->accept(this);
dvander@256
  1114
        }
dvander@256
  1115
    }
dvander@256
  1116
dvander@256
  1117
    void visitVariableDeclaration(VariableDeclaration *node) {
dvander@256
  1118
        // Bind the initializer before registering the declaration, so that we
dvander@256
  1119
        // can error on bogus initializers (new x = x).
dvander@256
  1120
        if (node->initialization())
dvander@256
  1121
            node->initialization()->accept(this);
dvander@256
  1122
dvander@256
  1123
        // If the node already has a symbol (meaning it was a global), then
dvander@256
  1124
        // we don't have to do anything more.
dvander@256
  1125
        if (node->sym())
dvander@256
  1126
            return;
dvander@256
  1127
dvander@256
  1128
        Local<Type> type(zone_, buildVariableType(node));
dvander@256
  1129
        if (!type)
dvander@256
  1130
            return;
dvander@256
  1131
dvander@256
  1132
        VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
dvander@256
  1133
        node->setSymbol(sym);
dvander@256
  1134
       
dvander@256
  1135
        if (Symbol *other = link_->scope()->localLookup(sym->name())) {
dvander@256
  1136
            // Report, but allow errors to continue.
dvander@256
  1137
            cc_.reportError(sym->pos(), Message_RedeclaredName,
dvander@256
  1138
                            sym->name()->chars(),
dvander@256
  1139
                            other->pos().line,
dvander@256
  1140
                            other->pos().col);
dvander@256
  1141
            return;
dvander@256
  1142
        }
dvander@256
  1143
        
dvander@256
  1144
        link_->scope()->addSymbol(sym);
dvander@256
  1145
    }
dvander@256
  1146
    void visitEnumStatement(EnumStatement *node) {
dvander@256
  1147
    }
dvander@256
  1148
    void visitFunctionStatement(FunctionStatement *node) {
dvander@256
  1149
        AutoLinkScope argScope(&link_, node->argScope());
dvander@256
  1150
        AutoLinkScope varScope(&link_, node->varScope());
dvander@256
  1151
dvander@256
  1152
        // If the function is in the global scope, we've already computed its
dvander@256
  1153
        // type.
dvander@256
  1154
        if (node->sym()->scope()->kind() != Scope::GLOBAL) {
dvander@256
  1155
            Local<FunctionType> type(zone_, node->sym()->type());
dvander@256
  1156
            if (!fillFunctionType(type, node->signature()))
dvander@256
  1157
                return;
dvander@256
  1158
        }
dvander@256
  1159
dvander@256
  1160
        if (node->body())
dvander@256
  1161
            node->body()->accept(this);
dvander@256
  1162
    }
dvander@256
  1163
    void visitStructureStatement(StructureStatement *node) {
dvander@256
  1164
        assert(false);
dvander@256
  1165
    }
dvander@256
  1166
    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
dvander@256
  1167
        assert(false);
dvander@256
  1168
    }
dvander@256
  1169
dvander@256
  1170
    void visitNameProxy(NameProxy *proxy) {
dvander@256
  1171
        // We could have already bound globals.
dvander@256
  1172
        if (proxy->sym())
dvander@256
  1173
            return;
dvander@256
  1174
dvander@256
  1175
        Scope *scope = link_->scope();
dvander@256
  1176
        Symbol *sym = scope->lookup(proxy->name());
dvander@256
  1177
        if (!sym)
dvander@256
  1178
            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
dvander@256
  1179
        proxy->bind(sym);
dvander@256
  1180
    }
dvander@256
  1181
    void visitAssignment(Assignment *node) {
dvander@256
  1182
        node->lvalue()->accept(this);
dvander@256
  1183
        node->expression()->accept(this);
dvander@256
  1184
    }
dvander@256
  1185
    void visitBinaryExpression(BinaryExpression *node) {
dvander@256
  1186
        node->left()->accept(this);
dvander@256
  1187
        node->right()->accept(this);
dvander@256
  1188
    }
dvander@256
  1189
    void visitReturnStatement(ReturnStatement *node) {
dvander@256
  1190
        node->expression()->accept(this);
dvander@256
  1191
    }
dvander@256
  1192
    void visitForStatement(ForStatement *node) {
dvander@256
  1193
        AutoLinkScope scope(&link_, node->scope());
dvander@256
  1194
dvander@256
  1195
        if (node->initialization())
dvander@256
  1196
            node->initialization()->accept(this);
dvander@256
  1197
        if (node->condition())
dvander@256
  1198
            node->condition()->accept(this);
dvander@256
  1199
        if (node->update())
dvander@256
  1200
            node->update()->accept(this);
dvander@256
  1201
        node->body()->accept(this);
dvander@256
  1202
    }
dvander@256
  1203
    void visitBlockStatement(BlockStatement *node) {
dvander@256
  1204
        AutoLinkScope scope(&link_, node->scope());
dvander@256
  1205
        for (size_t i = 0; i < node->statements()->length(); i++)
dvander@256
  1206
            node->statements()->at(i)->accept(this);
dvander@256
  1207
    }
dvander@256
  1208
    void visitIntegerLiteral(IntegerLiteral *node) {
dvander@256
  1209
    }
dvander@256
  1210
    void visitExpressionStatement(ExpressionStatement *node) {
dvander@256
  1211
        node->expression()->accept(this);
dvander@256
  1212
    }
dvander@256
  1213
    void visitCallExpression(CallExpression *node) {
dvander@256
  1214
        node->callee()->accept(this);
dvander@256
  1215
        for (size_t i = 0; i < node->arguments()->length(); i++)
dvander@256
  1216
            node->arguments()->at(i)->accept(this);
dvander@256
  1217
    }
dvander@256
  1218
    void visitIfStatement(IfStatement *node) {
dvander@256
  1219
        node->condition()->accept(this);
dvander@256
  1220
        node->ifTrue()->accept(this);
dvander@256
  1221
        if (node->ifFalse())
dvander@256
  1222
            node->ifFalse()->accept(this);
dvander@256
  1223
    }
dvander@256
  1224
    void visitIndexExpression(IndexExpression *node) {
dvander@256
  1225
        node->left()->accept(this);
dvander@256
  1226
        node->right()->accept(this);
dvander@256
  1227
    }
dvander@256
  1228
    void visitFloatLiteral(FloatLiteral *node) {
dvander@256
  1229
    }
dvander@256
  1230
    void visitWhileStatement(WhileStatement *node) {
dvander@256
  1231
        node->condition()->accept(this);
dvander@256
  1232
        node->body()->accept(this);
dvander@256
  1233
    }
dvander@256
  1234
    void visitBreakStatement(BreakStatement *node) {
dvander@256
  1235
    }
dvander@256
  1236
    void visitContinueStatement(ContinueStatement *node) {
dvander@256
  1237
    }
dvander@256
  1238
    void visitStringLiteral(StringLiteral *node) {
dvander@256
  1239
    }
dvander@256
  1240
    void visitIncDecExpression(IncDecExpression *node) {
dvander@256
  1241
        node->expression()->accept(this);
dvander@256
  1242
    }
dvander@256
  1243
    void visitUnaryExpression(UnaryExpression *node) {
dvander@256
  1244
        if (node->tag())
dvander@256
  1245
            node->tag()->accept(this);
dvander@256
  1246
        node->expression()->accept(this);
dvander@256
  1247
    }
dvander@256
  1248
    void visitTernaryExpression(TernaryExpression *node) {
dvander@256
  1249
        node->condition()->accept(this);
dvander@256
  1250
        node->left()->accept(this);
dvander@256
  1251
        node->right()->accept(this);
dvander@256
  1252
    }
dvander@256
  1253
    void visitBooleanLiteral(BooleanLiteral *node) {
dvander@256
  1254
    }
dvander@256
  1255
    void visitFieldExpression(FieldExpression *node) {
dvander@256
  1256
        node->left()->accept(this);
dvander@256
  1257
    }
dvander@256
  1258
    void visitSwitchStatement(SwitchStatement *node) {
dvander@256
  1259
        node->expression()->accept(this);
dvander@256
  1260
        node->defaultCase()->accept(this);
dvander@256
  1261
        for (size_t i = 0; i < node->cases()->length(); i++) {
dvander@256
  1262
            // We don't test case expressions because they are literals.
dvander@256
  1263
            Case *c = node->cases()->at(i);
dvander@256
  1264
            c->statement()->accept(this);
dvander@256
  1265
        }
dvander@256
  1266
    }
dvander@256
  1267
    void visitArrayLiteral(ArrayLiteral *node) {
dvander@256
  1268
        for (size_t i = 0; i < node->expressions()->length(); i++)
dvander@256
  1269
            node->expressions()->at(i)->accept(this);
dvander@256
  1270
    }
dvander@256
  1271
    void visitImportStatement(ImportStatement *node) {
dvander@256
  1272
    }
dvander@256
  1273
dvander@256
  1274
  private:
dvander@195
  1275
    AutoLinkScope *link_;
dvander@195
  1276
};
dvander@85
  1277
dvander@250
  1278
void
dvander@258
  1279
ke::BindGlobals(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@85
  1280
{
dvander@250
  1281
    AutoEnterCompileContext enter(cc, unit);
dvander@256
  1282
dvander@256
  1283
    GlobalBuilder builder(zone, cc, unit);
dvander@256
  1284
    Local<Struct> globals(zone, builder.build());
dvander@256
  1285
    if (!globals || unit->failed())
dvander@256
  1286
        return;
dvander@256
  1287
dvander@256
  1288
    unit->module()->setGlobals(globals);
dvander@258
  1289
}
dvander@256
  1290
dvander@258
  1291
void
dvander@258
  1292
ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
dvander@258
  1293
{
dvander@258
  1294
    AutoEnterCompileContext enter(cc, unit);
dvander@195
  1295
    NameBinder binder(zone, cc, unit);
dvander@250
  1296
    binder.bind();
dvander@85
  1297
}