139 lines
4.6 KiB
C++
139 lines
4.6 KiB
C++
#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
|