diff options
Diffstat (limited to 'include/mbgl/style/expression/compound_expression.hpp')
-rw-r--r-- | include/mbgl/style/expression/compound_expression.hpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/include/mbgl/style/expression/compound_expression.hpp b/include/mbgl/style/expression/compound_expression.hpp new file mode 100644 index 0000000000..fc3edbfd4a --- /dev/null +++ b/include/mbgl/style/expression/compound_expression.hpp @@ -0,0 +1,138 @@ +#pragma once + +#include <mbgl/style/expression/expression.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/expression/parsing_context.hpp> +#include <mbgl/style/expression/type.hpp> +#include <mbgl/style/expression/value.hpp> + +#include <mbgl/util/optional.hpp> +#include <mbgl/util/variant.hpp> + +#include <memory> +#include <vector> + +namespace mbgl { +namespace style { +namespace expression { + +/* + CompoundExpression provides a mechanism for implementing an expression + simply by providing a list of pure functions of the form + (const T0& arg0, const T1& arg1, ...) -> Result<U> where T0, T1, ..., U are + member types of mbgl::style::expression::Value. + + The majority of expressions specified in the style-spec are implemented in + this fashion (see compound_expression.cpp). +*/ + + +/* + Represents the parameter list for an expression that takes an arbitrary + number of arguments (of a specific type). +*/ +struct VarargsType { type::Type type; }; +template <typename T> +struct Varargs : std::vector<T> { using std::vector<T>::vector; }; + +namespace detail { +// Base class for the Signature<Fn> structs that are used to determine the +// each CompoundExpression definition's type::Type data from the type of its +// "evaluate" function. +struct SignatureBase { + SignatureBase(type::Type result_, variant<std::vector<type::Type>, VarargsType> params_) : + result(std::move(result_)), + params(std::move(params_)) + {} + virtual ~SignatureBase() = default; + virtual std::unique_ptr<Expression> makeExpression(const std::string& name, std::vector<std::unique_ptr<Expression>>) const = 0; + type::Type result; + variant<std::vector<type::Type>, VarargsType> params; +}; +} // namespace detail + + +/* + Common base class for CompoundExpression<Signature> instances. Used to + allow downcasting (and access to things like name & parameter list) during + an Expression tree traversal. +*/ +class CompoundExpressionBase : public Expression { +public: + CompoundExpressionBase(std::string name_, const detail::SignatureBase& signature) : + Expression(signature.result), + name(std::move(name_)), + params(signature.params) + {} + + std::string getName() const { return name; } + optional<std::size_t> getParameterCount() const { + return params.match( + [&](const VarargsType&) { return optional<std::size_t>(); }, + [&](const std::vector<type::Type>& p) -> optional<std::size_t> { return p.size(); } + ); + } + +private: + std::string name; + variant<std::vector<type::Type>, VarargsType> params; +}; + +template <typename Signature> +class CompoundExpression : public CompoundExpressionBase { +public: + using Args = typename Signature::Args; + + CompoundExpression(const std::string& name_, + Signature signature_, + typename Signature::Args args_) : + CompoundExpressionBase(name_, signature_), + signature(signature_), + args(std::move(args_)) + {} + + EvaluationResult evaluate(const EvaluationContext& evaluationParams) const override { + return signature.apply(evaluationParams, args); + } + + void eachChild(const std::function<void(const Expression&)>& visit) const override { + for (const std::unique_ptr<Expression>& e : args) { + visit(*e); + } + } + + bool operator==(const Expression& e) const override { + if (auto rhs = dynamic_cast<const CompoundExpression*>(&e)) { + return getName() == rhs->getName() && Expression::childrenEqual(args, rhs->args); + } + return false; + } + +private: + Signature signature; + typename Signature::Args args; +}; + +/* + Holds the map of expression name => implementation (which is just one or + more evaluation functions, each wrapped in a Signature struct). +*/ +struct CompoundExpressionRegistry { + using Definition = std::vector<std::unique_ptr<detail::SignatureBase>>; + static std::unordered_map<std::string, Definition> definitions; +}; + +ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext& ctx); + +ParseResult createCompoundExpression(const std::string& name, + const CompoundExpressionRegistry::Definition& definition, + std::vector<std::unique_ptr<Expression>> args, + ParsingContext& ctx); + +ParseResult createCompoundExpression(const std::string& name, + std::vector<std::unique_ptr<Expression>> args, + ParsingContext& ctx); + +} // namespace expression +} // namespace style +} // namespace mbgl |