diff options
Diffstat (limited to 'src/core/parser/ParserScope.cpp')
-rw-r--r-- | src/core/parser/ParserScope.cpp | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp index 2bacf10..0de0dbf 100644 --- a/src/core/parser/ParserScope.cpp +++ b/src/core/parser/ParserScope.cpp @@ -64,28 +64,37 @@ DeferredResolution::DeferredResolution(const NodeVector<Node> &nodes, const std::vector<std::string> &path, const Rtti &type, ResolutionResultCallback resultCallback, - const SourceLocation &location) + Handle<Node> owner) : scope(nodes), resultCallback(resultCallback), path(path), type(type), - location(location) + owner(owner) { } -bool DeferredResolution::resolve(Logger &logger) +bool DeferredResolution::resolve( + const std::unordered_multiset<const Node *> &ignore, Logger &logger) { - Rooted<Node> res = scope.resolve(path, type, logger); + // Fork the logger to prevent error messages from being shown if we actively + // ignore the resolution result + LoggerFork loggerFork = logger.fork(); + Rooted<Node> res = scope.resolve(path, type, loggerFork); if (res != nullptr) { - try { - // Push the location onto the logger default location stack - GuardedLogger localLogger(logger, location); - resultCallback(res, localLogger); - } - catch (LoggableException ex) { - logger.log(ex); + if (!ignore.count(res.get())) { + loggerFork.commit(); + try { + // Push the location onto the logger default location stack + GuardedLogger loggerGuard(logger, *owner); + resultCallback(res, logger); + } + catch (LoggableException ex) { + logger.log(ex); + } + return true; } - return true; + } else { + loggerFork.commit(); } return false; } @@ -111,7 +120,7 @@ bool ParserScope::checkUnwound(Logger &logger) const logger.note(std::string("Element of interal type ") + nodes[i]->type().name + std::string(" defined here:"), - nodes[i]->getLocation()); + *nodes[i]); } return false; } @@ -130,6 +139,8 @@ bool ParserScope::join(const ParserScope &fork, Logger &logger) // Insert the deferred resolutions of the fork into our own deferred // resolution list deferred.insert(deferred.end(), fork.deferred.begin(), fork.deferred.end()); + awaitingResolution.insert(fork.awaitingResolution.begin(), + fork.awaitingResolution.end()); return true; } @@ -220,9 +231,9 @@ bool ParserScope::resolve(const std::vector<std::string> &path, const Rtti &type, Logger &logger, ResolutionImposterCallback imposterCallback, ResolutionResultCallback resultCallback, - const SourceLocation &location) + Handle<Node> owner) { - if (!resolve(path, type, logger, resultCallback, location)) { + if (!resolve(path, type, logger, resultCallback, owner)) { resultCallback(imposterCallback(), logger); return false; } @@ -232,19 +243,26 @@ bool ParserScope::resolve(const std::vector<std::string> &path, bool ParserScope::resolve(const std::vector<std::string> &path, const Rtti &type, Logger &logger, ResolutionResultCallback resultCallback, - const SourceLocation &location) + Handle<Node> owner) { + // Try to directly resolve the node Rooted<Node> res = ParserScopeBase::resolve(path, type, logger); - if (res != nullptr) { + if (res != nullptr && !awaitingResolution.count(res.get())) { try { resultCallback(res, logger); } catch (LoggableException ex) { - logger.log(ex, location); + logger.log(ex, *owner); } return true; } - deferred.emplace_back(nodes, path, type, resultCallback, location); + + // Mark the owner as "awaitingResolution", preventing it from being returned + // as resolution result + if (owner != nullptr) { + awaitingResolution.insert(owner.get()); + } + deferred.emplace_back(nodes, path, type, resultCallback, owner); return false; } @@ -256,7 +274,10 @@ bool ParserScope::performDeferredResolution(Logger &logger) // Iterate over all deferred resolution processes, bool hasChange = false; for (auto it = deferred.begin(); it != deferred.end();) { - if (it->resolve(logger)) { + if (it->resolve(awaitingResolution, logger)) { + if (it->owner != nullptr) { + awaitingResolution.erase(it->owner.get()); + } it = deferred.erase(it); hasChange = true; } else { @@ -266,7 +287,13 @@ bool ParserScope::performDeferredResolution(Logger &logger) // Abort if nothing has changed in the last iteration if (!hasChange) { - break; + // In a last step, clear the "awaitingResolution" list to allow + // cyclical dependencies to be resolved + if (!awaitingResolution.empty()) { + awaitingResolution.clear(); + } else { + break; + } } } @@ -281,7 +308,7 @@ bool ParserScope::performDeferredResolution(Logger &logger) logger.error(std::string("Could not resolve ") + failed.type.name + std::string(" \"") + Utils::join(failed.path, ".") + std::string("\""), - failed.location); + *failed.owner); } deferred.clear(); return false; |