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