src/compiler/NameBinding.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 251 ca99a81745fe
child 257 9db4cc815ebc
permissions -rw-r--r--
Initial implementation of module imports.
[email protected]
     1
/* vim: set ts=4 sw=4 tw=99 et:
[email protected]
     2
 *
[email protected]
     3
 * Copyright (C) 2012 David Anderson
[email protected]
     4
 *
[email protected]
     5
 * This file is part of SourcePawn.
[email protected]
     6
 *
[email protected]
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
[email protected]
     8
 * the terms of the GNU General Public License as published by the Free
[email protected]
     9
 * Software Foundation, either version 3 of the License, or (at your option)
[email protected]
    10
 * any later version.
[email protected]
    11
 * 
[email protected]
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
[email protected]
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
[email protected]
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
[email protected]
    15
 *
[email protected]
    16
 * You should have received a copy of the GNU General Public License along with
[email protected]
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
[email protected]
    18
 */
[email protected]
    19
#include "../Strings.h"
[email protected]
    20
#include "../Zone.h"
[email protected]
    21
#include "../TypeManager.h"
[email protected]
    22
#include "NameBinding.h"
[email protected]
    23
#include "Scopes.h"
[email protected]
    24
#include "ConstantEvaluator.h"
[email protected]
    25
#include "../Spaces-inl.h"
[email protected]
    26
#include "../Heap-inl.h"
[email protected]
    27
[email protected]
    28
using namespace ke;
[email protected]
    29
[email protected]
    30
// Create symbol tables and symbols for every scope and declaration. For type
[email protected]
    31
// declarations and methods, we also pre-allocate a Type object, so that
[email protected]
    32
// circular dependencies between types will work.
[email protected]
    33
class NamePopulator : public AstVisitor
[email protected]
    34
{
[email protected]
    35
  private:
[email protected]
    36
    // This class is analagous to a Scope, however, it allows us to create
[email protected]
    37
    // scopes lazily. If a scope is requested, and the current environment
[email protected]
    38
    // has no scope, then a scope is created. If no scope is ever requested,
[email protected]
    39
    // a scope does not need to be created.
[email protected]
    40
    class SymbolEnv
[email protected]
    41
    {
[email protected]
    42
      public:
[email protected]
    43
        SymbolEnv(SymbolEnv **prevp, Scope *scope = NULL)
[email protected]
    44
          : envp_(prevp),
[email protected]
    45
            prev_(*prevp),
[email protected]
    46
            scope_(scope)
[email protected]
    47
        {
[email protected]
    48
            *envp_ = this;
[email protected]
    49
        }
[email protected]
    50
        ~SymbolEnv() {
[email protected]
    51
            *envp_ = prev_;
[email protected]
    52
        }
[email protected]
    53
[email protected]
    54
        Scope *scope() {
[email protected]
    55
            return scope_;
[email protected]
    56
        }
[email protected]
    57
        void setScope(Scope *scope) {
[email protected]
    58
            assert(!scope_);
[email protected]
    59
            scope_ = scope;
[email protected]
    60
        }
[email protected]
    61
        SymbolEnv *prev() const {
[email protected]
    62
            return prev_;
[email protected]
    63
        }
[email protected]
    64
[email protected]
    65
      private:
[email protected]
    66
        SymbolEnv **envp_;
[email protected]
    67
        SymbolEnv *prev_;
[email protected]
    68
        Scope *scope_;
[email protected]
    69
    };
[email protected]
    70
[email protected]
    71
    enum ReturnStatus {
[email protected]
    72
        NoReturn,
[email protected]
    73
        VoidReturn,
[email protected]
    74
        ValueReturn
[email protected]
    75
    };
[email protected]
    76
[email protected]
    77
    class FunctionScope
[email protected]
    78
    {
[email protected]
    79
      public:
[email protected]
    80
        FunctionScope(FunctionScope **prevp)
[email protected]
    81
          : prevp_(prevp),
[email protected]
    82
            prev_(*prevp),
[email protected]
    83
            status_(NoReturn)
[email protected]
    84
        {
[email protected]
    85
            *prevp_ = this;
[email protected]
    86
        }
[email protected]
    87
        ~FunctionScope() {
[email protected]
    88
            *prevp_ = prev_;
[email protected]
    89
        }
[email protected]
    90
        ReturnStatus returns() const {
[email protected]
    91
            return status_;
[email protected]
    92
        }
[email protected]
    93
        void returns(ReturnStatus status) {
[email protected]
    94
            if (status > status_)
[email protected]
    95
                status_ = status;
[email protected]
    96
        }
[email protected]
    97
      private:
[email protected]
    98
        FunctionScope **prevp_;
[email protected]
    99
        FunctionScope *prev_;
[email protected]
   100
        ReturnStatus status_;
[email protected]
   101
    };
[email protected]
   102
[email protected]
   103
  public:
[email protected]
   104
    NamePopulator(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
   105
      : zone_(zone),
[email protected]
   106
        pool_(zone->pool()),
[email protected]
   107
        cc_(cc),
[email protected]
   108
        unit_(unit),
[email protected]
   109
        env_(NULL),
[email protected]
   110
        fun_(NULL)
[email protected]
   111
    {
[email protected]
   112
    }
[email protected]
   113
[email protected]
   114
    void analyze() {
[email protected]
   115
        ImportScope *importScope = ImportScope::New(pool_);
[email protected]
   116
        if (!importScope)
[email protected]
   117
            return;
[email protected]
   118
[email protected]
   119
        // At the import level, we declare system types.
[email protected]
   120
        if (!declareSystemTypes(importScope))
[email protected]
   121
            return;
[email protected]
   122
[email protected]
   123
        GlobalScope *globalScope = GlobalScope::New(pool_, importScope);
[email protected]
   124
        if (!globalScope)
[email protected]
   125
            return;
[email protected]
   126
[email protected]
   127
        unit_->setImportScope(importScope);
[email protected]
   128
        unit_->setGlobalScope(globalScope);
[email protected]
   129
[email protected]
   130
        SymbolEnv env(&env_, globalScope);
[email protected]
   131
[email protected]
   132
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
[email protected]
   133
            Statement *stmt = unit_->tree()->statements()->at(i);
[email protected]
   134
            stmt->accept(this);
[email protected]
   135
        }
[email protected]
   136
[email protected]
   137
        return;
[email protected]
   138
    }
[email protected]
   139
[email protected]
   140
    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
[email protected]
   141
        Local<String> tag(zone_, zone_->makeSymbol(name));
[email protected]
   142
        if (!tag)
[email protected]
   143
            return false;
[email protected]
   144
[email protected]
   145
        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
[email protected]
   146
        return scope->addSymbol(sym);
[email protected]
   147
    }
[email protected]
   148
[email protected]
   149
    bool declareSystemType(ImportScope *scope, const char *name, PrimitiveType prim) {
[email protected]
   150
        Local<Type> primitive(zone_, zone_->types()->getPrimitive(prim));
[email protected]
   151
        assert(primitive);
[email protected]
   152
        return declareSystemType(scope, name, primitive);
[email protected]
   153
    }
