diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/style/conversion/function.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/expression/coalesce.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/expression/coercion.cpp | 33 | ||||
-rw-r--r-- | src/mbgl/style/expression/compound_expression.cpp | 13 | ||||
-rw-r--r-- | src/mbgl/style/expression/dsl.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/expression/parsing_context.cpp | 40 |
6 files changed, 58 insertions, 36 deletions
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 7cc599be1d..6ee962fb77 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -52,7 +52,7 @@ std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& so if (pos != end) { for (brace++; brace != end && tokenReservedChars.find(*brace) == std::string::npos; brace++); if (brace != end && *brace == '}') { - inputs.push_back(toString(get(literal(std::string(pos + 1, brace))))); + inputs.push_back(get(literal(std::string(pos + 1, brace)))); pos = brace + 1; } else { inputs.push_back(literal(std::string(pos, brace))); @@ -65,7 +65,7 @@ std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& so case 0: return literal(source); case 1: - return std::move(inputs[0]); + return toString(std::move(inputs[0])); default: return concat(std::move(inputs)); } diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp index cdbf452f7f..6b43e68ac6 100644 --- a/src/mbgl/style/expression/coalesce.cpp +++ b/src/mbgl/style/expression/coalesce.cpp @@ -57,7 +57,7 @@ ParseResult Coalesce::parse(const Convertible& value, ParsingContext& ctx) { Coalesce::Args args; args.reserve(length - 1); for (std::size_t i = 1; i < length; i++) { - auto parsed = ctx.parse(arrayMember(value, i), i, outputType, ParsingContext::omitTypeAnnotations); + auto parsed = ctx.parse(arrayMember(value, i), i, outputType, TypeAnnotationOption::omit); if (!parsed) { return parsed; } diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp index 187cdd48a4..4a17895991 100644 --- a/src/mbgl/style/expression/coercion.cpp +++ b/src/mbgl/style/expression/coercion.cpp @@ -8,6 +8,16 @@ namespace mbgl { namespace style { namespace expression { +EvaluationResult toBoolean(const Value& v) { + return v.match( + [&] (double f) { return static_cast<bool>(f); }, + [&] (const std::string& s) { return s.length() > 0; }, + [&] (bool b) { return b; }, + [&] (const NullValue&) { return false; }, + [&] (const auto&) { return true; } + ); +} + EvaluationResult toNumber(const Value& v) { optional<double> result = v.match( [](NullValue) -> optional<double> { return 0.0; }, @@ -78,10 +88,14 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in { assert(!inputs.empty()); type::Type t = getType(); - if (t.is<type::NumberType>()) { - coerceSingleValue = toNumber; + if (t.is<type::BooleanType>()) { + coerceSingleValue = toBoolean; } else if (t.is<type::ColorType>()) { coerceSingleValue = toColor; + } else if (t.is<type::NumberType>()) { + coerceSingleValue = toNumber; + } else if (t.is<type::StringType>()) { + coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); }; } else { assert(false); } @@ -89,16 +103,20 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in std::string Coercion::getOperator() const { return getType().match( - [](const type::NumberType&) { return "to-number"; }, + [](const type::BooleanType&) { return "to-boolean"; }, [](const type::ColorType&) { return "to-color"; }, + [](const type::NumberType&) { return "to-number"; }, + [](const type::StringType&) { return "to-string"; }, [](const auto&) { assert(false); return ""; }); } using namespace mbgl::style::conversion; ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) { static std::unordered_map<std::string, type::Type> types { + {"to-boolean", type::Boolean}, + {"to-color", type::Color}, {"to-number", type::Number}, - {"to-color", type::Color} + {"to-string", type::String} }; std::size_t length = arrayLength(value); @@ -110,7 +128,12 @@ ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) { auto it = types.find(*toString(arrayMember(value, 0))); assert(it != types.end()); - + + if ((it->second == type::Boolean || it->second == type::String) && length != 2) { + ctx.error("Expected one argument."); + return ParseResult(); + } + std::vector<std::unique_ptr<Expression>> parsed; parsed.reserve(length - 1); for (std::size_t i = 1; i < length; i++) { diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index f5cbd7030b..fc47b2d78e 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -309,19 +309,6 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali define("typeof", [](const Value& v) -> Result<std::string> { return toString(typeOf(v)); }); - define("to-string", [](const Value& value) -> Result<std::string> { - return toString(value); - }); - - define("to-boolean", [](const Value& v) -> Result<bool> { - return v.match( - [&] (double f) { return static_cast<bool>(f); }, - [&] (const std::string& s) { return s.length() > 0; }, - [&] (bool b) { return b; }, - [&] (const NullValue&) { return false; }, - [&] (const auto&) { return true; } - ); - }); define("to-rgba", [](const Color& color) -> Result<std::array<double, 4>> { return color.toArray(); }); diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp index cdada583a2..c6318fb637 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -74,7 +74,7 @@ std::unique_ptr<Expression> toColor(std::unique_ptr<Expression> value) { } std::unique_ptr<Expression> toString(std::unique_ptr<Expression> value) { - return compound("to-string", std::move(value)); + return std::make_unique<Coercion>(type::String, vec(std::move(value))); } std::unique_ptr<Expression> get(const char* value) { diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp index 29d04d96a2..0373b9721f 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -21,6 +21,7 @@ #include <mbgl/style/expression/step.hpp> #include <mbgl/style/expression/find_zoom_curve.hpp> +#include <mbgl/style/expression/dsl.hpp> #include <mbgl/style/conversion/get_json_type.hpp> #include <mbgl/style/conversion_impl.hpp> @@ -76,7 +77,7 @@ using namespace mbgl::style::conversion; ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_, optional<type::Type> expected_, - TypeAnnotationOption typeAnnotationOption) { + optional<TypeAnnotationOption> typeAnnotationOption) { ParsingContext child(key + "[" + util::toString(index_) + "]", errors, std::move(expected_), @@ -118,14 +119,16 @@ const ExpressionRegistry& getExpressionRegistry() { {"object", Assertion::parse}, {"step", Step::parse}, {"string", Assertion::parse}, + {"to-boolean", Coercion::parse}, {"to-color", Coercion::parse}, {"to-number", Coercion::parse}, + {"to-string", Coercion::parse}, {"var", Var::parse} }}; return registry; } -ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption typeAnnotationOption) { +ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotationOption> typeAnnotationOption) { ParseResult parsed; if (isArray(value)) { @@ -161,22 +164,27 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption return parsed; } - auto array = [&](std::unique_ptr<Expression> expression) { - std::vector<std::unique_ptr<Expression>> args; - args.push_back(std::move(expression)); - return args; + auto annotate = [] (std::unique_ptr<Expression> expression, type::Type type, TypeAnnotationOption typeAnnotation) -> std::unique_ptr<Expression> { + switch (typeAnnotation) { + case TypeAnnotationOption::assert: + return std::make_unique<Assertion>(type, dsl::vec(std::move(expression))); + case TypeAnnotationOption::coerce: + return std::make_unique<Coercion>(type, dsl::vec(std::move(expression))); + case TypeAnnotationOption::omit: + return expression; + } + + // Not reachable, but placate GCC. + assert(false); + return expression; }; if (expected) { const type::Type actual = (*parsed)->getType(); 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))) }; - } + parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::assert)) }; } else if (*expected == type::Color && (actual == type::Value || actual == type::String)) { - if (typeAnnotationOption == includeTypeAnnotations) { - parsed = { std::make_unique<Coercion>(*expected, array(std::move(*parsed))) }; - } + parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::coerce)) }; } else { checkType((*parsed)->getType()); if (errors->size() > 0) { @@ -212,11 +220,15 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption return parsed; } -ParseResult ParsingContext::parseExpression(const Convertible& value, TypeAnnotationOption typeAnnotationOption) { +ParseResult ParsingContext::parseExpression(const Convertible& value, optional<TypeAnnotationOption> typeAnnotationOption) { return parse(value, typeAnnotationOption); } -ParseResult ParsingContext::parseLayerPropertyExpression(const Convertible& value, TypeAnnotationOption typeAnnotationOption) { +ParseResult ParsingContext::parseLayerPropertyExpression(const Convertible& value) { + optional<TypeAnnotationOption> typeAnnotationOption; + if (expected && *expected == type::String) { + typeAnnotationOption = TypeAnnotationOption::coerce; + } ParseResult parsed = parse(value, typeAnnotationOption); if (parsed && !isZoomConstant(**parsed)) { optional<variant<const Interpolate*, const Step*, ParsingError>> zoomCurve = findZoomCurve(parsed->get()); |