1 #pragma once
2 
3 #include <mbgl/util/optional.hpp>
4 #include <mbgl/util/variant.hpp>
5 #include <mbgl/util/color.hpp>
6 #include <mbgl/style/expression/type.hpp>
7 #include <mbgl/style/expression/value.hpp>
8 #include <mbgl/style/expression/parsing_context.hpp>
9 
10 #include <array>
11 #include <vector>
12 #include <memory>
13 
14 namespace mbgl {
15 
16 class GeometryTileFeature;
17 
18 namespace style {
19 namespace expression {
20 
21 class EvaluationError {
22 public:
23     std::string message;
24 };
25 
26 class EvaluationContext {
27 public:
EvaluationContext(float zoom_)28     EvaluationContext(float zoom_) : zoom(zoom_), feature(nullptr) {}
EvaluationContext(GeometryTileFeature const * feature_)29     EvaluationContext(GeometryTileFeature const * feature_) : zoom(optional<float>()), feature(feature_) {}
EvaluationContext(float zoom_,GeometryTileFeature const * feature_)30     EvaluationContext(float zoom_, GeometryTileFeature const * feature_) :
31         zoom(zoom_), feature(feature_)
32     {}
EvaluationContext(optional<float> zoom_,GeometryTileFeature const * feature_,optional<double> heatmapDensity_)33     EvaluationContext(optional<float> zoom_, GeometryTileFeature const * feature_, optional<double> heatmapDensity_) :
34         zoom(std::move(zoom_)), feature(feature_), heatmapDensity(std::move(heatmapDensity_))
35     {}
36 
37     optional<float> zoom;
38     GeometryTileFeature const * feature;
39     optional<double> heatmapDensity;
40 };
41 
42 template <typename T>
43 class Result : private variant<EvaluationError, T> {
44 public:
45     using variant<EvaluationError, T>::variant;
46     using Value = T;
47 
48     Result() = default;
49 
operator bool() const50     explicit operator bool () const {
51         return this->template is<T>();
52     }
53 
54     // optional does some type trait magic for this one, so this might
55     // be problematic as is.
operator ->() const56     const T* operator->() const {
57         assert(this->template is<T>());
58         return std::addressof(this->template get<T>());
59     }
60 
operator ->()61     T* operator->() {
62         assert(this->template is<T>());
63         return std::addressof(this->template get<T>());
64     }
65 
operator *()66     T& operator*() {
67         assert(this->template is<T>());
68         return this->template get<T>();
69     }
70 
operator *() const71     const T& operator*() const {
72         assert(this->template is<T>());
73         return this->template get<T>();
74     }
75 
error() const76     const EvaluationError& error() const {
77         assert(this->template is<EvaluationError>());
78         return this->template get<EvaluationError>();
79     }
80 };
81 
82 class EvaluationResult : public Result<Value> {
83 public:
84     using Result::Result; // NOLINT
85 
86     EvaluationResult() = default;
87 
EvaluationResult(const std::array<double,4> & arr)88     EvaluationResult(const std::array<double, 4>& arr) :
89         Result(toExpressionValue(arr))
90     {}
91 
92     // used only for the special (private) "error" expression
EvaluationResult(const type::ErrorType &)93     EvaluationResult(const type::ErrorType&) {
94         assert(false);
95     }
96 };
97 
98 /*
99     Expression is an abstract class that serves as an interface and base class
100     for particular expression implementations.
101 
102     CompoundExpression implements the majority of expressions in the spec by
103     inferring the argument and output from a simple function (const T0& arg0,
104     const T1& arg1, ...) -> Result<U> where T0, T1, ..., U are member types of
105     mbgl::style::expression::Value.
106 
107     The other Expression subclasses (Let, Curve, Match, etc.) exist in order to
108     implement expressions that need specialized parsing, type checking, or
109     evaluation logic that can't be handled by CompoundExpression's inference
110     mechanism.
111 
112     Each Expression subclass also provides a static
113     ParseResult ExpressionClass::parse(const V&, ParsingContext),
114     which handles parsing a style-spec JSON representation of the expression.
115 */
116 
117 enum class Kind : int32_t {
118     Coalesce,
119     CompoundExpression,
120     Literal,
121     ArrayAssertion,
122     At,
123     Interpolate,
124     Assertion,
125     Length,
126     Step,
127     Let,
128     Var,
129     CollatorExpression,
130     Coercion,
131     Match,
132     Error,
133     Case,
134     Any,
135     All,
136     Equals,
137 };
138 
139 class Expression {
140 public:
Expression(Kind kind_,type::Type type_)141     Expression(Kind kind_, type::Type type_) : kind(kind_), type(std::move(type_)) {}
142     virtual ~Expression() = default;
143 
144     virtual EvaluationResult evaluate(const EvaluationContext& params) const = 0;
145     virtual void eachChild(const std::function<void(const Expression&)>&) const = 0;
146     virtual bool operator==(const Expression&) const = 0;
operator !=(const Expression & rhs) const147     bool operator!=(const Expression& rhs) const {
148         return !operator==(rhs);
149     }
150 
getKind() const151     Kind getKind() const { return kind; };
getType() const152     type::Type getType() const { return type; };
153 
154     EvaluationResult evaluate(optional<float> zoom, const Feature& feature, optional<double> heatmapDensity) const;
155 
156     /**
157      * Statically analyze the expression, attempting to enumerate possible outputs. Returns
158      * an array of values plus the sentinel null optional value, used to indicate that the
159      * complete set of outputs is statically undecidable.
160      */
161     virtual std::vector<optional<Value>> possibleOutputs() const = 0;
162 
serialize() const163     virtual mbgl::Value serialize() const {
164         std::vector<mbgl::Value> serialized;
165         serialized.emplace_back(getOperator());
166         eachChild([&](const Expression &child) {
167             serialized.emplace_back(child.serialize());
168         });
169         return serialized;
170     };
171 
172     virtual std::string getOperator() const = 0;
173 
174 protected:
175     template <typename T>
childrenEqual(const T & lhs,const T & rhs)176     static bool childrenEqual(const T& lhs, const T& rhs) {
177         if (lhs.size() != rhs.size()) return false;
178         for (auto leftChild = lhs.begin(), rightChild = rhs.begin();
179              leftChild != lhs.end();
180              leftChild++, rightChild++)
181          {
182              if (!Expression::childEqual(*leftChild, *rightChild)) return false;
183          }
184          return true;
185     }
186 
childEqual(const std::unique_ptr<Expression> & lhs,const std::unique_ptr<Expression> & rhs)187     static bool childEqual(const std::unique_ptr<Expression>& lhs, const std::unique_ptr<Expression>& rhs) {
188         return *lhs == *rhs;
189     }
190 
191     template <typename T>
childEqual(const std::pair<T,std::unique_ptr<Expression>> & lhs,const std::pair<T,std::unique_ptr<Expression>> & rhs)192     static bool childEqual(const std::pair<T, std::unique_ptr<Expression>>& lhs,
193                            const std::pair<T, std::unique_ptr<Expression>>& rhs) {
194         return lhs.first == rhs.first && *(lhs.second) == *(rhs.second);
195     }
196 
197     template <typename T>
childEqual(const std::pair<T,std::shared_ptr<Expression>> & lhs,const std::pair<T,std::shared_ptr<Expression>> & rhs)198     static bool childEqual(const std::pair<T, std::shared_ptr<Expression>>& lhs,
199                            const std::pair<T, std::shared_ptr<Expression>>& rhs) {
200         return lhs.first == rhs.first && *(lhs.second) == *(rhs.second);
201     }
202 
childEqual(const std::pair<std::unique_ptr<Expression>,std::unique_ptr<Expression>> & lhs,const std::pair<std::unique_ptr<Expression>,std::unique_ptr<Expression>> & rhs)203     static bool childEqual(const std::pair<std::unique_ptr<Expression>, std::unique_ptr<Expression>>& lhs,
204                            const std::pair<std::unique_ptr<Expression>, std::unique_ptr<Expression>>& rhs) {
205         return *(lhs.first) == *(rhs.first) && *(lhs.second) == *(rhs.second);
206     }
207 
208 private:
209     Kind kind;
210     type::Type type;
211 };
212 
213 } // namespace expression
214 } // namespace style
215 } // namespace mbgl
216