[email protected]
   154
[email protected]
   155
    bool declareSystemTypes(ImportScope *scope) {
[email protected]
   156
        if (!declareSystemType(scope, "float", PrimitiveType_Float))
[email protected]
   157
            return false;
[email protected]
   158
        if (!declareSystemType(scope, "_", PrimitiveType_Int32))
[email protected]
   159
            return false;
[email protected]
   160
        if (!declareSystemType(scope, "int", PrimitiveType_Int32))
[email protected]
   161
            return false;
[email protected]
   162
        if (!declareSystemType(scope, "bool", PrimitiveType_Bool))
[email protected]
   163
            return false;
[email protected]
   164
        if (!declareSystemType(scope, "char", PrimitiveType_Char))
[email protected]
   165
            return false;
[email protected]
   166
[email protected]
   167
        Local<Type> voidType(zone_, zone_->types()->getVoid());
[email protected]
   168
        if (!declareSystemType(scope, "void", voidType))
[email protected]
   169
            return false;
[email protected]
   170
[email protected]
   171
        return true;
[email protected]
   172
    }
[email protected]
   173
[email protected]
   174
    void visitVariableDeclaration(VariableDeclaration *node) {
[email protected]
   175
        Scope *scope = env_->scope();
[email protected]
   176
        if (!scope || scope->kind() != Scope::GLOBAL) {
[email protected]
   177
            if ((scope = getOrCreateBlockScope()) == NULL)
[email protected]
   178
                return;
[email protected]
   179
        }
[email protected]
   180
[email protected]
   181
        if (scope->kind() == Scope::GLOBAL) {
[email protected]
   182
            // The symbol must be added now, since it could be an export.
[email protected]
   183
            VariableSymbol *sym = new (pool_) VariableSymbol(scope, node->name(), node->pos());
[email protected]
   184
            node->setSymbol(sym);
[email protected]
   185
[email protected]
   186
            if (!registerName(scope, sym))
[email protected]
   187
                return;
[email protected]
   188
        } else {
[email protected]
   189
            // We ensure the scope will exist at the name binding phase, but
[email protected]
   190
            // we don't actually register the variable symbol yet. Otherwise,
[email protected]
   191
            // when binding the initializer, we could encounter:
[email protected]
   192
            //    new x = x;
[email protected]
   193
            //
[email protected]
   194
            // And we don't necessarily want this to bind.
[email protected]
   195
        }
[email protected]
   196
[email protected]
   197
        if (node->initialization())
[email protected]
   198
            node->initialization()->accept(this);
[email protected]
   199
    }
[email protected]
   200
[email protected]
   201
    void visitEnumStatement(EnumStatement *node) {
[email protected]
   202
        Local<String> name(zone_, node->name());
[email protected]
   203
        Local<Type> type(zone_);
[email protected]
   204
        if (name)
[email protected]
   205
            type = zone_->types()->newEnum(name);
[email protected]
   206
        else
[email protected]
   207
            type = zone_->types()->getPrimitive(PrimitiveType_Int32);
[email protected]
   208
[email protected]
   209
        if (!type)
[email protected]
   210
            return;
[email protected]
   211
[email protected]
   212
        Scope *scope = getGlobalOrCreateBlockScope();
[email protected]
   213
        if (!scope)
[email protected]
   214
            return;
[email protected]
   215
[email protected]
   216
        if (name) {
[email protected]
   217
            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
[email protected]
   218
            if (!registerName(scope, sym))
[email protected]
   219
                return;
[email protected]
   220
        }
[email protected]
   221
[email protected]
   222
        int value = 0;
[email protected]
   223
        for (size_t i = 0; i < node->entries()->length(); i++) {
[email protected]
   224
            EnumStatement::Entry &entry = node->entries()->at(i);
[email protected]
   225
            BoxedPrimitive box = BoxedPrimitive::Int(value);
[email protected]
   226
            if (entry.expr) {
[email protected]
   227
                if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
[email protected]
   228
                    cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
[email protected]
   229
                    return;
[email protected]
   230
                }
[email protected]
   231
[email protected]
   232
                assert(box.type() == PrimitiveType_Int32);
[email protected]
   233
                value = box.toInt();
[email protected]
   234
            }
[email protected]
   235
            
[email protected]
   236
            ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
[email protected]
   237
            if (!registerName(scope, sym))
[email protected]
   238
                return;
[email protected]
   239
[email protected]
   240
            value++;
[email protected]
   241
        }
[email protected]
   242
    }
[email protected]
   243
[email protected]
   244
    void visitFunctionStatement(FunctionStatement *node) {
[email protected]
   245
        // We create function types ahead of time, not for any particular
[email protected]
   246
        // reason. It makes things consistent with FunctionTypeStatement,
[email protected]
   247
        // which actually does produce a type.
[email protected]
   248
        Local<FunctionType> type(zone_, FunctionType::New(zone_, node->name(), node->token()));
[email protected]
   249
        if (!type)
[email protected]
   250
            return;
[email protected]
   251
[email protected]
   252
        assert(env_->scope());
[email protected]
   253
[email protected]
   254
        // Function statements are always named, so add the name to the outer scope.
[email protected]
   255
        FunctionSymbol *sym = new (pool_) FunctionSymbol(env_->scope(), node->name(), node->pos(), type);
[email protected]
   256
        if (!registerName(env_->scope(), sym))
[email protected]
   257
            return;
[email protected]
   258
[email protected]
   259
        if (node->token() == TOK_PUBLIC ||
[email protected]
   260
            node->token() == TOK_FORWARD ||
[email protected]
   261
            node->token() == TOK_NATIVE)
[email protected]
   262
        {
[email protected]
   263
            // We're in the global scope, for sure.
[email protected]
   264
            assert(env_->scope()->kind() == Scope::GLOBAL);
[email protected]
   265
        }
[email protected]
   266
[email protected]
   267
        node->setSymbol(sym);
[email protected]
   268
[email protected]
   269
        // Scope for the function's arguments.
[email protected]
   270
        SymbolEnv argEnv(&env_);
[email protected]
   271
        if (!registerArguments(node->signature()))
[email protected]
   272
            return;
[email protected]
   273
[email protected]
   274
        // Scope for function body.
[email protected]
   275
        SymbolEnv localEnv(&env_);
[email protected]
   276
        FunctionScope fun(&fun_);
[email protected]
   277
        if (node->body())
[email protected]
   278
            node->body()->accept(this);
[email protected]
   279
[email protected]
   280
        // Function statements have quirky semantics around their return
[email protected]
   281
        // type. For reasonable compatibility with SP1, we use the following
[email protected]
   282
        // heuristics for when no explicit type is declared.
[email protected]
   283
        if (!node->signature().returnType()) {
[email protected]
   284
            Local<Type> type(zone_);
[email protected]
   285
            if (node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) {
[email protected]
   286
                // If the function type is a native or forward, we always
[email protected]
   287
                // assume it returns an int32.
[email protected]
   288
                type = zone_->types()->getPrimitive(PrimitiveType_Int32);
[email protected]
   289
            } else if (fun.returns() != ValueReturn) {
[email protected]
   290
                // This function never returns a value, so mark it as
[email protected]
   291
                // returning void.
[email protected]
   292
                type = zone_->types()->getVoid();
[email protected]
   293
            }
[email protected]
   294
            // No need to NULL check here, we'll catch OOM later.
[email protected]
   295
            node->sym()->type()->setReturnType(type);
[email protected]
   296
        }
[email protected]
   297
[email protected]
   298
        node->setScopes(argEnv.scope(), localEnv.scope());
[email protected]
   299
    }
