diff options
| author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-04-15 00:37:39 +0200 | 
|---|---|---|
| committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2016-04-25 22:24:18 +0200 | 
| commit | 3803f1238f061a4cc962e67630c3bbbbae01eae5 (patch) | |
| tree | 4828a3473ce9fa48895fb51904ebcbe59e498a35 /src | |
| parent | 3075b0de2e889199c65438d9b3680f08e75eaaeb (diff) | |
Replace Typesystem "MagicCallback" by a more generic one.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/model/Typesystem.cpp | 88 | ||||
| -rw-r--r-- | src/core/model/Typesystem.hpp | 74 | ||||
| -rw-r--r-- | src/core/parser/ParserScope.cpp | 53 | ||||
| -rw-r--r-- | src/core/parser/ParserScope.hpp | 32 | ||||
| -rw-r--r-- | src/core/parser/stack/DocumentHandler.cpp | 4 | 
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() | 
