summaryrefslogtreecommitdiff
path: root/src/core/parser
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-30 14:42:06 +0100
committerAndreas Stöckel <andreas@somweyr.de>2015-01-30 14:42:06 +0100
commit729ea17ed17cf81eb19847216406e40686df679d (patch)
tree8636b0f3f39887f64047ee19f3d823dfbcf31426 /src/core/parser
parent0ba26c258b9c834894de34e7e14a9fdc774988a5 (diff)
Finished implementing constant importing
Diffstat (limited to 'src/core/parser')
-rw-r--r--src/core/parser/ParserScope.cpp135
-rw-r--r--src/core/parser/ParserScope.hpp37
2 files changed, 75 insertions, 97 deletions
diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp
index c7a9f2a..efd07d1 100644
--- a/src/core/parser/ParserScope.cpp
+++ b/src/core/parser/ParserScope.cpp
@@ -18,6 +18,7 @@
#include <core/common/Exceptions.hpp>
#include <core/common/Utils.hpp>
+#include <core/common/VariantWriter.hpp>
#include <core/model/Typesystem.hpp>
#include "ParserScope.hpp"
@@ -319,6 +320,44 @@ bool ParserScope::resolveType(const std::string &name, Handle<Node> owner,
return resolveType(Utils::split(name, '.'), owner, logger, resultCallback);
}
+bool ParserScope::resolveValue(Variant &data, Handle<Type> type,
+ Handle<Node> owner, Logger &logger)
+{
+ return type->build(
+ data, logger,
+ [&](Variant &innerData,
+ const Type *innerType) mutable -> Type::MagicCallbackResult {
+ // Try to resolve the node
+ Rooted<Constant> constant =
+ ParserScopeBase::resolve(RttiTypes::Constant,
+ Utils::split(innerData.asMagic(), '.'),
+ logger).cast<Constant>();
+
+ // Abort if nothing was found
+ if (constant == nullptr) {
+ return Type::MagicCallbackResult::NOT_FOUND;
+ }
+
+ // Set the data to the value of the constant
+ innerData = constant->getValue();
+
+ // Check whether the inner type of the constant is correct
+ // TODO: Use correct "isa" provided by Type
+ Rooted<Type> constantType = constant->getType();
+ if (innerType != constantType) {
+ logger.error(std::string("Expected value of type \"") +
+ innerType->getName() +
+ std::string("\" but found constant \"") +
+ constant->getName() +
+ std::string("\" of type \"") +
+ constantType->getName() + "\" instead.",
+ *owner);
+ return Type::MagicCallbackResult::FOUND_INVALID;
+ }
+ return Type::MagicCallbackResult::FOUND_VALID;
+ });
+}
+
bool ParserScope::resolveTypeWithValue(const std::vector<std::string> &path,
Handle<Node> owner, Variant &value,
Logger &logger,
@@ -326,90 +365,20 @@ bool ParserScope::resolveTypeWithValue(const std::vector<std::string> &path,
{
// Fork the parser scope -- constants need to be resolved in the same
// context as this resolve call
- std::shared_ptr<ParserScope> scope = std::make_shared<ParserScope>(fork());
-
- return resolveType(
- path, owner, logger,
- [=](Handle<Node> resolved, Handle<Node> owner, Logger &logger) mutable {
- // Abort if the lookup failed
- if (resolved == nullptr) {
- resultCallback(resolved, owner, logger);
- return;
- }
-
- // Fetch the type reference and the manager reference
- Rooted<Type> type = resolved.cast<Type>();
- Manager *mgr = &type->getManager();
-
- // The type has been resolved, try to resolve magic values as
- // constants and postpone calling the callback function until
- // all magic values have been resolved
- std::shared_ptr<bool> isAsync = std::make_shared<bool>(false);
- std::shared_ptr<int> magicCount = std::make_shared<int>(0);
- type->build(value, logger, [=](Variant &magicValue, bool isValid,
- ManagedUid innerTypeUid) mutable {
- // Fetch the inner type
- Rooted<Type> innerType =
- dynamic_cast<Type *>(mgr->getManaged(innerTypeUid));
- if (innerType == nullptr) {
- return;
- }
-
- // Fetch a pointer at the variant
- Variant *magicValuePtr = &magicValue;
-
- // Increment the number of encountered magic values
- (*magicCount)++;
-
- // Try to resolve the value as constant
- std::string constantName = magicValue.asMagic();
- scope->resolve<Constant>(constantName, owner, logger,
- [=](Handle<Node> resolved,
- Handle<Node> owner,
- Logger &logger) mutable {
- if (resolved != nullptr) {
- // Make sure the constant is of the correct inner type
- Rooted<Constant> constant = resolved.cast<Constant>();
- Rooted<Type> constantType = constant->getType();
- if (constantType != innerType) {
- logger.error(
- std::string("Expected value of type \"") +
- innerType->getName() +
- std::string("\" but found constant \"") +
- constant->getName() +
- std::string(" of type \"") +
- constantType->getName() + "\" instead.",
- *owner);
- } else if (!isValid) {
- logger.error("Identifier \"" + constantName +
- "\" is not a valid " +
- innerType->getName(),
- *owner);
- }
-
- // Nevertheless, no matter what happened, set the value
- // of the original magic variant to the given constant
- *magicValuePtr = constant->getValue();
- }
-
- // Decrement the number of magic values, call the callback
- // function if all magic values have been resolved
- (*magicCount)--;
- if ((*magicCount) == 0 && (*isAsync)) {
- resultCallback(resolved, owner, logger);
- }
- });
- });
-
- // Now we are asynchronous
- (*isAsync) = true;
+ ParserScope scope = fork();
+ Variant *valuePtr = &value;
+
+ return resolveType(path, owner, logger,
+ [=](Handle<Node> resolved, Handle<Node> owner,
+ Logger &logger) mutable {
+ if (resolved != nullptr) {
+ Rooted<Type> type = resolved.cast<Type>();
+ scope.resolveValue(*valuePtr, type, owner, logger);
+ }
- // Directly call the callback function if there were no magic values
- // involved
- if ((*magicCount) == 0) {
- resultCallback(resolved, owner, logger);
- }
- });
+ // Call the result callback with the type
+ resultCallback(resolved, owner, logger);
+ });
}
bool ParserScope::resolveTypeWithValue(const std::string &name,
diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp
index c49acd3..2ef33d9 100644
--- a/src/core/parser/ParserScope.hpp
+++ b/src/core/parser/ParserScope.hpp
@@ -44,6 +44,7 @@ namespace ousia {
class CharReader;
class Logger;
class ParserScope;
+class Type;
class Variant;
/**
@@ -60,8 +61,8 @@ using ResolutionImposterCallback = std::function<Rooted<Node>()>;
* @param owner is the node that was passed as "owner".
* @param logger is the logger to which errors should be logged.
*/
-using ResolutionResultCallback = std::function<void(Handle<Node> resolved,
- Handle<Node> owner, Logger &logger)>;
+using ResolutionResultCallback = std::function<
+ void(Handle<Node> resolved, Handle<Node> owner, Logger &logger)>;
/**
* Base class for the
@@ -621,14 +622,25 @@ public:
Logger &logger, ResolutionResultCallback resultCallback);
/**
+ * Build and resolves a (possibly) magic value with the given typesystem
+ * type. This function does not perform any deferred lookups.
+ *
+ * @param data is a reference at a variant that may contain magic values
+ * (even in inner structures). The data will be passed to the "build"
+ * function of the given type.
+ * @param type is the Typesystem type the data should be interpreted with.
+ * @param owner is the node for which the resolution takes place.
+ * @param logger is the logger instance into which resolution problems
+ * should be logged.
+ * @return true if the value was successfully built.
+ */
+ bool resolveValue(Variant &data, Handle<Type> type, Handle<Node> owner,
+ Logger &logger);
+
+ /**
* Resolves a type and makes sure the corresponding value is of the correct
* type.
*
- * <b>Warning:</b> This function is extremely dangerous as you have to make
- * sure that the "value" reference stays alife as long as the "owner" is
- * valid. This is especially problematic as internally references at parts
- * of "value" may be kept. Test usages of this function well!
- *
* @tparam T is the type of the node that should be resolved.
* @param path is the path for which a node should be resolved.
* @param owner is the node for which the resolution takes place.
@@ -646,17 +658,13 @@ public:
*/
bool resolveTypeWithValue(const std::vector<std::string> &path,
Handle<Node> owner, Variant &value,
- Logger &logger, ResolutionResultCallback resultCallback);
+ Logger &logger,
+ ResolutionResultCallback resultCallback);
/**
* Resolves a type and makes sure the corresponding value is of the correct
* type.
*
- * <b>Warning:</b> This function is extremely dangerous as you have to make
- * sure that the "value" reference stays alife as long as the "owner" is
- * valid. This is especially problematic as internally references at parts
- * of "value" may be kept. Test usages of this function well!
- *
* @tparam T is the type of the node that should be resolved.
* @param name is the path for which a node should be resolved. The name is
* split at '.' to form a path.
@@ -674,7 +682,8 @@ public:
* later.
*/
bool resolveTypeWithValue(const std::string &name, Handle<Node> owner,
- Variant &value, Logger &logger, ResolutionResultCallback resultCallback);
+ Variant &value, Logger &logger,
+ ResolutionResultCallback resultCallback);
/**
* Tries to resolve all currently deferred resolution steps. The list of