[email protected]
   300
[email protected]
   301
    void visitStructureStatement(StructureStatement *node) {
[email protected]
   302
        assert(false);
[email protected]
   303
    }
[email protected]
   304
[email protected]
   305
    void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
[email protected]
   306
        assert(false);
[email protected]
   307
    }
[email protected]
   308
[email protected]
   309
    void visitNameProxy(NameProxy *name) {
[email protected]
   310
    }
[email protected]
   311
    void visitAssignment(Assignment *node) {
[email protected]
   312
        node->lvalue()->accept(this);
[email protected]
   313
        node->expression()->accept(this);
[email protected]
   314
    }
[email protected]
   315
    void visitBinaryExpression(BinaryExpression *node) {
[email protected]
   316
        node->left()->accept(this);
[email protected]
   317
        node->right()->accept(this);
[email protected]
   318
    }
[email protected]
   319
    void visitReturnStatement(ReturnStatement *node) {
[email protected]
   320
        if (node->expression())
[email protected]
   321
            fun_->returns(ValueReturn);
[email protected]
   322
        else
[email protected]
   323
            fun_->returns(VoidReturn);
[email protected]
   324
    }
[email protected]
   325
    void visitForStatement(ForStatement *node) {
[email protected]
   326
        SymbolEnv env(&env_);
[email protected]
   327
[email protected]
   328
        if (node->initialization())
[email protected]
   329
            node->initialization()->accept(this);
[email protected]
   330
        if (node->condition())
[email protected]
   331
            node->condition()->accept(this);
[email protected]
   332
        if (node->update())
[email protected]
   333
            node->update()->accept(this);
[email protected]
   334
        node->body()->accept(this);
[email protected]
   335
[email protected]
   336
        node->setScope(env.scope());
[email protected]
   337
    }
[email protected]
   338
    void visitBlockStatement(BlockStatement *node) {
[email protected]
   339
        if (node->type() == TOK_NEW) {
[email protected]
   340
            // Don't create a symbol environment for this block, since it
[email protected]
   341
            // was created solely to house multiple variable decls.
[email protected]
   342
            for (size_t i = 0; i < node->statements()->length(); i++)
[email protected]
   343
                node->statements()->at(i)->accept(this);
[email protected]
   344
        } else {
[email protected]
   345
            assert(node->type() == TOK_LBRACE);
[email protected]
   346
[email protected]
   347
            SymbolEnv env(&env_);
[email protected]
   348
[email protected]
   349
            for (size_t i = 0; i < node->statements()->length(); i++)
[email protected]
   350
                node->statements()->at(i)->accept(this);
[email protected]
   351
        
[email protected]
   352
            if (node->type() == TOK_NEW) {
[email protected]
   353
                assert(!env.scope());
[email protected]
   354
                return;
[email protected]
   355
            }
[email protected]
   356
[email protected]
   357
            node->setScope(env.scope());
[email protected]
   358
        }
[email protected]
   359
    }
[email protected]
   360
    void visitIntegerLiteral(IntegerLiteral *node) {
[email protected]
   361
    }
[email protected]
   362
    void visitExpressionStatement(ExpressionStatement *node) {
[email protected]
   363
        node->expression()->accept(this);
[email protected]
   364
    }
[email protected]
   365
    void visitCallExpression(CallExpression *node) {
[email protected]
   366
        node->callee()->accept(this);
[email protected]
   367
        for (size_t i = 0; i < node->arguments()->length(); i++)
[email protected]
   368
            node->arguments()->at(i)->accept(this);
[email protected]
   369
    }
[email protected]
   370
    void visitIfStatement(IfStatement *node) {
[email protected]
   371
        node->ifTrue()->accept(this);
[email protected]
   372
        if (node->ifFalse())
[email protected]
   373
            node->ifFalse()->accept(this);
[email protected]
   374
    }
[email protected]
   375
    void visitIndexExpression(IndexExpression *node) {
[email protected]
   376
        node->left()->accept(this);
[email protected]
   377
        node->right()->accept(this);
[email protected]
   378
    }
[email protected]
   379
    void visitFloatLiteral(FloatLiteral *node) {
[email protected]
   380
    }
[email protected]
   381
    void visitWhileStatement(WhileStatement *node) {
[email protected]
   382
        node->condition()->accept(this);
[email protected]
   383
        node->body()->accept(this);
[email protected]
   384
    }
[email protected]
   385
    void visitBreakStatement(BreakStatement *node) {
[email protected]
   386
    }
[email protected]
   387
    void visitContinueStatement(ContinueStatement *node) {
[email protected]
   388
    }
[email protected]
   389
    void visitStringLiteral(StringLiteral *node) {
[email protected]
   390
    }
[email protected]
   391
    void visitIncDecExpression(IncDecExpression *node) {
[email protected]
   392
        node->expression()->accept(this);
[email protected]
   393
    }
[email protected]
   394
    void visitUnaryExpression(UnaryExpression *node) {
[email protected]
   395
        node->expression()->accept(this);
[email protected]
   396
    }
[email protected]
   397
    void visitTernaryExpression(TernaryExpression *node) {
[email protected]
   398
        assert(false);
[email protected]
   399
    }
[email protected]
   400
    void visitBooleanLiteral(BooleanLiteral *node) {
[email protected]
   401
    }
[email protected]
   402
    void visitFieldExpression(FieldExpression *node) {
[email protected]
   403
    }
[email protected]
   404
    void visitSwitchStatement(SwitchStatement *node) {
[email protected]
   405
        if (node->defaultCase())
[email protected]
   406
            node->defaultCase()->accept(this);
[email protected]
   407
[email protected]
   408
        for (size_t i = 0; i < node->cases()->length(); i++)
[email protected]
   409
            node->cases()->at(i)->statement()->accept(this);
[email protected]
   410
    }
[email protected]
   411
    void visitArrayLiteral(ArrayLiteral *node) {
[email protected]
   412
    }
[email protected]
   413
    void visitImportStatement(ImportStatement *node) {
[email protected]
   414
    }
[email protected]
   415
[email protected]
   416
  private:
