summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnand Thakker <github@anandthakker.net>2017-07-09 17:00:52 -0400
committerAnand Thakker <github@anandthakker.net>2017-07-09 17:00:52 -0400
commit945cdebe9b37c3de764d382cf216d55ee0b7fce6 (patch)
tree8f144b4b2d24f0d8fc26538c3fea189cf60782fe
parent8f7bfb80c401447758229a92d6b268783089f23c (diff)
downloadqtlocation-mapboxgl-945cdebe9b37c3de764d382cf216d55ee0b7fce6.tar.gz
Wrap EvaluationParameters and return an <Error, Value> variant
-rw-r--r--include/mbgl/style/expression/expression.hpp72
-rw-r--r--platform/node/src/node_expression.cpp85
-rw-r--r--platform/node/src/node_expression.hpp2
-rw-r--r--src/mbgl/style/function/expression.cpp10
4 files changed, 113 insertions, 56 deletions
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index e35a302f00..a3e69e4bb3 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -4,12 +4,14 @@
#include <vector>
#include <memory>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/style/function/type.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion.hpp>
+
namespace mbgl {
class GeometryTileFeature;
@@ -18,31 +20,40 @@ class GeometryTileFeature;
namespace style {
namespace expression {
-using OutputValue = variant<
+struct Value;
+using ValueBase = variant<
+ NullValue,
float,
std::string,
mbgl::Color,
- std::array<float, 2>,
- std::array<float, 4>>;
+ mapbox::util::recursive_wrapper<std::vector<Value>>,
+ mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>;
+struct Value : ValueBase {
+ using ValueBase::ValueBase;
+};
+
+constexpr NullValue Null = NullValue();
struct EvaluationError {
std::string message;
};
-struct CompileError {
- std::string message;
- std::string key;
+struct EvaluationParameters {
+ float zoom;
+ const GeometryTileFeature& feature;
};
+using EvaluationResult = variant<EvaluationError, Value>;
+
class Expression {
public:
Expression(std::string key_, type::Type type_) : key(key_), type(type_) {}
virtual ~Expression() {}
- virtual optional<OutputValue> evaluate(float, const GeometryTileFeature&, EvaluationError& e) const = 0;
+ virtual EvaluationResult evaluate(const EvaluationParameters&) const = 0;
// Exposed for use with pure Feature objects (e.g. beyond the context of tiled map data).
- optional<OutputValue> evaluate(float, const Feature&, EvaluationError&) const;
+ EvaluationResult evaluate(float, const Feature&) const;
type::Type getType() const {
return type;
@@ -70,6 +81,10 @@ private:
type::Type type;
};
+struct CompileError {
+ std::string message;
+ std::string key;
+};
using ParseResult = variant<CompileError, std::unique_ptr<Expression>>;
template <class V>
ParseResult parseExpression(const V& value, const ParsingContext& context);
@@ -81,16 +96,16 @@ public:
LiteralExpression(std::string key, float value_) : Expression(key, type::Primitive::Number), value(value_) {}
LiteralExpression(std::string key, const std::string& value_) : Expression(key, type::Primitive::String), value(value_) {}
LiteralExpression(std::string key, const mbgl::Color& value_) : Expression(key, type::Primitive::Color), value(value_) {}
- LiteralExpression(std::string key) : Expression(key, type::Primitive::Null) {}
-
- optional<OutputValue> evaluate(float, const GeometryTileFeature&, EvaluationError&) const override {
+ LiteralExpression(std::string key, const NullValue&) : Expression(key, type::Primitive::Null), value(Null) {}
+
+ EvaluationResult evaluate(const EvaluationParameters&) const override {
return value;
}
template <class V>
static ParseResult parse(const V& value, const ParsingContext& ctx) {
if (isUndefined(value))
- return std::make_unique<LiteralExpression>(ctx.key());
+ return std::make_unique<LiteralExpression>(ctx.key(), Null);
if (isObject(value)) {
return CompileError {ctx.key(), "Unimplemented: object literals"};
@@ -114,7 +129,7 @@ public:
}
private:
- optional<OutputValue> value;
+ Value value;
};
class LambdaExpression : public Expression {
@@ -154,19 +169,20 @@ private:
};
template <typename T, typename Rfunc>
-optional<OutputValue> evaluateBinaryOperator(float z,
- const GeometryTileFeature& f,
- EvaluationError& e,
+EvaluationResult evaluateBinaryOperator(const EvaluationParameters& params,
const LambdaExpression::Args& args,
optional<T> initial,
Rfunc reduce)
{
optional<T> memo = initial;
for(const auto& arg : args) {
- auto argValue = arg->evaluate(z, f, e);
- if (!argValue) return {};
- if (!memo) memo = {argValue->get<T>()};
- else memo = reduce(*memo, argValue->get<T>());
+ auto argValue = arg->evaluate(params);
+ if (argValue.is<EvaluationError>()) {
+ return argValue.get<EvaluationError>();
+ }
+ T value = argValue.get<Value>().get<T>();
+ if (!memo) memo = {value};
+ else memo = reduce(*memo, value);
}
return {*memo};
}
@@ -178,8 +194,8 @@ public:
{type::Primitive::Number, {type::NArgs({type::Primitive::Number})}})
{}
- optional<OutputValue> evaluate(float zoom, const GeometryTileFeature& feature, EvaluationError& error) const override {
- return evaluateBinaryOperator<float>(zoom, feature, error, args,
+ EvaluationResult evaluate(const EvaluationParameters& params) const override {
+ return evaluateBinaryOperator<float>(params, args,
{}, [](float memo, float next) { return memo + next; });
}
};
@@ -191,8 +207,8 @@ public:
{type::Primitive::Number, {type::NArgs({type::Primitive::Number})}})
{}
- optional<OutputValue> evaluate(float zoom, const GeometryTileFeature& feature, EvaluationError& error) const override {
- return evaluateBinaryOperator<float>(zoom, feature, error, args,
+ EvaluationResult evaluate(const EvaluationParameters& params) const override {
+ return evaluateBinaryOperator<float>(params, args,
{}, [](float memo, float next) { return memo * next; });
}
};
@@ -204,8 +220,8 @@ public:
{type::Primitive::Number, {type::Primitive::Number, type::Primitive::Number}})
{}
- optional<OutputValue> evaluate(float zoom, const GeometryTileFeature& feature, EvaluationError& error) const override {
- return evaluateBinaryOperator<float>(zoom, feature, error, args,
+ EvaluationResult evaluate(const EvaluationParameters& params) const override {
+ return evaluateBinaryOperator<float>(params, args,
{}, [](float memo, float next) { return memo - next; });
}
};
@@ -217,8 +233,8 @@ public:
{type::Primitive::Number, {type::Primitive::Number, type::Primitive::Number}})
{}
- optional<OutputValue> evaluate(float zoom, const GeometryTileFeature& feature, EvaluationError& error) const override {
- return evaluateBinaryOperator<float>(zoom, feature, error, args,
+ EvaluationResult evaluate(const EvaluationParameters& params) const override {
+ return evaluateBinaryOperator<float>(params, args,
{}, [](float memo, float next) { return memo / next; });
}
};
diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp
index c6c2a04bfb..0c03d05902 100644
--- a/platform/node/src/node_expression.cpp
+++ b/platform/node/src/node_expression.cpp
@@ -73,6 +73,55 @@ void NodeExpression::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(info.This());
}
+struct ToValue {
+ v8::Local<v8::Value> operator()(mbgl::NullValue) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::Null());
+ }
+
+ v8::Local<v8::Value> operator()(bool t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t));
+ }
+
+ v8::Local<v8::Value> operator()(float t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t));
+ }
+
+ v8::Local<v8::Value> operator()(const std::string& t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t).ToLocalChecked());
+ }
+
+ v8::Local<v8::Value> operator()(const std::vector<Value>& array) {
+ Nan::EscapableHandleScope scope;
+ v8::Local<v8::Array> result = Nan::New<v8::Array>();
+ for (unsigned int i = 0; i < array.size(); i++) {
+ result->Set(i, toJS(array[i]));
+ }
+ return scope.Escape(result);
+ }
+
+ v8::Local<v8::Value> operator()(const mbgl::Color& color) {
+ return operator()(color.stringify().c_str());
+ }
+
+ v8::Local<v8::Value> operator()(const std::unordered_map<std::string, Value>& map) {
+ Nan::EscapableHandleScope scope;
+ v8::Local<v8::Object> result = Nan::New<v8::Object>();
+ for (const auto& entry : map) {
+ Nan::Set(result, Nan::New(entry.first).ToLocalChecked(), toJS(entry.second));
+ }
+
+ return scope.Escape(result);
+ }
+};
+
+v8::Local<v8::Value> toJS(const Value& value) {
+ return Value::visit(value, ToValue());
+}
+
void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info) {
NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
const auto& expression = nodeExpr->expression;
@@ -99,29 +148,19 @@ void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info)
try {
mapbox::geojson::feature feature = geoJSON->get<mapbox::geojson::feature>();
- EvaluationError error;
- auto result = expression->evaluate(zoom, feature, error);
- if (result) {
- result->match(
- [&] (const std::array<float, 2>&) {},
- [&] (const std::array<float, 4>&) {},
- [&] (const std::string s) {
- info.GetReturnValue().Set(Nan::New(s.c_str()).ToLocalChecked());
- },
- [&] (const mbgl::Color& c) {
- info.GetReturnValue().Set(Nan::New(c.stringify().c_str()).ToLocalChecked());
- },
- [&] (const auto& v) {
- info.GetReturnValue().Set(Nan::New(v));
- }
- );
- } else {
- v8::Local<v8::Object> res = Nan::New<v8::Object>();
- Nan::Set(res,
- Nan::New("error").ToLocalChecked(),
- Nan::New(error.message.c_str()).ToLocalChecked());
- info.GetReturnValue().Set(res);
- }
+ auto result = expression->evaluate(zoom, feature);
+ result.match(
+ [&] (const Value& v) {
+ info.GetReturnValue().Set(toJS(v));
+ },
+ [&] (const EvaluationError& error) {
+ v8::Local<v8::Object> res = Nan::New<v8::Object>();
+ Nan::Set(res,
+ Nan::New("error").ToLocalChecked(),
+ Nan::New(error.message.c_str()).ToLocalChecked());
+ info.GetReturnValue().Set(res);
+ }
+ );
} catch(std::exception &ex) {
return Nan::ThrowTypeError(ex.what());
}
diff --git a/platform/node/src/node_expression.hpp b/platform/node/src/node_expression.hpp
index 3797632236..5cfc3b553e 100644
--- a/platform/node/src/node_expression.hpp
+++ b/platform/node/src/node_expression.hpp
@@ -16,6 +16,8 @@ using namespace mbgl::style::expression;
namespace node_mbgl {
+v8::Local<v8::Value> toJS(const Value&);
+
class NodeExpression : public Nan::ObjectWrap {
public:
static void Init(v8::Local<v8::Object>);
diff --git a/src/mbgl/style/function/expression.cpp b/src/mbgl/style/function/expression.cpp
index b609a6e576..1c24378265 100644
--- a/src/mbgl/style/function/expression.cpp
+++ b/src/mbgl/style/function/expression.cpp
@@ -29,18 +29,18 @@ public:
return {};
}
- optional<Value> getValue(const std::string& key) const override {
+ optional<mbgl::Value> getValue(const std::string& key) const override {
auto it = feature.properties.find(key);
if (it != feature.properties.end()) {
- return optional<Value>(it->second);
+ return optional<mbgl::Value>(it->second);
}
- return optional<Value>();
+ return optional<mbgl::Value>();
}
};
-optional<OutputValue> Expression::evaluate(float z, const Feature& feature, EvaluationError& error) const {
+EvaluationResult Expression::evaluate(float z, const Feature& feature) const {
std::unique_ptr<const GeometryTileFeature> f = std::make_unique<const GeoJSONFeature>(feature);
- return this->evaluate(z, *f, error);
+ return this->evaluate(EvaluationParameters {z, *f});
}