diff -r 9db4cc815ebc -r 241d082d6d89 src/compiler/NameBinding.cpp --- a/src/compiler/NameBinding.cpp Sun Jan 06 13:56:56 2013 -0800 +++ b/src/compiler/NameBinding.cpp Sat Jan 12 16:13:46 2013 -0800 @@ -217,6 +217,11 @@ TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type); if (!registerName(scope, sym)) return; + + if (scope->kind() == Scope::GLOBAL) { + if (!unit_->globalScope()->exported()->append(sym)) + return; + } } int value = 0; @@ -236,6 +241,10 @@ ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box); if (!registerName(scope, sym)) return; + if (scope->kind() == Scope::GLOBAL) { + if (!unit_->globalScope()->exported()->append(sym)) + return; + } value++; } @@ -262,6 +271,9 @@ { // We're in the global scope, for sure. assert(env_->scope()->kind() == Scope::GLOBAL); + + if (!unit_->globalScope()->exported()->append(sym)) + return; } node->setSymbol(sym); @@ -504,7 +516,6 @@ { } - protected: Type *buildVariableType(VariableDeclaration *node) { Local type(zone_, bindType(node->type(), node->quals())); @@ -762,7 +773,8 @@ { public: GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit) - : NameBinderBase(zone, cc, unit) + : NameBinderBase(zone, cc, unit), + globalScope_(unit->globalScope()) { } @@ -796,9 +808,10 @@ } void visitNameProxy(NameProxy *proxy) { - // Don't report errors here, since we'll report them later. Scope *scope = unit_->globalScope(); Symbol *sym = scope->lookup(proxy->name()); + if (!sym) + cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars()); proxy->bind(sym); } @@ -850,8 +863,7 @@ } void visitImportStatement(ImportStatement *node) { - // Eventually we'll handle |from| style imports as well. - { + if (!node->names()) { PathComponent *path = node->path(); while (path->next) path = path->next; @@ -868,12 +880,48 @@ ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex()); if (!unit_->importScope()->addSymbol(sym)) return; + } else if (node->importAllNames()) { + Local importable(zone_, unit_->module()->getImportAt(node->importIndex())); + if (importable->isPackage()) { + assert(false); + } else { + Local module(zone_, Module::cast(importable)); + if (!module->globals()) + importAllFromTranslationUnit(node, module, module->translationUnit()); + else + assert(false); + } + } + } + + private: + void importAllFromTranslationUnit(ImportStatement *node, Handle module, TranslationUnit *other) { + assert(!other->failed()); + + for (size_t i = 0; i < other->globalScope()->exported()->length(); i++) { + Symbol *import = other->globalScope()->exported()->at(i); + assert(import->type()); + + // Check for duplicate import names. + if (unit_->importScope()->localLookup(import->name())) { + cc_.reportError(node->pos(), Message_DuplicateImport, import->name()->chars()); + return; + } + + ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(), + import->name(), + node->pos(), + import->type(), + node->importIndex()); + if (!unit_->importScope()->addSymbol(sym)) + return; } } private: StructureBufferBuilder builder_; Vector *> descriptors_; + GlobalScope *globalScope_; }; class NameBinder : public NameBinderBase @@ -1093,21 +1141,22 @@ }; void -ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit) +ke::BindGlobals(Zone *zone, CompileContext &cc, TranslationUnit *unit) { AutoEnterCompileContext enter(cc, unit); - // Because of the way globals work in Pawn, we need a precursor step to - // actually enter global symbols into the global struct. They're already - // in the global symbol table, so we know they won't clash. This process - // also binds any remaining types on global variables. GlobalBuilder builder(zone, cc, unit); Local globals(zone, builder.build()); if (!globals || unit->failed()) return; unit->module()->setGlobals(globals); +} +void +ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit) +{ + AutoEnterCompileContext enter(cc, unit); NameBinder binder(zone, cc, unit); binder.bind(); }