summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnand Thakker <github@anandthakker.net>2017-10-19 16:02:19 -0400
committerAnand Thakker <github@anandthakker.net>2017-10-25 11:53:48 -0400
commitba786b65dbbeb3cc2831bb30514315839a234c87 (patch)
treea89cf27200a97a10870931ed4e16f55707de5a53
parent7a5101a8f669b39c78db98f73c2b4e0ce53c4257 (diff)
downloadqtlocation-mapboxgl-ba786b65dbbeb3cc2831bb30514315839a234c87.tar.gz
Implement special forms for 'any', 'all' to allow early return
-rw-r--r--include/mbgl/style/expression/boolean_operator.hpp12
-rw-r--r--src/mbgl/style/expression/boolean_operator.cpp71
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp10
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp5
4 files changed, 82 insertions, 16 deletions
diff --git a/include/mbgl/style/expression/boolean_operator.hpp b/include/mbgl/style/expression/boolean_operator.hpp
index ad24725422..db86e63a39 100644
--- a/include/mbgl/style/expression/boolean_operator.hpp
+++ b/include/mbgl/style/expression/boolean_operator.hpp
@@ -7,8 +7,8 @@ namespace expression {
class Any : public Expression {
public:
- Any(type::Array type_, std::vector<std::unique_ptr<Expression>> inputs_) :
- Expression(type_),
+ Any(std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(type::Boolean),
inputs(std::move(inputs_))
{}
@@ -18,13 +18,13 @@ public:
void accept(std::function<void(const Expression*)> visit) const override;
private:
- std::unique_ptr<Expression> inputs;
+ std::vector<std::unique_ptr<Expression>> inputs;
};
class All : public Expression {
public:
- All(type::Array type_, std::vector<std::unique_ptr<Expression>> inputs_) :
- Expression(type_),
+ All(std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(type::Boolean),
inputs(std::move(inputs_))
{}
@@ -34,7 +34,7 @@ public:
void accept(std::function<void(const Expression*)> visit) const override;
private:
- std::unique_ptr<Expression> inputs;
+ std::vector<std::unique_ptr<Expression>> inputs;
};
} // namespace expression
diff --git a/src/mbgl/style/expression/boolean_operator.cpp b/src/mbgl/style/expression/boolean_operator.cpp
index e69de29bb2..48052af8e3 100644
--- a/src/mbgl/style/expression/boolean_operator.cpp
+++ b/src/mbgl/style/expression/boolean_operator.cpp
@@ -0,0 +1,71 @@
+#include <mbgl/style/expression/boolean_operator.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Any::evaluate(const EvaluationParameters& params) const {
+ for (auto it = inputs.begin(); it != inputs.end(); it++) {
+ const EvaluationResult result = (*it)->evaluate(params);
+ if (!result) return result;
+ if (result->get<bool>()) return EvaluationResult(true);
+ }
+ return EvaluationResult(false);
+}
+
+void Any::accept(std::function<void(const Expression*)> visit) const {
+ visit(this);
+ for (const std::unique_ptr<Expression>& input : inputs) {
+ input->accept(visit);
+ }
+}
+
+EvaluationResult All::evaluate(const EvaluationParameters& params) const {
+ for (auto it = inputs.begin(); it != inputs.end(); it++) {
+ const EvaluationResult result = (*it)->evaluate(params);
+ if (!result) return result;
+ if (!result->get<bool>()) return EvaluationResult(false);
+ }
+ return EvaluationResult(true);
+}
+
+void All::accept(std::function<void(const Expression*)> visit) const {
+ visit(this);
+ for (const std::unique_ptr<Expression>& input : inputs) {
+ input->accept(visit);
+ }
+}
+
+template <class T>
+ParseResult parseBooleanOp(const mbgl::style::conversion::Convertible& value, ParsingContext ctx) {
+ using namespace mbgl::style::conversion;
+ assert(isArray(value));
+ auto length = arrayLength(value);
+
+ std::vector<std::unique_ptr<Expression>> parsedInputs;
+
+ for (std::size_t i = 1; i < length; i++) {
+ auto parsed = ctx.concat(i, {type::Boolean}).parse(arrayMember(value, i));
+ if (!parsed) {
+ return parsed;
+ }
+
+ parsedInputs.push_back(std::move(*parsed));
+ }
+
+ return ParseResult(std::make_unique<T>(std::move(parsedInputs)));
+}
+
+ParseResult Any::parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx) {
+ return parseBooleanOp<Any>(value, ctx);
+}
+
+ParseResult All::parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx) {
+ return parseBooleanOp<All>(value, ctx);
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index 0673f07736..5fc6228986 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -403,16 +403,6 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
define("<=", [](double lhs, double rhs) -> Result<bool> { return lhs <= rhs; });
define("<=", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs <= rhs; });
- define("any", [](const Varargs<bool>& args) -> Result<bool> {
- bool result = false;
- for (auto arg : args) result = result || arg;
- return result;
- });
- define("all", [](const Varargs<bool>& args) -> Result<bool> {
- bool result = true;
- for (bool arg : args) result = result && arg;
- return result;
- });
define("!", [](bool e) -> Result<bool> { return !e; });
define("upcase", [](const std::string& input) -> Result<std::string> {
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 2c00bbfb22..79b173ad87 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -3,6 +3,7 @@
#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/expression/array_assertion.hpp>
#include <mbgl/style/expression/assertion.hpp>
+#include <mbgl/style/expression/boolean_operator.hpp>
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/coercion.hpp>
@@ -71,6 +72,10 @@ ParseResult ParsingContext::parse(const mbgl::style::conversion::Convertible& va
parsed = Assertion::parse(value, *this);
} else if (*op == "to-color" || *op == "to-number") {
parsed = Coercion::parse(value, *this);
+ } else if (*op == "any") {
+ parsed = Any::parse(value, *this);
+ } else if (*op == "all") {
+ parsed = All::parse(value, *this);
} else {
parsed = parseCompoundExpression(*op, value, *this);
}