[email protected]
   417
    Scope *getGlobalOrCreateBlockScope() {
[email protected]
   418
        if (env_->scope()) {
[email protected]
   419
            assert(env_->scope()->kind() == Scope::BLOCK ||
[email protected]
   420
                   env_->scope()->kind() == Scope::GLOBAL);
[email protected]
   421
            return env_->scope();
[email protected]
   422
        }
[email protected]
   423
        return getOrCreateBlockScope();
[email protected]
   424
    }
[email protected]
   425
    Scope *getOrCreateBlockScope() {
[email protected]
   426
        if (env_->scope()) {
[email protected]
   427
            assert(env_->scope()->kind() == Scope::BLOCK);
[email protected]
   428
            return env_->scope();
[email protected]
   429
        }
[email protected]
   430
        
[email protected]
   431
        LocalScope *scope = LocalScope::New(pool_);
[email protected]
   432
        if (!scope)
[email protected]
   433
            return NULL;
[email protected]
   434
[email protected]
   435
        env_->setScope(scope);
[email protected]
   436
        return scope;
[email protected]
   437
    }
[email protected]
   438
[email protected]
   439
    bool registerName(Scope *scope, Symbol *sym) {
[email protected]
   440
        if (!scope)
[email protected]
   441
            return false;
[email protected]
   442
[email protected]
   443
        if (Symbol *other = scope->localLookup(sym->name())) {
[email protected]
   444
            // Report, but allow errors to continue.
[email protected]
   445
            cc_.reportError(sym->pos(), Message_RedeclaredName,
[email protected]
   446
                            sym->name()->chars(),
[email protected]
   447
                            other->pos().line,
[email protected]
   448
                            other->pos().col);
[email protected]
   449
            return true;
[email protected]
   450
        }
[email protected]
   451
[email protected]
   452
        return scope->addSymbol(sym);
[email protected]
   453
    }
[email protected]
   454
[email protected]
   455
    bool registerArguments(const FunctionSignature &sig) {
[email protected]
   456
        if (!sig.parameters()->length())
[email protected]
   457
            return true;
[email protected]
   458
[email protected]
   459
        ArgumentScope *argScope = ArgumentScope::New(pool_);
[email protected]
   460
        if (!argScope)
[email protected]
   461
            return false;
[email protected]
   462
        env_->setScope(argScope);
[email protected]
   463
[email protected]
   464
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
[email protected]
   465
            Parameter *param = sig.parameters()->at(i);
[email protected]
   466
            VariableSymbol *sym = new (pool_) VariableSymbol(argScope, param->name(), param->pos());
[email protected]
   467
            if (!registerName(env_->scope(), sym))
[email protected]
   468
                return false;
[email protected]
   469
            param->setSymbol(sym);
[email protected]
   470
        }
[email protected]
   471
[email protected]
   472
        return true;
[email protected]
   473
    }
[email protected]
   474
[email protected]
   475
  private:
[email protected]
   476
    Zone *zone_;
[email protected]
   477
    PoolAllocator &pool_;
[email protected]
   478
    CompileContext &cc_;
[email protected]
   479
    TranslationUnit *unit_;
[email protected]
   480
    SymbolEnv *env_;
[email protected]
   481
    FunctionScope *fun_;
[email protected]
   482
};
[email protected]
   483
[email protected]
   484
void
[email protected]
   485
ke::PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
   486
{
[email protected]
   487
    AutoEnterCompileContext enter(cc, unit);
[email protected]
   488
    NamePopulator populator(zone, cc, unit);
[email protected]
   489
    populator.analyze();
[email protected]
   490
}
[email protected]
   491
[email protected]
   492
static const int INFER_ARRAY_SIZE = 0;
[email protected]
   493
static const int EVAL_ARRAY_SIZE = -1;
[email protected]
   494
static const int DYNAMIC_ARRAY_SIZE = -2;
[email protected]
   495
[email protected]
   496
class NameBinderBase : public AstVisitor
[email protected]
   497
{
[email protected]
   498
  public:
[email protected]
   499
    NameBinderBase(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
   500
      : zone_(zone),
[email protected]
   501
        pool_(zone->pool()),
[email protected]
   502
        cc_(cc),
[email protected]
   503
        unit_(unit)
[email protected]
   504
    {
[email protected]
   505
    }
[email protected]
   506
[email protected]
   507
[email protected]
   508
  protected:
[email protected]
   509
    Type *buildVariableType(VariableDeclaration *node) {
[email protected]
   510
        Local<Type> type(zone_, bindType(node->type(), node->quals()));
[email protected]
   511
        if (!type)
[email protected]
   512
            return NULL;
[email protected]
   513
[email protected]
   514
        // We don't allow array typedefs yet.
[email protected]
   515
        assert(!type->isArray());
[email protected]
   516
[email protected]
   517
        if (node->dims()) {
[email protected]
   518
            int dims[MAX_ARRAY_DEPTH];
[email protected]
   519
            int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
[email protected]
   520
            if (levels < 0)
[email protected]
   521
                return NULL;
[email protected]
   522
[email protected]
   523
            // Do some extra inference based on the initializer, if present.
[email protected]
   524
            Expression *init = node->initialization();
[email protected]
   525
            if (init) {
[email protected]
   526
                if (init->isArrayLiteral() && init->toArrayLiteral()->isFixed()) {
[email protected]
   527
                    Local<Type> contained(zone_, type->isArray()
[email protected]
   528
                                                 ? ArrayType::cast(type)->contained()
[email protected]
   529
                                                 : type);
[email protected]
   530
                    if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
[email protected]
   531
                        return NULL;
[email protected]
   532
                } else if (init->isStringLiteral()) {
[email protected]
   533
                    dims[levels - 1] = init->toStringLiteral()->string()->length() + 1;
[email protected]
   534
                }
[email protected]
   535
            }
[email protected]
   536
[email protected]
   537
            // If we got extra dimensions, we need to build a new type.
[email protected]
   538
            if (node->dims()) {
[email protected]
   539
                if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL)
[email protected]
   540
                    return NULL;
[email protected]
   541
            }
[email protected]
   542
        }
[email protected]
   543
[email protected]
   544
        return type;
[email protected]
   545
    }
[email protected]
   546
[email protected]
   547
    int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
[email protected]
   548
        unsigned level = 0;
[email protected]
   549
        Local<Type> type(zone_, typeArg);
[email protected]
   550
        while (type->isArray()) {
[email protected]
   551
            ArrayType *atype = ArrayType::cast(type);
[email protected]
   552
            dims[level] = atype->isFixedLength()
[email protected]
   553
                          ? atype->fixedLength()
[email protected]
   554
                          : DYNAMIC_ARRAY_SIZE;
[email protected]
   555
            type = atype->contained();
[email protected]
   556
            level++;
[email protected]
   557
        }
[email protected]
   558
[email protected]
   559
        if (!exprs)
[email protected]
   560
            return level;
[email protected]
   561
[email protected]
   562
        if (level + exprs->length() > MAX_ARRAY_DEPTH) {
[email protected]
   563
            cc_.reportError(pos, Message_MaximumArrayDepth);
[email protected]
   564
            return -1;
[email protected]
   565
        }
[email protected]
   566
[email protected]
   567
        bool hadEmptySize = false;
[email protected]
   568
        for (size_t i = 0; i < exprs->length(); i++) {
[email protected]
   569
            Expression *expr = exprs->at(i);
[email protected]
   570
            if (!expr) {
[email protected]
   571
                dims[i] = INFER_ARRAY_SIZE;
[email protected]
   572
                hadEmptySize = true;
[email protected]
   573
                continue;
[email protected]
   574
            }
[email protected]
   575
[email protected]
   576
            BoxedPrimitive box;
[email protected]
   577
            if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
[email protected]
   578
                int size = box.toInt();
[email protected]
   579
                if (size <= 0) {
[email protected]
   580
                    cc_.reportError(expr->pos(), Message_BadArraySize);
[email protected]
   581
                    return false;
[email protected]
   582
                }
[email protected]
   583
[email protected]
   584
                dims[i] = size;
[email protected]
   585
                continue;
[email protected]
   586
            }
[email protected]
   587
[email protected]
   588
            if (hadEmptySize) {
[email protected]
   589
                cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
[email protected]
   590
                return false;
[email protected]
   591
            }
[email protected]
   592
[email protected]
   593
            dims[i] = EVAL_ARRAY_SIZE;
[email protected]
   594
        }
