}
void ModFileWriter::WriteOne(const Scope &scope) {
- auto *symbol{scope.symbol()};
- if (scope.kind() != Scope::Kind::Module) {
+ if (scope.kind() == Scope::Kind::Module) {
+ auto *symbol{scope.symbol()};
+ if (!symbol->test(Symbol::Flag::ModFile)) {
+ Write(*symbol);
+ }
+ WriteChildren(scope); // write out submodules
+ }
+}
+
+// Write the module file for symbol, which must be a module or submodule.
+void ModFileWriter::Write(const Symbol &symbol) {
+ auto *ancestor{symbol.get<ModuleDetails>().ancestor()};
+ auto ancestorName{ancestor ? ancestor->name().ToString() : ""s};
+ auto path{ModFilePath(dir_, symbol.name(), ancestorName)};
+ unlink(path.data());
+ std::ofstream os{path};
+ PutSymbols(*symbol.scope());
+ std::string all{GetAsString(symbol)};
+ auto header{GetHeader(all)};
+ os << header << all;
+ os.close();
+ if (!os) {
+ errors_.emplace_back(
+ "Error writing %s: %s"_err_en_US, path.c_str(), std::strerror(errno));
return;
}
- if (!symbol->test(Symbol::Flag::ModFile)) {
- auto *ancestor{symbol->get<ModuleDetails>().ancestor()};
- auto ancestorName{ancestor ? ancestor->name().ToString() : ""s};
- auto path{ModFilePath(dir_, symbol->name(), ancestorName)};
- unlink(path.data());
- std::ofstream os{path};
- PutSymbols(scope);
- std::string all{GetAsString(*symbol)};
- auto header{GetHeader(all)};
- os << header << all;
- os.close();
- if (!os) {
- errors_.emplace_back(
- "Error writing %s: %s"_err_en_US, path.c_str(), std::strerror(errno));
- return;
- }
- if (!MakeReadonly(path)) {
- errors_.emplace_back("Error changing permissions on %s: %s"_en_US,
- path.c_str(), std::strerror(errno));
- }
+ if (!MakeReadonly(path)) {
+ errors_.emplace_back("Error changing permissions on %s: %s"_en_US,
+ path.c_str(), std::strerror(errno));
}
- WriteChildren(scope); // write out submodules
}
// Return the entire body of the module file
name.ToString(), *path));
return nullptr;
}
- Scope *parentScope;
+ Scope *parentScope; // the scope this module/submodule goes into
if (!ancestor) {
- // module: goes into global scope
parentScope = &Scope::globalScope;
+ } else if (auto *parent{GetSubmoduleParent(*parseTree)}) {
+ parentScope = Read(*parent, ancestor);
} else {
- // submodule: goes into parent module/submodule
- auto *parent{GetSubmoduleParent(*parseTree)};
- parentScope = parent ? Read(*parent, ancestor) : ancestor;
+ parentScope = ancestor;
}
ResolveNames(*parentScope, *parseTree, parsing.cooked(), directories_);
const auto &it{parentScope->find(name)};
const SourceName &useName);
Symbol &BeginModule(const SourceName &, bool isSubmodule,
const std::optional<parser::ModuleSubprogramPart> &);
- Scope *FindModule(const SourceName &, Scope * = nullptr);
+ Scope *FindModule(const SourceName &, Scope *ancestor = nullptr);
};
class InterfaceVisitor : public virtual ScopeHandler {
}
PushScope(*parentScope); // submodule is hosted in parent
auto &symbol{BeginModule(name, true, subpPart)};
- if (ancestor->AddSubmodule(name, &CurrScope())) {
+ if (!ancestor->AddSubmodule(name, &CurrScope())) {
Say(name, "Module '%s' already has a submodule named '%s'"_err_en_US,
ancestorName, name);
}