1 #pragma once 2 3 #include <mbgl/style/expression/expression.hpp> 4 #include <mbgl/style/conversion.hpp> 5 #include <mbgl/style/expression/parsing_context.hpp> 6 #include <mbgl/style/expression/type.hpp> 7 #include <mbgl/style/expression/value.hpp> 8 9 #include <mbgl/util/optional.hpp> 10 #include <mbgl/util/variant.hpp> 11 12 #include <memory> 13 #include <vector> 14 15 namespace mbgl { 16 namespace style { 17 namespace expression { 18 19 /* 20 CompoundExpression provides a mechanism for implementing an expression 21 simply by providing a list of pure functions of the form 22 (const T0& arg0, const T1& arg1, ...) -> Result<U> where T0, T1, ..., U are 23 member types of mbgl::style::expression::Value. 24 25 The majority of expressions specified in the style-spec are implemented in 26 this fashion (see compound_expression.cpp). 27 */ 28 29 30 /* 31 Represents the parameter list for an expression that takes an arbitrary 32 number of arguments (of a specific type). 33 */ 34 struct VarargsType { type::Type type; }; 35 template <typename T> 36 struct Varargs : std::vector<T> { 37 template <class... Args> Varargsmbgl::style::expression::Varargs38 Varargs(Args&&... args) : std::vector<T>(std::forward<Args>(args)...) {} 39 }; 40 41 namespace detail { 42 // Base class for the Signature<Fn> structs that are used to determine 43 // each CompoundExpression definition's type::Type data from the type of its 44 // "evaluate" function. 45 struct SignatureBase { SignatureBasembgl::style::expression::detail::SignatureBase46 SignatureBase(type::Type result_, variant<std::vector<type::Type>, VarargsType> params_, std::string name_) : 47 result(std::move(result_)), 48 params(std::move(params_)), 49 name(std::move(name_)) 50 {} 51 virtual ~SignatureBase() = default; 52 virtual std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>>) const = 0; 53 type::Type result; 54 variant<std::vector<type::Type>, VarargsType> params; 55 std::string name; 56 }; 57 } // namespace detail 58 59 60 /* 61 Common base class for CompoundExpression<Signature> instances. Used to 62 allow downcasting (and access to things like name & parameter list) during 63 an Expression tree traversal. 64 */ 65 class CompoundExpressionBase : public Expression { 66 public: CompoundExpressionBase(std::string name_,const detail::SignatureBase & signature)67 CompoundExpressionBase(std::string name_, const detail::SignatureBase& signature) : 68 Expression(Kind::CompoundExpression, signature.result), 69 name(std::move(name_)), 70 params(signature.params) 71 {} 72 getName() const73 std::string getName() const { return name; } getParameterCount() const74 optional<std::size_t> getParameterCount() const { 75 return params.match( 76 [&](const VarargsType&) { return optional<std::size_t>(); }, 77 [&](const std::vector<type::Type>& p) -> optional<std::size_t> { return p.size(); } 78 ); 79 } 80 possibleOutputs() const81 std::vector<optional<Value>> possibleOutputs() const override { 82 return { nullopt }; 83 } 84 85 private: 86 std::string name; 87 variant<std::vector<type::Type>, VarargsType> params; 88 }; 89 90 template <typename Signature> 91 class CompoundExpression : public CompoundExpressionBase { 92 public: 93 using Args = typename Signature::Args; 94 CompoundExpression(const std::string & name_,Signature signature_,typename Signature::Args args_)95 CompoundExpression(const std::string& name_, 96 Signature signature_, 97 typename Signature::Args args_) : 98 CompoundExpressionBase(name_, signature_), 99 signature(signature_), 100 args(std::move(args_)) 101 {} 102 evaluate(const EvaluationContext & evaluationParams) const103 EvaluationResult evaluate(const EvaluationContext& evaluationParams) const override { 104 return signature.apply(evaluationParams, args); 105 } 106 eachChild(const std::function<void (const Expression &)> & visit) const107 void eachChild(const std::function<void(const Expression&)>& visit) const override { 108 for (const std::unique_ptr<Expression>& e : args) { 109 visit(*e); 110 } 111 } 112 operator ==(const Expression & e) const113 bool operator==(const Expression& e) const override { 114 if (e.getKind() == Kind::CompoundExpression) { 115 auto rhs = static_cast<const CompoundExpression*>(&e); 116 return getName() == rhs->getName() && Expression::childrenEqual(args, rhs->args); 117 } 118 return false; 119 } 120 getOperator() const121 std::string getOperator() const override { 122 return signature.name; 123 } 124 125 private: 126 Signature signature; 127 typename Signature::Args args; 128 }; 129 130 /* 131 Holds the map of expression name => implementation (which is just one or 132 more evaluation functions, each wrapped in a Signature struct). 133 */ 134 struct CompoundExpressionRegistry { 135 using Definition = std::vector<std::unique_ptr<detail::SignatureBase>>; 136 static std::unordered_map<std::string, Definition> definitions; 137 }; 138 139 ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext& ctx); 140 141 ParseResult createCompoundExpression(const std::string& name, 142 std::vector<std::unique_ptr<Expression>> args, 143 ParsingContext& ctx); 144 145 } // namespace expression 146 } // namespace style 147 } // namespace mbgl 148