[email protected]
   595
[email protected]
   596
        return level + exprs->length();
[email protected]
   597
    }
[email protected]
   598
[email protected]
   599
    // This function computes missing dimension sizes based on a literal
[email protected]
   600
    // initializer. We don't really handle any size rules here; we just
[email protected]
   601
    // do a really dumb inference.
[email protected]
   602
    bool inferFixedArrayDimensions(ArrayLiteral *lit, Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], int levels) {
[email protected]
   603
        for (int i = 0; i < levels; i++) {
[email protected]
   604
            if (dims[i] == EVAL_ARRAY_SIZE || dims[i] == DYNAMIC_ARRAY_SIZE) {
[email protected]
   605
                // The following are invalid:
[email protected]
   606
                //   new x[<expr>] = {...}
[email protected]
   607
                //   new Type:x = {...}  // where Type is a non-fixed array type
[email protected]
   608
                cc_.reportError(lit->pos(), Message_CannotInitializeEvalArray);
[email protected]
   609
                return false;
[email protected]
   610
            }
[email protected]
   611
[email protected]
   612
            if (dims[i] == INFER_ARRAY_SIZE) {
[email protected]
   613
                // Character arrays are always dynamic when inferred from string literals.
[email protected]
   614
                if (i == levels - 1 && contained->isChar())
[email protected]
   615
                    dims[i] = DYNAMIC_ARRAY_SIZE;
[email protected]
   616
                else
[email protected]
   617
                    dims[i] = lit->expressions()->length();
[email protected]
   618
            }
[email protected]
   619
[email protected]
   620
            if (i != levels - 1) {
[email protected]
   621
                // Fixed array literals are guaranteed to have at least one expression.
[email protected]
   622
                Expression *next = lit->expressions()->at(0);
[email protected]
   623
                if (!next->isArrayLiteral()) {
[email protected]
   624
                    // Whelp... this array is just malformed. Not the best error message
[email protected]
   625
                    // but whatever.
[email protected]
   626
                    cc_.reportError(next->pos(), Message_ArraySizeCannotBeDetermined);
[email protected]
   627
                    return false;
[email protected]
   628
                }
[email protected]
   629
                lit = next->toArrayLiteral();
[email protected]
   630
            }
[email protected]
   631
        }
[email protected]
   632
[email protected]
   633
        return true;
[email protected]
   634
    }
[email protected]
   635
[email protected]
   636
    ArrayType *buildArrayType(Handle<Type> contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
[email protected]
   637
        Local<Type> type(zone_, contained);
[email protected]
   638
[email protected]
   639
        for (size_t i = postlevels - 1; i < postlevels; i--) {
[email protected]
   640
            int size = dims[i] > 0
[email protected]
   641
                       ? dims[i]
[email protected]
   642
                       : ArrayType::DYNAMIC_ARRAY_SIZE;
[email protected]
   643
            
[email protected]
   644
            if ((type = zone_->types()->newArray(contained, size)) == NULL)
[email protected]
   645
                return NULL;
[email protected]
   646
            if ((type = zone_->types()->qualify(type, quals)) == NULL)
[email protected]
   647
                return NULL;
[email protected]
   648
        }
[email protected]
   649
        return ArrayType::cast(type);
[email protected]
   650
    }
[email protected]
   651
[email protected]
   652
    bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
[email protected]
   653
        Local<Type> type(zone_);
[email protected]
   654
        if (!fun->returnType()) {
[email protected]
   655
            if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL)
[email protected]
   656
                return false;
[email protected]
   657
            fun->setReturnType(type);
[email protected]
   658
        }
[email protected]
   659
[email protected]
   660
        if (sig.variadic())
[email protected]
   661
            fun->setVariadic();
[email protected]
   662
[email protected]
   663
        Local<FixedArray> params(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
[email protected]
   664
        if (!params)
[email protected]
   665
            return false;
[email protected]
   666
[email protected]
   667
        for (size_t i = 0; i < sig.parameters()->length(); i++) {
[email protected]
   668
            Parameter *param = sig.parameters()->at(i);
[email protected]
   669
            if ((type = bindType(param->type(), param->quals())) == NULL)
[email protected]
   670
                return false;
[email protected]
   671
[email protected]
   672
            assert(!type->isArray());
[email protected]
   673
[email protected]
   674
            if (param->dims()) {
[email protected]
   675
                int dims[MAX_ARRAY_DEPTH];
[email protected]
   676
                int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
[email protected]
   677
                if (levels < 0)
[email protected]
   678
                    return false;
[email protected]
   679
[email protected]
   680
                // If we got extra dimensions, we need to build a new type.
[email protected]
   681
                // Unlike variables, we do not infer anything about array
[email protected]
   682
                // sizes from its default initializer.
[email protected]
   683
                if (param->dims()) {
[email protected]
   684
                    if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL)
[email protected]
   685
                        return false;
[email protected]
   686
                }
[email protected]
   687
[email protected]
   688
                if (ArrayType::cast(type)->innermost()->isVoid()) {
[email protected]
   689
                    cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
[email protected]
   690
                    return false;
[email protected]
   691
                }
[email protected]
   692
            }
[email protected]
   693
[email protected]
   694
            if (param->reference()) {
[email protected]
   695
                if (!type->isPod()) {
[email protected]
   696
                    cc_.reportError(param->pos(), Message_ArrayCantBeReference);
[email protected]
   697
                    return false;
[email protected]
   698
                }
[email protected]
   699
                if (param->quals() & TypeQual_Const) {
[email protected]
   700
                    cc_.reportError(param->pos(), Message_CannotConstReference);
[email protected]
   701
                    return false;
[email protected]
   702
                }
[email protected]
   703
                if ((type = zone_->types()->getReference(type, false)) == NULL)
[email protected]
   704
                    return false;
[email protected]
   705
            }
[email protected]
   706
            if (param->quals() & TypeQual_Const) {
[email protected]
   707
                if (!type->isArray() && !type->isStruct()) {
[email protected]
   708
                    cc_.reportError(param->pos(), Message_InvalidConstOnFormal);
[email protected]
   709
                    return false;
[email protected]
   710
                }
[email protected]
   711
            }
[email protected]
   712
[email protected]
   713
            if (type->isVoid()) {
[email protected]
   714
                cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
[email protected]
   715
                return false;
[email protected]
   716
            }
[email protected]
   717
[email protected]
   718
            params->set(zone_, i, type);
[email protected]
   719
            param->sym()->setType(type);
[email protected]
   720
        }
