summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/model/Typesystem.cpp88
-rw-r--r--src/core/model/Typesystem.hpp74
-rw-r--r--src/core/parser/ParserScope.cpp53
-rw-r--r--src/core/parser/ParserScope.hpp32
-rw-r--r--src/core/parser/stack/DocumentHandler.cpp4
5 files changed, 99 insertions, 152 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp
index 17d81dd..cf980d6 100644
--- a/src/core/model/Typesystem.cpp
+++ b/src/core/model/Typesystem.cpp
@@ -27,34 +27,55 @@ namespace ousia {
/* Static helper functions */
-static Type::MagicCallbackResult NullMagicCallback(Variant &, const Type *)
+static bool NullResolveCallback(bool, const Rtti *,
+ const std::vector<std::string> &,
+ ResolutionResultCallback)
{
- return Type::MagicCallbackResult::NOT_FOUND;
+ return false;
}
/* Class Type */
bool Type::build(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
// If the given variant is marked as "magic", try to resolve the real value
if (data.isMagic()) {
- switch (magicCallback(data, this)) {
- case MagicCallbackResult::NOT_FOUND:
- break;
- case MagicCallbackResult::FOUND_INVALID: {
- // The magic callback has probably already issued an error
- // message -- do not print more errors
+ Rooted<Constant> constant;
+ if (resolveCallback(
+ false, &RttiTypes::Constant, Utils::split(data.asMagic(), '.'),
+ [&constant](Handle<Node> resolved, Handle<Node> owner,
+ Logger &logger) mutable {
+ // Copy the resolution result out of this function
+ constant = resolved.cast<Constant>();
+ })) {
+ // Check whether the inner type of the constant is correct
+ Rooted<Type> constantType = constant->getType();
+ if (!constantType->checkIsa(this)) {
+ logger.error(
+ std::string("Expected value of type \"") + this->getName() +
+ std::string("\" but found constant \"") +
+ constant->getName() + std::string("\" of type \"") +
+ constantType->getName() + "\" instead.",
+ data);
+ logger.note("Constant was defined here:", *constant);
+
+ // The resolution was successful, but the received value has the
+ // wrong type. The code above has already issued an error
+ // message -- do not print more errors.
Logger nullLogger;
return build(data, nullLogger);
}
- case MagicCallbackResult::FOUND_VALID:
- return true;
+
+ // A valid constant was found, copy the data to the variant and
+ // abort
+ data = constant->getValue();
+ return true;
}
}
try {
- return doBuild(data, logger, magicCallback);
+ return doBuild(data, logger, resolveCallback);
}
catch (LoggableException ex) {
logger.log(ex, data);
@@ -65,7 +86,7 @@ bool Type::build(Variant &data, Logger &logger,
bool Type::build(Variant &data, Logger &logger) const
{
- return build(data, logger, NullMagicCallback);
+ return build(data, logger, NullResolveCallback);
}
bool Type::doCheckIsa(Handle<const Type> type) const { return false; }
@@ -81,7 +102,7 @@ bool Type::checkIsa(Handle<const Type> type) const
/* Class BoolType */
bool BoolType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
return VariantConverter::toBool(data, logger);
}
@@ -89,7 +110,7 @@ bool BoolType::doBuild(Variant &data, Logger &logger,
/* Class IntType */
bool IntType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
return VariantConverter::toInt(data, logger);
}
@@ -97,7 +118,7 @@ bool IntType::doBuild(Variant &data, Logger &logger,
/* Class DoubleType */
bool DoubleType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
return VariantConverter::toDouble(data, logger);
}
@@ -105,7 +126,7 @@ bool DoubleType::doBuild(Variant &data, Logger &logger,
/* Class StringType */
bool StringType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
return VariantConverter::toString(data, logger);
}
@@ -113,7 +134,7 @@ bool StringType::doBuild(Variant &data, Logger &logger,
/* Class CardinalityType */
bool CardinalityType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
return VariantConverter::toCardinality(data, logger);
}
@@ -126,7 +147,7 @@ EnumType::EnumType(Manager &mgr, std::string name, Handle<Typesystem> system)
}
bool EnumType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
// If the variant is an int, check whether the value is in range
if (data.isInt()) {
@@ -363,7 +384,7 @@ bool StructType::insertDefaults(Variant &data, const std::vector<bool> &set,
}
bool StructType::buildFromArray(Variant &data, Logger &logger,
- const MagicCallback &magicCallback,
+ const ResolveCallback &resolveCallback,
bool trim) const
{
bool ok = true;
@@ -388,7 +409,8 @@ bool StructType::buildFromArray(Variant &data, Logger &logger,
// Make sure the given attributes have to correct type
const size_t len = std::min(n, N);
for (size_t a = 0; a < len; a++) {
- set[a] = attributes[a]->getType()->build(arr[a], logger, magicCallback);
+ set[a] =
+ attributes[a]->getType()->build(arr[a], logger, resolveCallback);
ok = ok && set[a];
}
@@ -396,7 +418,7 @@ bool StructType::buildFromArray(Variant &data, Logger &logger,
}
bool StructType::buildFromMap(Variant &data, Logger &logger,
- const MagicCallback &magicCallback,
+ const ResolveCallback &resolveCallback,
bool trim) const
{
bool ok = true;
@@ -429,7 +451,7 @@ bool StructType::buildFromMap(Variant &data, Logger &logger,
// Convert the value to the type of the attribute
arr[idx] = value;
set[idx] = attributes[idx]->getType()->build(arr[idx], logger,
- magicCallback);
+ resolveCallback);
} else if (!trim) {
ok = false;
logger.error(std::string("Invalid attribute key \"") + key +
@@ -447,14 +469,14 @@ bool StructType::buildFromMap(Variant &data, Logger &logger,
}
bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger,
- const MagicCallback &magicCallback,
+ const ResolveCallback &resolveCallback,
bool trim) const
{
if (data.isArray()) {
- return buildFromArray(data, logger, magicCallback, trim);
+ return buildFromArray(data, logger, resolveCallback, trim);
}
if (data.isMap()) {
- return buildFromMap(data, logger, magicCallback, trim);
+ return buildFromMap(data, logger, resolveCallback, trim);
}
throw LoggableException(
std::string(
@@ -488,9 +510,9 @@ void StructType::initialize(Logger &logger)
}
bool StructType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
- return buildFromArrayOrMap(data, logger, magicCallback, false);
+ return buildFromArrayOrMap(data, logger, resolveCallback, false);
}
bool StructType::doValidate(Logger &logger) const
@@ -616,7 +638,7 @@ bool StructType::derivedFrom(Handle<StructType> other) const
bool StructType::cast(Variant &data, Logger &logger) const
{
- return buildFromArrayOrMap(data, logger, NullMagicCallback, true);
+ return buildFromArrayOrMap(data, logger, NullResolveCallback, true);
}
NodeVector<Attribute> StructType::getOwnAttributes() const
@@ -650,7 +672,7 @@ ReferenceType::ReferenceType(Manager &mgr, const std::string &name,
}
bool ReferenceType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
// Null references are valid references
if (data.isNull()) {
@@ -693,7 +715,7 @@ void ReferenceType::setDescriptor(Handle<Descriptor> descriptor)
/* Class ArrayType */
bool ArrayType::doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const
+ const ResolveCallback &resolveCallback) const
{
if (!data.isArray()) {
throw LoggableException(
@@ -701,7 +723,7 @@ bool ArrayType::doBuild(Variant &data, Logger &logger,
}
bool res = true;
for (auto &v : data.asArray()) {
- if (!innerType->build(v, logger, magicCallback)) {
+ if (!innerType->build(v, logger, resolveCallback)) {
res = false;
}
}
@@ -730,7 +752,7 @@ bool ArrayType::doCheckIsa(Handle<const Type> type) const
/* Class UnknownType */
-bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const
+bool UnknownType::doBuild(Variant &, Logger &, const ResolveCallback &) const
{
return true;
}
diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp
index 3d869d9..dc4526e 100644
--- a/src/core/model/Typesystem.hpp
+++ b/src/core/model/Typesystem.hpp
@@ -39,6 +39,7 @@
#include "Node.hpp"
#include "RootNode.hpp"
+#include "ResolutionCallbacks.hpp"
namespace ousia {
@@ -59,45 +60,6 @@ class Descriptor;
* definitions.
*/
class Type : public Node {
-public:
- /**
- * Enum describing the result of the MagicCallback.
- */
- enum class MagicCallbackResult {
- /**
- * A magic value with the given name could not be resolved.
- */
- NOT_FOUND,
-
- /**
- * A magic value with the given name could be resolved, but is of the
- * wrong type.
- */
- FOUND_INVALID,
-
- /**
- * A magic value with the given name could be resolved and is of the
- * correct type.
- */
- FOUND_VALID
- };
-
- /**
- * Callback function called when a variant with "magic" value is reached.
- * This callback allows to transform these magic values into something else.
- * This mechanism is used to resolve constants.
- *
- * @param data is the magic value that should be looked up and the variant
- * to which the value of the looked up constant should be written.
- * @param type is a const pointer at the type. TODO: Replace this with a
- * "ConstHandle".
- * @return a MagicCallbackResult describing whether the magic value could
- * not be resolved, could be resolved but is of the wrong type or could be
- * resolved and is of the correct type.
- */
- using MagicCallback =
- std::function<MagicCallbackResult(Variant &data, const Type *type)>;
-
protected:
/**
* Protected constructor to be called by the classes derived from the Type
@@ -125,12 +87,12 @@ protected:
* -- if possible and necessary -- converted to a variant adhering to the
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be written.
- * @param magicCallback is a callback that should be called to other "build"
+ * @param resolveCallback is a callback that should be called to other "build"
* functions.
* @return true if the conversion was successful, false otherwise.
*/
virtual bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const = 0;
+ const ResolveCallback &resolveCallback) const = 0;
/**
* May be overriden to check whether an instance of this type logically is
@@ -167,12 +129,12 @@ public:
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be
* written.
- * @param magicCallback is the callback function to be called whenever
+ * @param resolveCallback is the callback function to be called whenever
* a variant with "magic" value is reached.
* @return true if the conversion was successful, false otherwise.
*/
bool build(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const;
+ const ResolveCallback &resolveCallback) const;
/**
* Validates and completes the given variant which was read from a
@@ -241,7 +203,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
public:
/**
@@ -280,7 +242,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
public:
/**
@@ -319,7 +281,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
public:
/**
@@ -358,7 +320,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
public:
/**
@@ -396,7 +358,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
public:
/**
@@ -452,7 +414,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
/**
* Returns true if the internal value list is non-empty.
@@ -751,7 +713,7 @@ private:
* @return true if the operation is successful, false otherwise.
*/
bool buildFromArray(Variant &data, Logger &logger,
- const MagicCallback &magicCallback, bool trim) const;
+ const ResolveCallback &resolveCallback, bool trim) const;
/**
* Checks a map and its entries for validity and if possible updates its
@@ -764,7 +726,7 @@ private:
* @return true if the operation is successful, false otherwise.
*/
bool buildFromMap(Variant &data, Logger &logger,
- const MagicCallback &magicCallback, bool trim) const;
+ const ResolveCallback &resolveCallback, bool trim) const;
/**
* Checks a map or an array for validity and if possible updates its content
@@ -777,7 +739,7 @@ private:
* @return true if the operation is successful, false otherwise.
*/
bool buildFromArrayOrMap(Variant &data, Logger &logger,
- const MagicCallback &magicCallback,
+ const ResolveCallback &resolveCallback,
bool trim) const;
/**
@@ -811,7 +773,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
/**
* Checks the struct descriptor for being valid.
@@ -1004,7 +966,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
/**
* Returns true if this type is equivalent to another given ReferenceType,
@@ -1074,7 +1036,7 @@ protected:
* @return true if the conversion was successful, false otherwise.
*/
bool doBuild(Variant &data, Logger &logger,
- const MagicCallback &magicCallback) const override;
+ const ResolveCallback &resolveCallback) const override;
/**
* Returns true if this type is equivalent to another given ArrayType.
@@ -1134,7 +1096,7 @@ protected:
*
* @return always true.
*/
- bool doBuild(Variant &, Logger &, const MagicCallback &) const override;
+ bool doBuild(Variant &, Logger &, const ResolveCallback &) const override;
public:
/**
diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp
index ed35839..5e4b37f 100644
--- a/src/core/parser/ParserScope.cpp
+++ b/src/core/parser/ParserScope.cpp
@@ -409,45 +409,20 @@ 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, Logger &logger)
+bool ParserScope::resolveValue(Variant &data, Handle<Node> owner,
+ Handle<Type> type, 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;
- }
-
- // Check whether the inner type of the constant is correct
- Type::MagicCallbackResult res =
- Type::MagicCallbackResult::FOUND_VALID;
- Rooted<Type> constantType = constant->getType();
- if (!constantType->checkIsa(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.",
- innerData);
- logger.note("Constant was defined here:", *constant);
- res = Type::MagicCallbackResult::FOUND_INVALID;
- }
-
- // Set the data to the value of the constant (even if an error
- // happend -- probably the type was not that wrong -- who knows?)
- innerData = constant->getValue();
-
- return res;
- });
+ return type->build(data, logger,
+ [&](bool async, const Rtti *rttiType,
+ const std::vector<std::string> &path,
+ ResolutionResultCallback resultCallback) mutable {
+ if (!async) {
+ Rooted<Node> resolved = ParserScopeBase::resolve(rttiType, path, logger);
+ resultCallback(resolved, owner, logger);
+ return resolved != nullptr;
+ }
+ return resolve(rttiType, path, type, logger, resultCallback);
+ });
}
bool ParserScope::resolveTypeWithValue(const std::vector<std::string> &path,
@@ -465,7 +440,7 @@ bool ParserScope::resolveTypeWithValue(const std::vector<std::string> &path,
[=](Handle<Node> resolved, Handle<Node> owner, Logger &logger) mutable {
if (resolved != nullptr) {
Rooted<Type> type = resolved.cast<Type>();
- scope.resolveValue(*valuePtr, type, logger);
+ scope.resolveValue(*valuePtr, owner, type, logger);
}
// Call the result callback with the type
diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp
index 85b5d8b..eec4751 100644
--- a/src/core/parser/ParserScope.hpp
+++ b/src/core/parser/ParserScope.hpp
@@ -28,6 +28,7 @@
#include <core/common/Rtti.hpp>
#include <core/common/Utils.hpp>
#include <core/model/Node.hpp>
+#include <core/model/ResolutionCallbacks.hpp>
/**
* @file ParserScope.hpp
@@ -48,23 +49,6 @@ class Type;
class Variant;
/**
- * Callback function type used for creating a dummy object while no correct
- * object is available for resolution.
- */
-using ResolutionImposterCallback = std::function<Rooted<Node>()>;
-
-/**
- * Callback function type called whenever the result of a resolution is
- * available.
- *
- * @param resolved is the new, resolved 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)>;
-
-/**
* Base class for the ParserScope, does not contain the mechanisms for deferred
* lookup, only maintains the stack of nodes.
*/
@@ -288,14 +272,14 @@ enum class ParserFlag {
POST_HEAD,
/**
- * Set to the boolean value "true" if explicit fields may no longer be
- * defined inside a structure element.
- */
+ * Set to the boolean value "true" if explicit fields may no longer be
+ * defined inside a structure element.
+ */
POST_EXPLICIT_FIELDS,
/**
- * Set to true if all user defined tokens have been registered.
- */
+ * Set to true if all user defined tokens have been registered.
+ */
POST_USER_DEFINED_TOKEN_REGISTRATION
};
@@ -716,12 +700,14 @@ public:
* @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 owner is the node for which the resolution takes place.
* @param type is the Typesystem type the data should be interpreted with.
* @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, Logger &logger);
+ bool resolveValue(Variant &data, Handle<Node> owner, Handle<Type> type,
+ Logger &logger);
/**
* Resolves a type and makes sure the corresponding value is of the correct
diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp
index 7564fad..2228f11 100644
--- a/src/core/parser/stack/DocumentHandler.cpp
+++ b/src/core/parser/stack/DocumentHandler.cpp
@@ -768,7 +768,9 @@ bool DocumentChildHandler::convertData(Handle<FieldDescriptor> field,
}
// Now try to resolve the value for the primitive type
- return valid && scope().resolveValue(data, type, logger);
+ return valid &&
+ scope().resolveValue(data, field->getParent().cast<Node>(), type,
+ logger);
}
bool DocumentChildHandler::data()