diff options
author | Anand Thakker <github@anandthakker.net> | 2017-10-19 16:02:19 -0400 |
---|---|---|
committer | Anand Thakker <github@anandthakker.net> | 2017-10-25 11:53:48 -0400 |
commit | ba786b65dbbeb3cc2831bb30514315839a234c87 (patch) | |
tree | a89cf27200a97a10870931ed4e16f55707de5a53 | |
parent | 7a5101a8f669b39c78db98f73c2b4e0ce53c4257 (diff) | |
download | qtlocation-mapboxgl-ba786b65dbbeb3cc2831bb30514315839a234c87.tar.gz |
Implement special forms for 'any', 'all' to allow early return
-rw-r--r-- | include/mbgl/style/expression/boolean_operator.hpp | 12 | ||||
-rw-r--r-- | src/mbgl/style/expression/boolean_operator.cpp | 71 | ||||
-rw-r--r-- | src/mbgl/style/expression/compound_expression.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/style/expression/parsing_context.cpp | 5 |
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); } |