summaryrefslogtreecommitdiff
path: root/src/core/parser/ParserScope.cpp
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-29 03:26:53 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-29 03:26:53 +0100
commit1a831356eee562451c8ce85654ec3b650658e7f9 (patch)
tree6c58fa339fc1043d9f19c434fd07da4e1227f942 /src/core/parser/ParserScope.cpp
parentcf493215beb33c427a0687d56b1e18d8e6f85586 (diff)
ParserScope now stores the nodes for which the resolution was triggered and first executes those resolutions that depend on not currently resolving nodes (this behaviour is needed for the resolution of constants).
Diffstat (limited to 'src/core/parser/ParserScope.cpp')
-rw-r--r--src/core/parser/ParserScope.cpp71
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;