summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2018-09-11 12:48:07 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2018-09-13 13:58:20 -0700
commit33e127f43656092467372069027893bfc2dc97d8 (patch)
tree0e4709c19e60eb7191f7a7f609cc15b6d5e91dfa
parentb8425b51eb71a9a1374209b63019121b40884a90 (diff)
downloadqtlocation-mapboxgl-33e127f43656092467372069027893bfc2dc97d8.tar.gz
[core] Implement array assertion fallback behavior
This was added in gl-js in #7095.
-rw-r--r--cmake/core-files.txt2
-rw-r--r--include/mbgl/style/expression/array_assertion.hpp47
-rw-r--r--include/mbgl/style/expression/assertion.hpp1
-rw-r--r--include/mbgl/style/expression/expression.hpp1
-rw-r--r--src/mbgl/style/conversion/function.cpp4
-rw-r--r--src/mbgl/style/expression/array_assertion.cpp106
-rw-r--r--src/mbgl/style/expression/assertion.cpp79
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp12
8 files changed, 78 insertions, 174 deletions
diff --git a/cmake/core-files.txt b/cmake/core-files.txt
index 6361540eb3..2db2d5bf87 100644
--- a/cmake/core-files.txt
+++ b/cmake/core-files.txt
@@ -450,7 +450,6 @@ src/mbgl/style/conversion/tileset.cpp
src/mbgl/style/conversion/transition_options.cpp
# style/expression
-include/mbgl/style/expression/array_assertion.hpp
include/mbgl/style/expression/assertion.hpp
include/mbgl/style/expression/at.hpp
include/mbgl/style/expression/boolean_operator.hpp
@@ -479,7 +478,6 @@ include/mbgl/style/expression/parsing_context.hpp
include/mbgl/style/expression/step.hpp
include/mbgl/style/expression/type.hpp
include/mbgl/style/expression/value.hpp
-src/mbgl/style/expression/array_assertion.cpp
src/mbgl/style/expression/assertion.cpp
src/mbgl/style/expression/at.cpp
src/mbgl/style/expression/boolean_operator.cpp
diff --git a/include/mbgl/style/expression/array_assertion.hpp b/include/mbgl/style/expression/array_assertion.hpp
deleted file mode 100644
index 0c0912b73e..0000000000
--- a/include/mbgl/style/expression/array_assertion.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/expression/parsing_context.hpp>
-#include <mbgl/style/conversion.hpp>
-
-#include <memory>
-
-namespace mbgl {
-namespace style {
-namespace expression {
-
-class ArrayAssertion : public Expression {
-public:
- ArrayAssertion(type::Array type_, std::unique_ptr<Expression> input_) :
- Expression(Kind::ArrayAssertion, type_),
- input(std::move(input_))
- {}
-
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
-
- EvaluationResult evaluate(const EvaluationContext& params) const override;
- void eachChild(const std::function<void(const Expression&)>& visit) const override;
-
- bool operator==(const Expression& e) const override {
- if (e.getKind() == Kind::ArrayAssertion) {
- auto rhs = static_cast<const ArrayAssertion*>(&e);
- return getType() == rhs->getType() && *input == *(rhs->input);
- }
- return false;
- }
-
- std::vector<optional<Value>> possibleOutputs() const override {
- return input->possibleOutputs();
- }
-
- mbgl::Value serialize() const override;
- std::string getOperator() const override { return "array"; }
-
-private:
- std::unique_ptr<Expression> input;
-};
-
-} // namespace expression
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/expression/assertion.hpp b/include/mbgl/style/expression/assertion.hpp
index 239cdf2ea6..0dec89dac9 100644
--- a/include/mbgl/style/expression/assertion.hpp
+++ b/include/mbgl/style/expression/assertion.hpp
@@ -24,6 +24,7 @@ public:
std::vector<optional<Value>> possibleOutputs() const override;
+ mbgl::Value serialize() const override;
std::string getOperator() const override;
private:
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index bfd1e08ee7..ce02c4114b 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -118,7 +118,6 @@ enum class Kind : int32_t {
Coalesce,
CompoundExpression,
Literal,
- ArrayAssertion,
At,
Interpolate,
Assertion,
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 2ce2f4eafd..7cc599be1d 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -6,7 +6,6 @@
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/case.hpp>
-#include <mbgl/style/expression/array_assertion.hpp>
#include <mbgl/util/string.hpp>
#include <cassert>
@@ -679,8 +678,7 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ
return toColor(get(literal(*property)));
},
[&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
- return std::unique_ptr<Expression>(
- std::make_unique<ArrayAssertion>(array, get(literal(*property))));
+ return assertion(array, get(literal(*property)));
},
[&] (const auto&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
diff --git a/src/mbgl/style/expression/array_assertion.cpp b/src/mbgl/style/expression/array_assertion.cpp
deleted file mode 100644
index 9df586bdc3..0000000000
--- a/src/mbgl/style/expression/array_assertion.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <mbgl/style/expression/array_assertion.hpp>
-#include <mbgl/style/expression/check_subtype.hpp>
-#include <mbgl/style/conversion_impl.hpp>
-#include <mbgl/util/string.hpp>
-
-namespace mbgl {
-namespace style {
-namespace expression {
-
-EvaluationResult ArrayAssertion::evaluate(const EvaluationContext& params) const {
- auto result = input->evaluate(params);
- if (!result) {
- return result.error();
- }
- type::Type expected = getType();
- type::Type actual = typeOf(*result);
- if (checkSubtype(expected, actual)) {
- return EvaluationError {
- "Expected value to be of type " + toString(expected) +
- ", but found " + toString(actual) + " instead."
- };
- }
- return *result;
-}
-
-void ArrayAssertion::eachChild(const std::function<void(const Expression&)>& visit) const {
- visit(*input);
-}
-
-using namespace mbgl::style::conversion;
-ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext& ctx) {
-
- static std::unordered_map<std::string, type::Type> itemTypes {
- {"string", type::String},
- {"number", type::Number},
- {"boolean", type::Boolean}
- };
-
- auto length = arrayLength(value);
- if (length < 2 || length > 4) {
- ctx.error("Expected 1, 2, or 3 arguments, but found " + util::toString(length - 1) + " instead.");
- return ParseResult();
- }
-
- optional<type::Type> itemType;
- optional<std::size_t> N;
- if (length > 2) {
- optional<std::string> itemTypeName = toString(arrayMember(value, 1));
- auto it = itemTypeName ? itemTypes.find(*itemTypeName) : itemTypes.end();
- if (it == itemTypes.end()) {
- ctx.error(
- R"(The item type argument of "array" must be one of string, number, boolean)",
- 1
- );
- return ParseResult();
- }
- itemType = it->second;
- } else {
- itemType = {type::Value};
- }
-
- if (length > 3) {
- auto n = toNumber(arrayMember(value, 2));
- if (!n || *n != std::floor(*n)) {
- ctx.error(
- R"(The length argument to "array" must be a positive integer literal.)",
- 2
- );
- return ParseResult();
- }
- N = optional<std::size_t>(*n);
- }
-
- auto input = ctx.parse(arrayMember(value, length - 1), length - 1, {type::Value});
- if (!input) {
- return input;
- }
-
- return ParseResult(std::make_unique<ArrayAssertion>(
- type::Array(*itemType, N),
- std::move(*input)
- ));
-}
-
-mbgl::Value ArrayAssertion::serialize() const {
- std::vector<mbgl::Value> serialized;
- serialized.emplace_back(getOperator());
-
-
- const auto array = getType().get<type::Array>();
- if (array.itemType.is<type::StringType>()
- || array.itemType.is<type::NumberType>()
- || array.itemType.is<type::BooleanType>()) {
- serialized.emplace_back(type::toString(array.itemType));
- if (array.N) {
- serialized.emplace_back(uint64_t(*array.N));
- }
- }
-
- serialized.emplace_back(input->serialize());
- return serialized;
-}
-
-} // namespace expression
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/expression/assertion.cpp b/src/mbgl/style/expression/assertion.cpp
index 7e93003ac3..8e5a8b555d 100644
--- a/src/mbgl/style/expression/assertion.cpp
+++ b/src/mbgl/style/expression/assertion.cpp
@@ -30,22 +30,64 @@ ParseResult Assertion::parse(const Convertible& value, ParsingContext& ctx) {
return ParseResult();
}
- auto it = types.find(*toString(arrayMember(value, 0)));
- assert(it != types.end());
-
+ std::size_t i = 1;
+ type::Type type;
+
+ std::string name = *toString(arrayMember(value, 0));
+ if (name == "array") {
+ optional<type::Type> itemType;
+ if (length > 2) {
+ optional<std::string> itemTypeName = toString(arrayMember(value, 1));
+ auto it = itemTypeName ? types.find(*itemTypeName) : types.end();
+ if (it == types.end() || it->second == type::Object) {
+ ctx.error(
+ R"(The item type argument of "array" must be one of string, number, boolean)",
+ 1
+ );
+ return ParseResult();
+ }
+ itemType = it->second;
+ i++;
+ } else {
+ itemType = {type::Value};
+ }
+
+ optional<std::size_t> N;
+ if (length > 3) {
+ auto m = arrayMember(value, 2);
+ optional<float> n = toNumber(m);
+ if (!isUndefined(m) &&
+ (!n || *n < 0 || *n != std::floor(*n))) {
+ ctx.error(
+ R"(The length argument to "array" must be a positive integer literal.)",
+ 2
+ );
+ return ParseResult();
+ }
+ if (n) {
+ N = optional<std::size_t>(*n);
+ }
+ i++;
+ }
+
+ type = type::Array(*itemType, N);
+ } else {
+ type = types.at(name);
+ }
+
std::vector<std::unique_ptr<Expression>> parsed;
parsed.reserve(length - 1);
- for (std::size_t i = 1; i < length; i++) {
+ for (; i < length; i++) {
ParseResult input = ctx.parse(arrayMember(value, i), i, {type::Value});
if (!input) return ParseResult();
parsed.push_back(std::move(*input));
}
- return ParseResult(std::make_unique<Assertion>(it->second, std::move(parsed)));
+ return ParseResult(std::make_unique<Assertion>(type, std::move(parsed)));
}
std::string Assertion::getOperator() const {
- return type::toString(getType());
+ return getType().is<type::Array>() ? "array" : type::toString(getType());
}
EvaluationResult Assertion::evaluate(const EvaluationContext& params) const {
@@ -90,6 +132,31 @@ std::vector<optional<Value>> Assertion::possibleOutputs() const {
return result;
}
+mbgl::Value Assertion::serialize() const {
+ std::vector<mbgl::Value> serialized;
+ serialized.emplace_back(getOperator());
+
+ if (getType().is<type::Array>()) {
+ const auto array = getType().get<type::Array>();
+ if (array.itemType.is<type::StringType>()
+ || array.itemType.is<type::NumberType>()
+ || array.itemType.is<type::BooleanType>()) {
+ serialized.emplace_back(type::toString(array.itemType));
+ if (array.N) {
+ serialized.emplace_back(uint64_t(*array.N));
+ } else if (inputs.size() > 1) {
+ serialized.emplace_back(mbgl::NullValue());
+ }
+ }
+ }
+
+ for (const auto& input : inputs) {
+ serialized.emplace_back(input->serialize());
+ }
+
+ return serialized;
+}
+
} // namespace expression
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 3fe50aa1e4..29d04d96a2 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -6,7 +6,6 @@
#include <mbgl/style/expression/expression.hpp>
#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>
@@ -46,8 +45,7 @@ bool isConstant(const Expression& expression) {
}
bool isTypeAnnotation = expression.getKind() == Kind::Coercion ||
- expression.getKind() == Kind::Assertion ||
- expression.getKind() == Kind::ArrayAssertion;
+ expression.getKind() == Kind::Assertion;
bool childrenConstant = true;
expression.eachChild([&](const Expression& child) {
@@ -105,7 +103,7 @@ const ExpressionRegistry& getExpressionRegistry() {
{"<=", parseComparison},
{"all", All::parse},
{"any", Any::parse},
- {"array", ArrayAssertion::parse},
+ {"array", Assertion::parse},
{"at", At::parse},
{"boolean", Assertion::parse},
{"case", Case::parse},
@@ -171,14 +169,10 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption
if (expected) {
const type::Type actual = (*parsed)->getType();
- if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object) && actual == type::Value) {
+ if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object || expected->is<type::Array>()) && actual == type::Value) {
if (typeAnnotationOption == includeTypeAnnotations) {
parsed = { std::make_unique<Assertion>(*expected, array(std::move(*parsed))) };
}
- } else if (expected->is<type::Array>() && actual == type::Value) {
- if (typeAnnotationOption == includeTypeAnnotations) {
- parsed = { std::make_unique<ArrayAssertion>(expected->get<type::Array>(), std::move(*parsed)) };
- }
} else if (*expected == type::Color && (actual == type::Value || actual == type::String)) {
if (typeAnnotationOption == includeTypeAnnotations) {
parsed = { std::make_unique<Coercion>(*expected, array(std::move(*parsed))) };