[email protected]
   721
[email protected]
   722
        fun->setParameterTypes(params);
[email protected]
   723
[email protected]
   724
        return true;
[email protected]
   725
    }
[email protected]
   726
[email protected]
   727
    Type *bindType(Expression *expr, TypeQualifiers quals) {
[email protected]
   728
        Local<Type> type(zone_);
[email protected]
   729
[email protected]
   730
        if (!expr) {
[email protected]
   731
            // If no type was declared, we return int32.
[email protected]
   732
            type = zone_->types()->getPrimitive(PrimitiveType_Int32);
[email protected]
   733
        } else {
[email protected]
   734
            expr->accept(this);
[email protected]
   735
[email protected]
   736
            NameProxy *proxy = expr->asNameProxy();
[email protected]
   737
            assert(proxy);
[email protected]
   738
[email protected]
   739
            Symbol *sym = proxy->sym();
[email protected]
   740
            if (!sym)
[email protected]
   741
                return NULL;
[email protected]
   742
[email protected]
   743
            if (!sym->isType()) {
[email protected]
   744
                cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
[email protected]
   745
                return NULL;
[email protected]
   746
            }
[email protected]
   747
[email protected]
   748
            type = sym->type();
[email protected]
   749
        }
[email protected]
   750
[email protected]
   751
        return zone_->types()->qualify(type, quals);
[email protected]
   752
    }
[email protected]
   753
[email protected]
   754
  protected:
[email protected]
   755
    Zone *zone_;
[email protected]
   756
    PoolAllocator &pool_;
[email protected]
   757
    CompileContext &cc_;
[email protected]
   758
    TranslationUnit *unit_;
[email protected]
   759
};
[email protected]
   760
[email protected]
   761
class GlobalBuilder : public NameBinderBase
[email protected]
   762
{
[email protected]
   763
  public:
[email protected]
   764
    GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
   765
      : NameBinderBase(zone, cc, unit)
[email protected]
   766
    {
[email protected]
   767
    }
[email protected]
   768
[email protected]
   769
    Struct *build() {
[email protected]
   770
        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
[email protected]
   771
            unit_->tree()->imports()->at(i)->accept(this);
[email protected]
   772
[email protected]
   773
        // Next, enter the global scope and walk all statements.
[email protected]
   774
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
[email protected]
   775
            Statement *stmt = unit_->tree()->statements()->at(i);
[email protected]
   776
            stmt->accept(this);
[email protected]
   777
        }
[email protected]
   778
[email protected]
   779
        Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
[email protected]
   780
        if (!descs)
[email protected]
   781
            return NULL;
[email protected]
   782
[email protected]
   783
        for (unsigned i = 0; i < descriptors_.length(); i++)
[email protected]
   784
            descs->set(zone_, i, *descriptors_[i]);
[email protected]
   785
[email protected]
   786
        Local<String> name(zone_, unit_->module()->name());
[email protected]
   787
        Local<StructType> type(zone_, StructType::New(zone_, name, descs));
[email protected]
   788
        if (!type)
[email protected]
   789
            return NULL;
[email protected]
   790
[email protected]
   791
        Local<StructMap> map(zone_, type->newMap());
[email protected]
   792
        return Struct::New(zone_, map, Heap::Tenure_Old);
[email protected]
   793
    }
[email protected]
   794
[email protected]
   795
    void visitEnumStatement(EnumStatement *stmt) {
[email protected]
   796
    }
[email protected]
   797
[email protected]
   798
    void visitNameProxy(NameProxy *proxy) {
[email protected]
   799
        // Don't report errors here, since we'll report them later.
[email protected]
   800
        Scope *scope = unit_->globalScope();
[email protected]
   801
        Symbol *sym = scope->lookup(proxy->name());
[email protected]
   802
        proxy->bind(sym);
[email protected]
   803
    }
[email protected]
   804
[email protected]
   805
    void visitFunctionStatement(FunctionStatement *node) {
[email protected]
   806
        Local<FunctionType> type(zone_, node->sym()->type());
[email protected]
   807
        if (!fillFunctionType(type, node->signature()))
[email protected]
   808
            return;
[email protected]
   809
[email protected]
   810
        unsigned offset;
[email protected]
   811
        if (!builder_.add(type, &offset))
[email protected]
   812
            return;
[email protected]
   813
[email protected]
   814
        Descriptor::Visibility visibility = (node->token() == TOK_NATIVE || node->token() == TOK_FORWARD)
[email protected]
   815
                                            ? Descriptor::Public
[email protected]
   816
                                            : Descriptor::Private;
[email protected]
   817
[email protected]
   818
        Descriptor *desc = Descriptor::New(zone_, node->name(), type, visibility);
[email protected]
   819
        if (!desc)
[email protected]
   820
            return;
[email protected]
   821
        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
[email protected]
   822
            return;
[email protected]
   823
    }
[email protected]
   824
[email protected]
   825
    void visitVariableDeclaration(VariableDeclaration *node) {
[email protected]
   826
        Local<Type> type(zone_, buildVariableType(node));
[email protected]
   827
        if (!type)
[email protected]
   828
            return;
[email protected]
   829
[email protected]
   830
        // If we're in global scope, and we received a |const| qualifier, then
[email protected]
   831
        // we extend this to array references as well. This is to sort of mimic
[email protected]
   832
        // SP1 functionality, but also means that you cannot have changeable
[email protected]
   833
        // const pointers in global scope.
[email protected]
   834
        if ((node->quals() & TypeQual_Const) && type->isArray()) {
[email protected]
   835
            if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
[email protected]
   836
                return;
[email protected]
   837
        }
[email protected]
   838
[email protected]
   839
        node->sym()->setType(type);
[email protected]
   840
[email protected]
   841
        unsigned offset;
[email protected]
   842
        if (!builder_.add(type, &offset))
[email protected]
   843
            return;
[email protected]
   844
[email protected]
   845
        Descriptor *desc = Descriptor::New(zone_, node->name(), type, Descriptor::Private);
[email protected]
   846
        if (!desc)
[email protected]
   847
            return;
[email protected]
   848
        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
[email protected]
   849
            return;
[email protected]
   850
    }
