src/compiler/NameBinding.cpp
changeset 258 241d082d6d89
parent 257 9db4cc815ebc
child 259 99ab8b19f0b9
     1.1 --- a/src/compiler/NameBinding.cpp	Sun Jan 06 13:56:56 2013 -0800
     1.2 +++ b/src/compiler/NameBinding.cpp	Sat Jan 12 16:13:46 2013 -0800
     1.3 @@ -217,6 +217,11 @@
     1.4              TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
     1.5              if (!registerName(scope, sym))
     1.6                  return;
     1.7 +
     1.8 +            if (scope->kind() == Scope::GLOBAL) {
     1.9 +                if (!unit_->globalScope()->exported()->append(sym))
    1.10 +                    return;
    1.11 +            }
    1.12          }
    1.13  
    1.14          int value = 0;
    1.15 @@ -236,6 +241,10 @@
    1.16              ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
    1.17              if (!registerName(scope, sym))
    1.18                  return;
    1.19 +            if (scope->kind() == Scope::GLOBAL) {
    1.20 +                if (!unit_->globalScope()->exported()->append(sym))
    1.21 +                    return;
    1.22 +            }
    1.23  
    1.24              value++;
    1.25          }
    1.26 @@ -262,6 +271,9 @@
    1.27          {
    1.28              // We're in the global scope, for sure.
    1.29              assert(env_->scope()->kind() == Scope::GLOBAL);
    1.30 +
    1.31 +            if (!unit_->globalScope()->exported()->append(sym))
    1.32 +                return;
    1.33          }
    1.34  
    1.35          node->setSymbol(sym);
    1.36 @@ -504,7 +516,6 @@
    1.37      {
    1.38      }
    1.39  
    1.40 -
    1.41    protected:
    1.42      Type *buildVariableType(VariableDeclaration *node) {
    1.43          Local<Type> type(zone_, bindType(node->type(), node->quals()));
    1.44 @@ -762,7 +773,8 @@
    1.45  {
    1.46    public:
    1.47      GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    1.48 -      : NameBinderBase(zone, cc, unit)
    1.49 +      : NameBinderBase(zone, cc, unit),
    1.50 +        globalScope_(unit->globalScope())
    1.51      {
    1.52      }
    1.53  
    1.54 @@ -796,9 +808,10 @@
    1.55      }
    1.56  
    1.57      void visitNameProxy(NameProxy *proxy) {
    1.58 -        // Don't report errors here, since we'll report them later.
    1.59          Scope *scope = unit_->globalScope();
    1.60          Symbol *sym = scope->lookup(proxy->name());
    1.61 +        if (!sym)
    1.62 +            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
    1.63          proxy->bind(sym);
    1.64      }
    1.65  
    1.66 @@ -850,8 +863,7 @@
    1.67      }
    1.68  
    1.69      void visitImportStatement(ImportStatement *node) {
    1.70 -        // Eventually we'll handle |from| style imports as well.
    1.71 -        {
    1.72 +        if (!node->names()) {
    1.73              PathComponent *path = node->path();
    1.74              while (path->next)
    1.75                  path = path->next;
    1.76 @@ -868,12 +880,48 @@
    1.77              ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex());
    1.78              if (!unit_->importScope()->addSymbol(sym))
    1.79                  return;
    1.80 +        } else if (node->importAllNames()) {
    1.81 +            Local<Importable> importable(zone_, unit_->module()->getImportAt(node->importIndex()));
    1.82 +            if (importable->isPackage()) {
    1.83 +                assert(false);
    1.84 +            } else {
    1.85 +                Local<Module> module(zone_, Module::cast(importable));
    1.86 +                if (!module->globals())
    1.87 +                    importAllFromTranslationUnit(node, module, module->translationUnit());
    1.88 +                else
    1.89 +                    assert(false);
    1.90 +            }
    1.91 +        }
    1.92 +    }
    1.93 +
    1.94 +  private:
    1.95 +    void importAllFromTranslationUnit(ImportStatement *node, Handle<Module> module, TranslationUnit *other) {
    1.96 +        assert(!other->failed());
    1.97 +
    1.98 +        for (size_t i = 0; i < other->globalScope()->exported()->length(); i++) {
    1.99 +            Symbol *import = other->globalScope()->exported()->at(i);
   1.100 +            assert(import->type());
   1.101 +
   1.102 +            // Check for duplicate import names.
   1.103 +            if (unit_->importScope()->localLookup(import->name())) {
   1.104 +                cc_.reportError(node->pos(), Message_DuplicateImport, import->name()->chars());
   1.105 +                return;
   1.106 +            }
   1.107 +
   1.108 +            ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   1.109 +                                                         import->name(),
   1.110 +                                                         node->pos(),
   1.111 +                                                         import->type(),
   1.112 +                                                         node->importIndex());
   1.113 +            if (!unit_->importScope()->addSymbol(sym))
   1.114 +                return;
   1.115          }
   1.116      }
   1.117  
   1.118    private:
   1.119      StructureBufferBuilder builder_;
   1.120      Vector<ScopedRoot<Descriptor> *> descriptors_;
   1.121 +    GlobalScope *globalScope_;
   1.122  };
   1.123      
   1.124  class NameBinder : public NameBinderBase
   1.125 @@ -1093,21 +1141,22 @@
   1.126  };
   1.127  
   1.128  void
   1.129 -ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   1.130 +ke::BindGlobals(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   1.131  {
   1.132      AutoEnterCompileContext enter(cc, unit);
   1.133  
   1.134 -    // Because of the way globals work in Pawn, we need a precursor step to
   1.135 -    // actually enter global symbols into the global struct. They're already
   1.136 -    // in the global symbol table, so we know they won't clash. This process
   1.137 -    // also binds any remaining types on global variables.
   1.138      GlobalBuilder builder(zone, cc, unit);
   1.139      Local<Struct> globals(zone, builder.build());
   1.140      if (!globals || unit->failed())
   1.141          return;
   1.142  
   1.143      unit->module()->setGlobals(globals);
   1.144 +}
   1.145  
   1.146 +void
   1.147 +ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   1.148 +{
   1.149 +    AutoEnterCompileContext enter(cc, unit);
   1.150      NameBinder binder(zone, cc, unit);
   1.151      binder.bind();
   1.152  }