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