[email protected]
   851
[email protected]
   852
    void visitImportStatement(ImportStatement *node) {
[email protected]
   853
        // Eventually we'll handle |from| style imports as well.
[email protected]
   854
        {
[email protected]
   855
            PathComponent *path = node->path();
[email protected]
   856
            while (path->next)
[email protected]
   857
                path = path->next;
[email protected]
   858
[email protected]
   859
            // Imports automatically go into the importScope. For now, we
[email protected]
   860
            // error if there are any duplicate symbols entered into the
[email protected]
   861
            // importScope.
[email protected]
   862
            if (Symbol *sym = unit_->importScope()->localLookup(path->name)) {
[email protected]
   863
                cc_.reportError(node->pos(), Message_DuplicateImport, path->name->chars());
[email protected]
   864
                return;
[email protected]
   865
            }
[email protected]
   866
[email protected]
   867
            Local<Type> type(zone_, zone_->types()->getImportable());
[email protected]
   868
            ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex());
[email protected]
   869
            if (!unit_->importScope()->addSymbol(sym))
[email protected]
   870
                return;
[email protected]
   871
        }
[email protected]
   872
    }
[email protected]
   873
[email protected]
   874
  private:
[email protected]
   875
    StructureBufferBuilder builder_;
[email protected]
   876
    Vector<ScopedRoot<Descriptor> *> descriptors_;
[email protected]
   877
};
[email protected]
   878
    
[email protected]
   879
class NameBinder : public NameBinderBase
[email protected]
   880
{
[email protected]
   881
  public:
[email protected]
   882
    class AutoLinkScope
[email protected]
   883
    {
[email protected]
   884
      public:
[email protected]
   885
        AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
[email protected]
   886
          : prevp_(prevp),
[email protected]
   887
            prev_(*prevp),
[email protected]
   888
            scope_(scope)
[email protected]
   889
        {
[email protected]
   890
            if (scope_) {
[email protected]
   891
                *prevp_ = this;
[email protected]
   892
                if (prev_)
[email protected]
   893
                    scope_->setParent(prev_->scope());
[email protected]
   894
            }
[email protected]
   895
        }
[email protected]
   896
        ~AutoLinkScope() {
[email protected]
   897
            if (scope_) {
[email protected]
   898
                assert(*prevp_ == this);
[email protected]
   899
                *prevp_ = prev_;
[email protected]
   900
            }
[email protected]
   901
        }
[email protected]
   902
        Scope *scope() const {
[email protected]
   903
            return scope_;
[email protected]
   904
        }
[email protected]
   905
[email protected]
   906
      private:
[email protected]
   907
        AutoLinkScope **prevp_;
[email protected]
   908
        AutoLinkScope *prev_;
[email protected]
   909
        Scope *scope_;
[email protected]
   910
    };
[email protected]
   911
[email protected]
   912
  public:
[email protected]
   913
    NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
   914
      : NameBinderBase(zone, cc, unit),
[email protected]
   915
        link_(NULL)
[email protected]
   916
    {
[email protected]
   917
    }
[email protected]
   918
[email protected]
   919
    void bind() {
[email protected]
   920
        // Start with the import scope, and collect all imported names.
[email protected]
   921
        AutoLinkScope importScope(&link_, unit_->importScope());
[email protected]
   922
[email protected]
   923
        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
[email protected]
   924
            unit_->tree()->imports()->at(i)->accept(this);
[email protected]
   925
[email protected]
   926
        // Next, enter the global scope and walk all statements.
[email protected]
   927
        AutoLinkScope globalScope(&link_, unit_->globalScope());
[email protected]
   928
        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
[email protected]
   929
            Statement *stmt = unit_->tree()->statements()->at(i);
[email protected]
   930
            stmt->accept(this);
[email protected]
   931
        }
[email protected]
   932
    }
[email protected]
   933
[email protected]
   934
    void visitVariableDeclaration(VariableDeclaration *node) {
[email protected]
   935
        // Bind the initializer before registering the declaration, so that we
[email protected]
   936
        // can error on bogus initializers (new x = x).
[email protected]
   937
        if (node->initialization())
[email protected]
   938
            node->initialization()->accept(this);
[email protected]
   939
[email protected]
   940
        // If the node already has a symbol (meaning it was a global), then
[email protected]
   941
        // we don't have to do anything more.
[email protected]
   942
        if (node->sym())
[email protected]
   943
            return;
[email protected]
   944
[email protected]
   945
        Local<Type> type(zone_, buildVariableType(node));
[email protected]
   946
        if (!type)
[email protected]
   947
            return;
[email protected]
   948
[email protected]
   949
        VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
[email protected]
   950
        node->setSymbol(sym);
[email protected]
   951
       
[email protected]
   952
        if (Symbol *other = link_->scope()->localLookup(sym->name())) {
[email protected]
   953
            // Report, but allow errors to continue.
[email protected]
   954
            cc_.reportError(sym->pos(), Message_RedeclaredName,
[email protected]
   955
                            sym->name()->chars(),
[email protected]
   956
                            other->pos().line,
[email protected]
   957
                            other->pos().col);
[email protected]
   958
            return;
[email protected]
   959
        }
[email protected]
   960
        
[email protected]
   961
        link_->scope()->addSymbol(sym);
[email protected]
   962
    }
[email protected]
   963
    void visitEnumStatement(EnumStatement *node) {
[email protected]
   964
    }
[email protected]
   965
    void visitFunctionStatement(FunctionStatement *node) {
[email protected]
   966
        AutoLinkScope argScope(&link_, node->argScope());
[email protected]
   967
        AutoLinkScope varScope(&link_, node->varScope());
[email protected]
   968
[email protected]
   969
        // If the function is in the global scope, we've already computed its
[email protected]
   970
        // type.
[email protected]
   971
        if (node->sym()->scope()->kind() != Scope::GLOBAL) {
[email protected]
   972
            Local<FunctionType> type(zone_, node->sym()->type());
[email protected]
   973
            if (!fillFunctionType(type, node->signature()))
[email protected]
   974
                return;
[email protected]
   975
        }
[email protected]
   976
[email protected]
   977
        if (node->body())
[email protected]
   978
            node->body()->accept(this);
[email protected]
   979
    }
[email protected]
   980
    void visitStructureStatement(StructureStatement *node) {
[email protected]
   981
        assert(false);
[email protected]
   982
    }
[email protected]
   983
    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
[email protected]
   984
        assert(false);
[email protected]
   985
    }
[email protected]
   986
