TEST(TestDeclaration, testImportKind_Var) { PARSE_STATEMENT(L"import var Foundation.NSFileManager"); ImportPtr import; ASSERT_NOT_NULL(import = std::dynamic_pointer_cast<Import>(root)); ASSERT_EQ(L"Foundation.NSFileManager", import->getPath()); ASSERT_EQ(Import::Var, import->getKind()); }
TEST(TestDeclaration, testImportSubModule) { PARSE_STATEMENT(L"import Foundation.SubModule"); ImportPtr import; ASSERT_NOT_NULL(import = std::dynamic_pointer_cast<Import>(root)); ASSERT_EQ(L"Foundation.SubModule", import->getPath()); ASSERT_EQ(Import::_, import->getKind()); }
void loadDependent(ModulePtr m, vector<string> *sourceFiles, ImportPtr dependent, bool verbose) { ImportPtr x = dependent; x->module = loadModuleByName(x->dottedName, sourceFiles, verbose); switch (x->importKind) { case IMPORT_MODULE : { ImportModule *im = (ImportModule *)x.ptr(); IdentifierPtr name = NULL; if (im->alias.ptr()) { name = im->alias; m->importedModuleNames[im->alias->str].module = x->module; } else { llvm::ArrayRef<IdentifierPtr> parts = im->dottedName->parts; if (parts.size() == 1) name = parts[0]; else if (x->visibility == PUBLIC) error(x->location, "public imports of dotted module paths must have an \"as <name>\" alias"); llvm::StringMap<ModuleLookup> *node = &m->importedModuleNames; for (size_t i = parts.size() - 1; i >= 1; --i) { node = &(*node)[parts[i]->str].parents; } (*node)[parts[0]->str].module = x->module; } if (name.ptr()) { string nameStr(name->str.begin(), name->str.end()); if (m->importedNames.count(nameStr)) error(name, "name imported already: " + nameStr); m->importedNames.insert(nameStr); m->allSymbols[nameStr].insert(x->module.ptr()); if (x->visibility == PUBLIC) m->publicSymbols[nameStr].insert(x->module.ptr()); } break; } case IMPORT_STAR : break; case IMPORT_MEMBERS : { ImportMembers *y = (ImportMembers *)x.ptr(); for (unsigned i = 0; i < y->members.size(); ++i) { ImportedMember &z = y->members[i]; IdentifierPtr alias = z.alias.ptr() ? z.alias : z.name; string aliasStr(alias->str.begin(), alias->str.end()); if (m->importedNames.count(aliasStr)) error(alias, "name imported already: " + aliasStr); assert(y->aliasMap.count(aliasStr) == 0); m->importedNames.insert(aliasStr); y->aliasMap[aliasStr] = z.name; } break; } default : assert(false); } }
/* GRAMMAR OF AN IMPORT DECLARATION import-declaration → attributesoptimportimport-kindoptimport-path import-kind → typealias struct class enum protocol var func import-path → import-path-identifier | import-path-identifier.import-path import-path-identifier → identifier | operator” */ DeclarationPtr Parser::parseImport(const std::vector<AttributePtr>& attrs) { Token token; expect(Keyword::Import, token); ImportPtr ret = nodeFactory->createImport(token.state); ret->setAttributes(attrs); expect_next(token); tassert(token, token.type == TokenType::Identifier, Errors::E_EXPECT_IDENTIFIER_1, token.token); Import::Kind kind = Import::_; switch(token.identifier.keyword) { case Keyword::_: restore(token); break; case Keyword::Typealias: kind = Import::Typealias; break; case Keyword::Struct: kind = Import::Struct; break; case Keyword::Class: kind = Import::Class; break; case Keyword::Enum: kind = Import::Enum; break; case Keyword::Protocol: kind = Import::Protocol; break; case Keyword::Var: kind = Import::Var; break; case Keyword::Func: kind = Import::Func; break; default: unexpected(token); break; } std::wstring path; int n = 0; do { expect_next(token); if(token.type != TokenType::Identifier && token.type != TokenType::Operator) unexpected(token); if(n) path += L"."; path += token.token; n++; } while (match(L".")); ret->setPath(path); ret->setKind(kind); return ret; }
static void loadDependents(ModulePtr m, vector<string> *sourceFiles) { m->rootHolder = new ModuleHolder(); m->publicRootHolder = new ModuleHolder(); vector<ImportPtr>::iterator ii, iend; for (ii = m->imports.begin(), iend = m->imports.end(); ii != iend; ++ii) { ImportPtr x = *ii; x->module = loadModuleByName(x->dottedName, sourceFiles); switch (x->importKind) { case IMPORT_MODULE : { ImportModule *y = (ImportModule *)x.ptr(); { ModuleHolderPtr holder = m->rootHolder; if (y->alias.ptr()) { holder = installHolder(holder, y->alias); } else { vector<IdentifierPtr> &parts = y->dottedName->parts; for (unsigned i = 0; i < parts.size(); ++i) holder = installHolder(holder, parts[i]); } if (holder->import.ptr()) error(x, "module already imported"); holder->import = y; } if (y->visibility == PUBLIC) { ModuleHolderPtr holder = m->publicRootHolder; if (y->alias.ptr()) { holder = installHolder(holder, y->alias); } else { vector<IdentifierPtr> &parts = y->dottedName->parts; for (unsigned i = 0; i < parts.size(); ++i) holder = installHolder(holder, parts[i]); } if (holder->import.ptr()) error(x, "module already imported"); holder->import = y; } break; } case IMPORT_STAR : { break; } case IMPORT_MEMBERS : { ImportMembers *y = (ImportMembers *)x.ptr(); for (unsigned i = 0; i < y->members.size(); ++i) { ImportedMember &z = y->members[i]; IdentifierPtr alias = z.alias; if (!alias) alias = z.name; if (y->aliasMap.count(alias->str)) error(alias, "name imported already: " + alias->str); y->aliasMap[alias->str] = z.name; } break; } default : assert(false); } } }