[email protected]
   987
    void visitNameProxy(NameProxy *proxy) {
[email protected]
   988
        // We could have already bound globals.
[email protected]
   989
        if (proxy->sym())
[email protected]
   990
            return;
[email protected]
   991
[email protected]
   992
        Scope *scope = link_->scope();
[email protected]
   993
        Symbol *sym = scope->lookup(proxy->name());
[email protected]
   994
        if (!sym)
[email protected]
   995
            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
[email protected]
   996
        proxy->bind(sym);
[email protected]
   997
    }
[email protected]
   998
    void visitAssignment(Assignment *node) {
[email protected]
   999
        node->lvalue()->accept(this);
[email protected]
  1000
        node->expression()->accept(this);
[email protected]
  1001
    }
[email protected]
  1002
    void visitBinaryExpression(BinaryExpression *node) {
[email protected]
  1003
        node->left()->accept(this);
[email protected]
  1004
        node->right()->accept(this);
[email protected]
  1005
    }
[email protected]
  1006
    void visitReturnStatement(ReturnStatement *node) {
[email protected]
  1007
        node->expression()->accept(this);
[email protected]
  1008
    }
[email protected]
  1009
    void visitForStatement(ForStatement *node) {
[email protected]
  1010
        AutoLinkScope scope(&link_, node->scope());
[email protected]
  1011
[email protected]
  1012
        if (node->initialization())
[email protected]
  1013
            node->initialization()->accept(this);
[email protected]
  1014
        if (node->condition())
[email protected]
  1015
            node->condition()->accept(this);
[email protected]
  1016
        if (node->update())
[email protected]
  1017
            node->update()->accept(this);
[email protected]
  1018
        node->body()->accept(this);
[email protected]
  1019
    }
[email protected]
  1020
    void visitBlockStatement(BlockStatement *node) {
[email protected]
  1021
        AutoLinkScope scope(&link_, node->scope());
[email protected]
  1022
        for (size_t i = 0; i < node->statements()->length(); i++)
[email protected]
  1023
            node->statements()->at(i)->accept(this);
[email protected]
  1024
    }
[email protected]
  1025
    void visitIntegerLiteral(IntegerLiteral *node) {
[email protected]
  1026
    }
[email protected]
  1027
    void visitExpressionStatement(ExpressionStatement *node) {
[email protected]
  1028
        node->expression()->accept(this);
[email protected]
  1029
    }
[email protected]
  1030
    void visitCallExpression(CallExpression *node) {
[email protected]
  1031
        node->callee()->accept(this);
[email protected]
  1032
        for (size_t i = 0; i < node->arguments()->length(); i++)
[email protected]
  1033
            node->arguments()->at(i)->accept(this);
[email protected]
  1034
    }
[email protected]256
  1035
    void visitIfStatement(IfStatement *node) {
[email protected]
  1036
        node->condition()->accept(this);
[email protected]
  1037
        node->ifTrue()->accept(this);
[email protected]
  1038
        if (node->ifFalse())
[email protected]
  1039
            node->ifFalse()->accept(this);
[email protected]
  1040
    }
[email protected]
  1041
    void visitIndexExpression(IndexExpression *node) {
[email protected]
  1042
        node->left()->accept(this);
[email protected]
  1043
        node->right()->accept(this);
[email protected]
  1044
    }
[email protected]
  1045
    void visitFloatLiteral(FloatLiteral *node) {
[email protected]
  1046
    }
[email protected]
  1047
    void visitWhileStatement(WhileStatement *node) {
[email protected]
  1048
        node->condition()->accept(this);
[email protected]
  1049
        node->body()->accept(this);
[email protected]
  1050
    }
[email protected]
  1051
    void visitBreakStatement(BreakStatement *node) {
[email protected]
  1052
    }
[email protected]
  1053
    void visitContinueStatement(ContinueStatement *node) {
[email protected]
  1054
    }
[email protected]
  1055
    void visitStringLiteral(StringLiteral *node) {
[email protected]
  1056
    }
[email protected]
  1057
    void visitIncDecExpression(IncDecExpression *node) {
[email protected]
  1058
        node->expression()->accept(this);
[email protected]
  1059
    }
[email protected]
  1060
    void visitUnaryExpression(UnaryExpression *node) {
[email protected]
  1061
        if (node->tag())
[email protected]
  1062
            node->tag()->accept(this);
[email protected]
  1063
        node->expression()->accept(this);
[email protected]
  1064
    }
[email protected]
  1065
    void visitTernaryExpression(TernaryExpression *node) {
[email protected]
  1066
        node->condition()->accept(this);
[email protected]
  1067
        node->left()->accept(this);
[email protected]
  1068
        node->right()->accept(this);
[email protected]
  1069
    }
[email protected]
  1070
    void visitBooleanLiteral(BooleanLiteral *node) {
[email protected]
  1071
    }
[email protected]
  1072
    void visitFieldExpression(FieldExpression *node) {
[email protected]56
  1073
        node->left()->accept(this);
[email protected]
  1074
    }
[email protected]
  1075
    void visitSwitchStatement(SwitchStatement *node) {
[email protected]
  1076
        node->expression()->accept(this);
[email protected]
  1077
        node->defaultCase()->accept(this);
[email protected]
  1078
        for (size_t i = 0; i < node->cases()->length(); i++) {
[email protected]
  1079
            // We don't test case expressions because they are literals.
[email protected]
  1080
            Case *c = node->cases()->at(i);
[email protected]
  1081
            c->statement()->accept(this);
[email protected]
  1082
        }
[email protected]
  1083
    }
[email protected]
  1084
    void visitArrayLiteral(ArrayLiteral *node) {
[email protected]
  1085
        for (size_t i = 0; i < node->expressions()->length(); i++)
[email protected]
  1086
            node->expressions()->at(i)->accept(this);
[email protected]
  1087
    }
[email protected]
  1088
    void visitImportStatement(ImportStatement *node) {
[email protected]
  1089
    }
[email protected]
  1090
[email protected]
  1091
  private:
[email protected]
  1092
    AutoLinkScope *link_;
[email protected]
  1093
};
[email protected]
  1094
[email protected]
  1095
void
[email protected]
  1096
ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
[email protected]
  1097
{
[email protected]
  1098
    AutoEnterCompileContext enter(cc, unit);
[email protected]
  1099
[email protected]
  1100
    // Because of the way globals work in Pawn, we need a precursor step to
[email protected]
  1101
    // actually enter global symbols into the global struct. They're already
[email protected]
  1102
    // in the global symbol table, so we know they won't clash. This process
[email protected]
  1103
    // also binds any remaining types on global variables.
[email protected]
  1104
    GlobalBuilder builder(zone, cc, unit);
[email protected]
  1105
    Local<Struct> globals(zone, builder.build());
[email protected]
  1106
    if (!globals || unit->failed())
[email protected]
  1107
        return;
[email protected]
  1108
[email protected]
  1109
    unit->module()->setGlobals(globals);
[email protected]
  1110
[email protected]
  1111
    NameBinder binder(zone, cc, unit);
[email protected]
  1112
    binder.bind();
[email protected]
  1113
}