summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnand Thakker <github@anandthakker.net>2017-10-27 13:44:08 -0400
committerAnand Thakker <github@anandthakker.net>2017-10-27 13:44:08 -0400
commite3b12e8e17797b27e1017e67269d4b9d22d40c20 (patch)
tree660ef6410c41c81f60fb4a91bcdbbfe5f6a3dfb1
parent9b17784ccc01f5a0dd313b1c3a55fa4a1bc684c1 (diff)
downloadqtlocation-mapboxgl-e3b12e8e17797b27e1017e67269d4b9d22d40c20.tar.gz
Refactor ParsingContext
- Pass by reference - Hide members behind getters - Create `errors` within ParsingContext() rather than taking a reference - Limit public constructors to "root" context and remove `concat()` in favor of parse() overloads for parsing child expressions
-rw-r--r--include/mbgl/style/conversion/expression.hpp6
-rw-r--r--include/mbgl/style/expression/array_assertion.hpp2
-rw-r--r--include/mbgl/style/expression/assertion.hpp2
-rw-r--r--include/mbgl/style/expression/at.hpp2
-rw-r--r--include/mbgl/style/expression/boolean_operator.hpp4
-rw-r--r--include/mbgl/style/expression/case.hpp2
-rw-r--r--include/mbgl/style/expression/coalesce.hpp2
-rw-r--r--include/mbgl/style/expression/coercion.hpp2
-rw-r--r--include/mbgl/style/expression/compound_expression.hpp6
-rw-r--r--include/mbgl/style/expression/curve.hpp2
-rw-r--r--include/mbgl/style/expression/expression.hpp7
-rw-r--r--include/mbgl/style/expression/let.hpp4
-rw-r--r--include/mbgl/style/expression/literal.hpp2
-rw-r--r--include/mbgl/style/expression/match.hpp2
-rw-r--r--include/mbgl/style/expression/parsing_context.hpp87
-rw-r--r--include/mbgl/style/function/convert.hpp62
-rw-r--r--platform/node/src/node_expression.cpp10
-rw-r--r--src/mbgl/style/expression/array_assertion.cpp4
-rw-r--r--src/mbgl/style/expression/assertion.cpp4
-rw-r--r--src/mbgl/style/expression/at.cpp8
-rw-r--r--src/mbgl/style/expression/boolean_operator.cpp8
-rw-r--r--src/mbgl/style/expression/case.cpp12
-rw-r--r--src/mbgl/style/expression/coalesce.cpp8
-rw-r--r--src/mbgl/style/expression/coercion.cpp4
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp31
-rw-r--r--src/mbgl/style/expression/curve.cpp19
-rw-r--r--src/mbgl/style/expression/let.cpp9
-rw-r--r--src/mbgl/style/expression/literal.cpp10
-rw-r--r--src/mbgl/style/expression/match.cpp43
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp23
30 files changed, 217 insertions, 170 deletions
diff --git a/include/mbgl/style/conversion/expression.hpp b/include/mbgl/style/conversion/expression.hpp
index 21f28ca8c1..c5fcf906a7 100644
--- a/include/mbgl/style/conversion/expression.hpp
+++ b/include/mbgl/style/conversion/expression.hpp
@@ -14,13 +14,13 @@ using namespace mbgl::style::expression;
template<> struct Converter<std::unique_ptr<Expression>> {
optional<std::unique_ptr<Expression>> operator()(const Convertible& value, Error& error, type::Type expected) const {
- std::vector<ParsingError> errors;
- ParseResult parsed = ParsingContext(errors, expected).parse(value);
+ ParsingContext ctx(optional<type::Type> {expected});
+ ParseResult parsed = ctx.parse(value);
if (parsed) {
return std::move(*parsed);
}
std::string combinedError;
- for (const ParsingError& parsingError : errors) {
+ for (const ParsingError& parsingError : ctx.getErrors()) {
if (combinedError.size() > 0) {
combinedError += "\n";
}
diff --git a/include/mbgl/style/expression/array_assertion.hpp b/include/mbgl/style/expression/array_assertion.hpp
index 1b0e766c13..d7b0f786cc 100644
--- a/include/mbgl/style/expression/array_assertion.hpp
+++ b/include/mbgl/style/expression/array_assertion.hpp
@@ -18,7 +18,7 @@ public:
input(std::move(input_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
diff --git a/include/mbgl/style/expression/assertion.hpp b/include/mbgl/style/expression/assertion.hpp
index 635ec5eff1..e572f7a6f9 100644
--- a/include/mbgl/style/expression/assertion.hpp
+++ b/include/mbgl/style/expression/assertion.hpp
@@ -16,7 +16,7 @@ public:
inputs(std::move(inputs_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
diff --git a/include/mbgl/style/expression/at.hpp b/include/mbgl/style/expression/at.hpp
index f04b24dcb7..171c8ec9b1 100644
--- a/include/mbgl/style/expression/at.hpp
+++ b/include/mbgl/style/expression/at.hpp
@@ -16,7 +16,7 @@ public:
input(std::move(input_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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*)>&) const override;
diff --git a/include/mbgl/style/expression/boolean_operator.hpp b/include/mbgl/style/expression/boolean_operator.hpp
index 7a7f2b30d3..4e025c5d2d 100644
--- a/include/mbgl/style/expression/boolean_operator.hpp
+++ b/include/mbgl/style/expression/boolean_operator.hpp
@@ -15,7 +15,7 @@ public:
inputs(std::move(inputs_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
@@ -31,7 +31,7 @@ public:
inputs(std::move(inputs_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
diff --git a/include/mbgl/style/expression/case.hpp b/include/mbgl/style/expression/case.hpp
index 9ee3896e2b..26d030aed6 100644
--- a/include/mbgl/style/expression/case.hpp
+++ b/include/mbgl/style/expression/case.hpp
@@ -19,7 +19,7 @@ public:
: Expression(type_), branches(std::move(branches_)), otherwise(std::move(otherwise_)) {
}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
diff --git a/include/mbgl/style/expression/coalesce.hpp b/include/mbgl/style/expression/coalesce.hpp
index 2dbf236032..f32949ea76 100644
--- a/include/mbgl/style/expression/coalesce.hpp
+++ b/include/mbgl/style/expression/coalesce.hpp
@@ -19,7 +19,7 @@ public:
args(std::move(args_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
EvaluationResult evaluate(const EvaluationContext& params) const override;
diff --git a/include/mbgl/style/expression/coercion.hpp b/include/mbgl/style/expression/coercion.hpp
index 978f6320d2..65bd1aab58 100644
--- a/include/mbgl/style/expression/coercion.hpp
+++ b/include/mbgl/style/expression/coercion.hpp
@@ -17,7 +17,7 @@ class Coercion : public Expression {
public:
Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_);
- static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ 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;
diff --git a/include/mbgl/style/expression/compound_expression.hpp b/include/mbgl/style/expression/compound_expression.hpp
index 8dfe175f44..909927e299 100644
--- a/include/mbgl/style/expression/compound_expression.hpp
+++ b/include/mbgl/style/expression/compound_expression.hpp
@@ -115,16 +115,16 @@ struct CompoundExpressionRegistry {
static std::unordered_map<std::string, Definition> definitions;
};
-ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
ParseResult createCompoundExpression(const std::string& name,
const CompoundExpressionRegistry::Definition& definition,
std::vector<std::unique_ptr<Expression>> args,
- ParsingContext ctx);
+ ParsingContext& ctx);
ParseResult createCompoundExpression(const std::string& name,
std::vector<std::unique_ptr<Expression>> args,
- ParsingContext ctx);
+ ParsingContext& ctx);
} // namespace expression
} // namespace style
diff --git a/include/mbgl/style/expression/curve.hpp b/include/mbgl/style/expression/curve.hpp
index 6a46a6e152..c1d0eb6ac9 100644
--- a/include/mbgl/style/expression/curve.hpp
+++ b/include/mbgl/style/expression/curve.hpp
@@ -55,7 +55,7 @@ public:
};
-ParseResult parseCurve(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ParseResult parseCurve(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
template <typename T>
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index 25c84fbf13..85fffae938 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -104,10 +104,9 @@ public:
evaluation logic that can't be handled by CompoundExpression's inference
mechanism.
- Each Expression subclass has an accompanying
- template <class V> ParseResult ParseXxxx::parse(const V&, ParsingContext),
- found in style/expression/parse/xxxx.hpp, which handles parsing a style-spec
- JSON representation of the expression.
+ Each Expression subclass also provides a static
+ ParseResult ExpressionClass::parse(const V&, ParsingContext),
+ which handles parsing a style-spec JSON representation of the expression.
*/
class Expression {
public:
diff --git a/include/mbgl/style/expression/let.hpp b/include/mbgl/style/expression/let.hpp
index 499dd0b657..a9356853df 100644
--- a/include/mbgl/style/expression/let.hpp
+++ b/include/mbgl/style/expression/let.hpp
@@ -21,7 +21,7 @@ public:
result(std::move(result_))
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext);
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
EvaluationResult evaluate(const EvaluationContext& params) const override;
void eachChild(const std::function<void(const Expression*)>&) const override;
@@ -43,7 +43,7 @@ public:
value(value_)
{}
- static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext);
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
EvaluationResult evaluate(const EvaluationContext& params) const override;
void eachChild(const std::function<void(const Expression*)>&) const override;
diff --git a/include/mbgl/style/expression/literal.hpp b/include/mbgl/style/expression/literal.hpp
index 84f72d540a..34d539fedf 100644
--- a/include/mbgl/style/expression/literal.hpp
+++ b/include/mbgl/style/expression/literal.hpp
@@ -18,7 +18,7 @@ public:
return value;
}
- static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext);
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
void eachChild(const std::function<void(const Expression*)>&) const override {}
diff --git a/include/mbgl/style/expression/match.hpp b/include/mbgl/style/expression/match.hpp
index 38d4edeee5..01c0db5bf5 100644
--- a/include/mbgl/style/expression/match.hpp
+++ b/include/mbgl/style/expression/match.hpp
@@ -36,7 +36,7 @@ private:
std::unique_ptr<Expression> otherwise;
};
-ParseResult parseMatch(const mbgl::style::conversion::Convertible& value, ParsingContext ctx);
+ParseResult parseMatch(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
} // namespace expression
} // namespace style
diff --git a/include/mbgl/style/expression/parsing_context.hpp b/include/mbgl/style/expression/parsing_context.hpp
index 56d68c19d2..9aa287869b 100644
--- a/include/mbgl/style/expression/parsing_context.hpp
+++ b/include/mbgl/style/expression/parsing_context.hpp
@@ -24,7 +24,8 @@ using ParseResult = optional<std::unique_ptr<Expression>>;
namespace detail {
-struct Scope {
+class Scope {
+public:
Scope(const std::map<std::string, std::shared_ptr<Expression>>& bindings_, std::shared_ptr<Scope> parent_ = nullptr) :
bindings(bindings_),
parent(std::move(parent_))
@@ -49,28 +50,18 @@ struct Scope {
class ParsingContext {
public:
- ParsingContext(std::vector<ParsingError>& errors_, optional<type::Type> expected_ = {})
- : errors(errors_),
- expected(std::move(expected_))
+ ParsingContext() : errors(std::make_shared<std::vector<ParsingError>>()) {}
+ ParsingContext(std::string key) : key(std::move(key)), errors(std::make_shared<std::vector<ParsingError>>()) {}
+ explicit ParsingContext(optional<type::Type> expected_)
+ : expected(std::move(expected_)),
+ errors(std::make_shared<std::vector<ParsingError>>())
{}
+ ParsingContext(ParsingContext&&) = default;
- ParsingContext concat(std::size_t index_, optional<type::Type> expected_ = {}) {
- return ParsingContext(key + "[" + std::to_string(index_) + "]",
- errors,
- std::move(expected_),
- scope);
- }
-
- ParsingContext concat(std::size_t index_,
- optional<type::Type> expected_,
- const std::map<std::string, std::shared_ptr<Expression>>& bindings) {
- return ParsingContext(key + "[" + std::to_string(index_) + "]",
- errors,
- std::move(expected_),
- std::make_shared<detail::Scope>(bindings, scope));
+ std::string getKey() const { return key; }
+ optional<type::Type> getExpected() const { return expected; }
+ const std::vector<ParsingError>& getErrors() const { return *errors; }
- }
-
/*
Parse the given style-spec JSON value into an Expression object.
Specifically, this function is responsible for determining the expression
@@ -80,6 +71,21 @@ public:
ParseResult parse(const mbgl::style::conversion::Convertible& value);
/*
+ Parse a child expression.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible&,
+ std::size_t,
+ optional<type::Type> = {});
+
+ /*
+ Parse a child expression.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible&,
+ std::size_t index,
+ optional<type::Type>,
+ const std::map<std::string, std::shared_ptr<Expression>>&);
+
+ /*
Check whether `t` is a subtype of `expected`, collecting an error if not.
*/
optional<std::string> checkType(const type::Type& t);
@@ -90,28 +96,45 @@ public:
}
void error(std::string message) {
- errors.push_back({message, key});
+ errors->push_back({message, key});
}
- void error(std::string message, std::size_t child) {
- errors.push_back({message, key + "[" + std::to_string(child) + "]"});
+ void error(std::string message, std::size_t child) {
+ errors->push_back({message, key + "[" + std::to_string(child) + "]"});
}
-
- std::string key;
- std::vector<ParsingError>& errors;
- optional<type::Type> expected;
- std::shared_ptr<detail::Scope> scope;
-
+
+ void error(std::string message, std::size_t child, std::size_t grandchild) {
+ errors->push_back({message, key + "[" + std::to_string(child) + "][" + std::to_string(grandchild) + "]"});
+ }
+
+ void appendErrors(ParsingContext&& ctx) {
+ errors->reserve(errors->size() + ctx.errors->size());
+ std::move(ctx.errors->begin(), ctx.errors->end(), std::inserter(*errors, errors->end()));
+ ctx.errors->clear();
+ }
+
+ void clearErrors() {
+ errors->clear();
+ }
+
private:
ParsingContext(std::string key_,
- std::vector<ParsingError>& errors_,
+ std::shared_ptr<std::vector<ParsingError>> errors_,
optional<type::Type> expected_,
std::shared_ptr<detail::Scope> scope_)
: key(std::move(key_)),
- errors(errors_),
expected(std::move(expected_)),
- scope(std::move(scope_))
+ scope(std::move(scope_)),
+ errors(std::move(errors_))
{}
+
+ ParsingContext(const ParsingContext&) = delete;
+ ParsingContext& operator=(const ParsingContext&) = delete;
+
+ std::string key;
+ optional<type::Type> expected;
+ std::shared_ptr<detail::Scope> scope;
+ std::shared_ptr<std::vector<ParsingError>> errors;
};
} // namespace expression
diff --git a/include/mbgl/style/function/convert.hpp b/include/mbgl/style/function/convert.hpp
index ac148c7af1..e07b4038ea 100644
--- a/include/mbgl/style/function/convert.hpp
+++ b/include/mbgl/style/function/convert.hpp
@@ -55,10 +55,13 @@ struct Convert {
return std::make_unique<Literal>(Value(toExpressionValue(value)));
}
- static std::unique_ptr<Expression> makeGet(type::Type type, const std::string& property, ParsingContext ctx) {
+ static std::unique_ptr<Expression> makeGet(type::Type type, const std::string& property) {
+ ParsingContext ctx;
std::vector<std::unique_ptr<Expression>> getArgs;
getArgs.push_back(makeLiteral(property));
ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx);
+ assert(get);
+ assert(ctx.getErrors().size() == 0);
std::vector<std::unique_ptr<Expression>> assertionArgs;
assertionArgs.push_back(std::move(*get));
@@ -66,8 +69,12 @@ struct Convert {
return std::make_unique<Assertion>(type, std::move(assertionArgs));
}
- static std::unique_ptr<Expression> makeZoom(ParsingContext ctx) {
- return std::move(*(createCompoundExpression("zoom", std::vector<std::unique_ptr<Expression>>(), ctx)));
+ static std::unique_ptr<Expression> makeZoom() {
+ ParsingContext ctx;
+ ParseResult zoom = createCompoundExpression("zoom", std::vector<std::unique_ptr<Expression>>(), ctx);
+ assert(zoom);
+ assert(ctx.getErrors().size() == 0);
+ return std::move(*zoom);
}
static std::unique_ptr<Expression> makeError(std::string message) {
@@ -145,19 +152,16 @@ struct Convert {
type::Type type = valueTypeToExpressionType<T>();
- std::vector<ParsingError> errors;
- ParsingContext ctx(errors);
-
const CategoricalValue& firstKey = stops.begin()->first;
return firstKey.match(
[&](bool) {
- return makeCase(type, makeGet(type::Boolean, property, ctx), std::move(convertedStops));
+ return makeCase(type, makeGet(type::Boolean, property), std::move(convertedStops));
},
[&](const std::string&) {
- return makeMatch<std::string>(type, makeGet(type::String, property, ctx), std::move(convertedStops));
+ return makeMatch<std::string>(type, makeGet(type::String, property), std::move(convertedStops));
},
[&](int64_t) {
- return makeMatch<int64_t>(type, makeGet(type::Number, property, ctx), std::move(convertedStops));
+ return makeMatch<int64_t>(type, makeGet(type::Number, property), std::move(convertedStops));
}
);
}
@@ -177,10 +181,9 @@ struct Convert {
template <typename T>
static std::unique_ptr<Expression> toExpression(const ExponentialStops<T>& stops)
{
- std::vector<ParsingError> errors;
ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(
valueTypeToExpressionType<T>(),
- makeZoom(ParsingContext(errors)),
+ makeZoom(),
convertStops(stops.stops),
ExponentialInterpolator(stops.base));
assert(e);
@@ -190,9 +193,8 @@ struct Convert {
template <typename T>
static std::unique_ptr<Expression> toExpression(const IntervalStops<T>& stops)
{
- std::vector<ParsingError> errors;
ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(ParsingContext(errors)),
+ makeZoom(),
convertStops(stops.stops),
StepInterpolator());
assert(e);
@@ -203,9 +205,8 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const ExponentialStops<T>& stops)
{
- std::vector<ParsingError> errors;
ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeGet(type::Number, property, ParsingContext(errors)),
+ makeGet(type::Number, property),
convertStops(stops.stops),
ExponentialInterpolator(stops.base));
assert(e);
@@ -216,8 +217,7 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const IntervalStops<T>& stops)
{
- std::vector<ParsingError> errors;
- std::unique_ptr<Expression> get = makeGet(type::Number, property, ParsingContext(errors));
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
ParseResult e = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
std::move(get),
convertStops(stops.stops),
@@ -250,10 +250,9 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const CompositeExponentialStops<T>& stops)
{
- std::vector<ParsingError> errors;
std::map<double, std::unique_ptr<Expression>> outerStops;
for (const std::pair<float, std::map<float, T>>& stop : stops.stops) {
- std::unique_ptr<Expression> get = makeGet(type::Number, property, ParsingContext(errors));
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
ParseResult innerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
std::move(get),
convertStops(stop.second),
@@ -262,7 +261,7 @@ struct Convert {
outerStops.emplace(stop.first, std::move(*innerCurve));
}
ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(ParsingContext(errors)),
+ makeZoom(),
std::move(outerStops),
zoomInterpolator<T>());
assert(outerCurve);
@@ -273,10 +272,9 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const CompositeIntervalStops<T>& stops)
{
- std::vector<ParsingError> errors;
std::map<double, std::unique_ptr<Expression>> outerStops;
for (const std::pair<float, std::map<float, T>>& stop : stops.stops) {
- std::unique_ptr<Expression> get = makeGet(type::Number, property, ParsingContext(errors));
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
ParseResult innerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
std::move(get),
convertStops(stop.second),
@@ -285,7 +283,7 @@ struct Convert {
outerStops.emplace(stop.first, std::move(*innerCurve));
}
ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(ParsingContext(errors)),
+ makeZoom(),
std::move(outerStops),
zoomInterpolator<T>());
assert(outerCurve);
@@ -296,7 +294,6 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const CompositeCategoricalStops<T>& stops)
{
- std::vector<ParsingError> errors;
std::map<double, std::unique_ptr<Expression>> outerStops;
for (const std::pair<float, std::map<CategoricalValue, T>>& stop : stops.stops) {
ParseResult innerCurve = fromCategoricalStops(stop.second, property);
@@ -304,7 +301,7 @@ struct Convert {
outerStops.emplace(stop.first, std::move(*innerCurve));
}
ParseResult outerCurve = makeCurve<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
- makeZoom(ParsingContext(errors)),
+ makeZoom(),
std::move(outerStops),
zoomInterpolator<T>());
assert(outerCurve);
@@ -316,27 +313,28 @@ struct Convert {
static std::unique_ptr<Expression> toExpression(const std::string& property,
const IdentityStops<T>&)
{
- std::vector<ParsingError> errors;
-
std::unique_ptr<Expression> input = valueTypeToExpressionType<T>().match(
[&] (const type::StringType&) {
- return makeGet(type::String, property, ParsingContext(errors));
+ return makeGet(type::String, property);
},
[&] (const type::NumberType&) {
- return makeGet(type::Number, property, ParsingContext(errors));
+ return makeGet(type::Number, property);
},
[&] (const type::BooleanType&) {
- return makeGet(type::Boolean, property, ParsingContext(errors));
+ return makeGet(type::Boolean, property);
},
[&] (const type::ColorType&) {
std::vector<std::unique_ptr<Expression>> args;
- args.push_back(makeGet(type::String, property, ParsingContext(errors)));
+ args.push_back(makeGet(type::String, property));
return std::make_unique<Coercion>(type::Color, std::move(args));
},
[&] (const type::Array& arr) {
std::vector<std::unique_ptr<Expression>> getArgs;
getArgs.push_back(makeLiteral(property));
- ParseResult get = createCompoundExpression("get", std::move(getArgs), ParsingContext(errors));
+ ParsingContext ctx;
+ ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx);
+ assert(get);
+ assert(ctx.getErrors().size() == 0);
return std::make_unique<ArrayAssertion>(arr, std::move(*get));
},
[&] (const auto&) -> std::unique_ptr<Expression> {
diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp
index 8ab3e71f9e..bcbd62cfd0 100644
--- a/platform/node/src/node_expression.cpp
+++ b/platform/node/src/node_expression.cpp
@@ -72,10 +72,10 @@ void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto expr = info[0];
try {
- std::vector<ParsingError> errors;
- ParseResult parsed = ParsingContext(errors, expected).parse(mbgl::style::conversion::Convertible(expr));
+ ParsingContext ctx(expected);
+ ParseResult parsed = ctx.parse(mbgl::style::conversion::Convertible(expr));
if (parsed) {
- assert(errors.size() == 0);
+ assert(ctx.getErrors().size() == 0);
auto nodeExpr = new NodeExpression(std::move(*parsed));
const int argc = 0;
v8::Local<v8::Value> argv[0] = {};
@@ -86,8 +86,8 @@ void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
v8::Local<v8::Array> result = Nan::New<v8::Array>();
- for (std::size_t i = 0; i < errors.size(); i++) {
- const auto& error = errors[i];
+ for (std::size_t i = 0; i < ctx.getErrors().size(); i++) {
+ const auto& error = ctx.getErrors()[i];
v8::Local<v8::Object> err = Nan::New<v8::Object>();
Nan::Set(err,
Nan::New("key").ToLocalChecked(),
diff --git a/src/mbgl/style/expression/array_assertion.cpp b/src/mbgl/style/expression/array_assertion.cpp
index 2faa696302..8031868c9c 100644
--- a/src/mbgl/style/expression/array_assertion.cpp
+++ b/src/mbgl/style/expression/array_assertion.cpp
@@ -26,7 +26,7 @@ void ArrayAssertion::eachChild(const std::function<void(const Expression*)>& vis
}
using namespace mbgl::style::conversion;
-ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext& ctx) {
static std::unordered_map<std::string, type::Type> itemTypes {
{"string", type::String},
@@ -69,7 +69,7 @@ ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext ctx)
N = optional<std::size_t>(*n);
}
- auto input = ctx.concat(length - 1, {type::Value}).parse(arrayMember(value, length - 1));
+ auto input = ctx.parse(arrayMember(value, length - 1), length - 1, {type::Value});
if (!input) {
return input;
}
diff --git a/src/mbgl/style/expression/assertion.cpp b/src/mbgl/style/expression/assertion.cpp
index 59b4c6e1ae..3b0846ec63 100644
--- a/src/mbgl/style/expression/assertion.cpp
+++ b/src/mbgl/style/expression/assertion.cpp
@@ -6,7 +6,7 @@ namespace style {
namespace expression {
using namespace mbgl::style::conversion;
-ParseResult Assertion::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Assertion::parse(const Convertible& value, ParsingContext& ctx) {
static std::unordered_map<std::string, type::Type> types {
{"string", type::String},
{"number", type::Number},
@@ -27,7 +27,7 @@ ParseResult Assertion::parse(const Convertible& value, ParsingContext ctx) {
std::vector<std::unique_ptr<Expression>> parsed;
parsed.reserve(length - 1);
for (std::size_t i = 1; i < length; i++) {
- ParseResult input = ctx.concat(i, {type::Value}).parse(arrayMember(value, i));
+ ParseResult input = ctx.parse(arrayMember(value, i), i, {type::Value});
if (!input) return ParseResult();
parsed.push_back(std::move(*input));
}
diff --git a/src/mbgl/style/expression/at.cpp b/src/mbgl/style/expression/at.cpp
index 5c8fddeed1..535ebee8a0 100644
--- a/src/mbgl/style/expression/at.cpp
+++ b/src/mbgl/style/expression/at.cpp
@@ -38,7 +38,7 @@ void At::eachChild(const std::function<void(const Expression*)>& visit) const {
}
using namespace mbgl::style::conversion;
-ParseResult At::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult At::parse(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
std::size_t length = arrayLength(value);
@@ -47,8 +47,10 @@ ParseResult At::parse(const Convertible& value, ParsingContext ctx) {
return ParseResult();
}
- ParseResult index = ctx.concat(1, {type::Number}).parse(arrayMember(value, 1));
- ParseResult input = ctx.concat(2, {type::Array(ctx.expected ? *ctx.expected : type::Value)}).parse(arrayMember(value, 2));
+ ParseResult index = ctx.parse(arrayMember(value, 1), 1, {type::Number});
+
+ type::Type inputType = type::Array(ctx.getExpected() ? *ctx.getExpected() : type::Value);
+ ParseResult input = ctx.parse(arrayMember(value, 2), 2, {inputType});
if (!index || !input) return ParseResult();
diff --git a/src/mbgl/style/expression/boolean_operator.cpp b/src/mbgl/style/expression/boolean_operator.cpp
index 986de99d4b..c960d5d79a 100644
--- a/src/mbgl/style/expression/boolean_operator.cpp
+++ b/src/mbgl/style/expression/boolean_operator.cpp
@@ -37,7 +37,7 @@ void All::eachChild(const std::function<void(const Expression*)>& visit) const {
using namespace mbgl::style::conversion;
template <class T>
-ParseResult parseBooleanOp(const Convertible& value, ParsingContext ctx) {
+ParseResult parseBooleanOp(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
@@ -46,7 +46,7 @@ ParseResult parseBooleanOp(const Convertible& value, ParsingContext ctx) {
parsedInputs.reserve(length - 1);
for (std::size_t i = 1; i < length; i++) {
- auto parsed = ctx.concat(i, {type::Boolean}).parse(arrayMember(value, i));
+ auto parsed = ctx.parse(arrayMember(value, i), i, {type::Boolean});
if (!parsed) {
return parsed;
}
@@ -57,11 +57,11 @@ ParseResult parseBooleanOp(const Convertible& value, ParsingContext ctx) {
return ParseResult(std::make_unique<T>(std::move(parsedInputs)));
}
-ParseResult Any::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Any::parse(const Convertible& value, ParsingContext& ctx) {
return parseBooleanOp<Any>(value, ctx);
}
-ParseResult All::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult All::parse(const Convertible& value, ParsingContext& ctx) {
return parseBooleanOp<All>(value, ctx);
}
diff --git a/src/mbgl/style/expression/case.cpp b/src/mbgl/style/expression/case.cpp
index 8c6c2c0c8f..1d2fd70978 100644
--- a/src/mbgl/style/expression/case.cpp
+++ b/src/mbgl/style/expression/case.cpp
@@ -27,7 +27,7 @@ void Case::eachChild(const std::function<void(const Expression*)>& visit) const
}
using namespace mbgl::style::conversion;
-ParseResult Case::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Case::parse(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
if (length < 4) {
@@ -42,19 +42,19 @@ ParseResult Case::parse(const Convertible& value, ParsingContext ctx) {
}
optional<type::Type> outputType;
- if (ctx.expected && *ctx.expected != type::Value) {
- outputType = ctx.expected;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
}
std::vector<Case::Branch> branches;
branches.reserve((length - 2) / 2);
for (size_t i = 1; i + 1 < length; i += 2) {
- auto test = ctx.concat(i, {type::Boolean}).parse(arrayMember(value, i));
+ auto test = ctx.parse(arrayMember(value, i), i, {type::Boolean});
if (!test) {
return test;
}
- auto output = ctx.concat(i + 1, outputType).parse(arrayMember(value, i + 1));
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
if (!output) {
return output;
}
@@ -68,7 +68,7 @@ ParseResult Case::parse(const Convertible& value, ParsingContext ctx) {
assert(outputType);
- auto otherwise = ctx.concat(length - 1, outputType).parse(arrayMember(value, length - 1));
+ auto otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType);
if (!otherwise) {
return otherwise;
}
diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp
index 784492c51e..54ac0fa499 100644
--- a/src/mbgl/style/expression/coalesce.cpp
+++ b/src/mbgl/style/expression/coalesce.cpp
@@ -20,7 +20,7 @@ void Coalesce::eachChild(const std::function<void(const Expression*)>& visit) co
}
using namespace mbgl::style::conversion;
-ParseResult Coalesce::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Coalesce::parse(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
if (length < 2) {
@@ -29,14 +29,14 @@ ParseResult Coalesce::parse(const Convertible& value, ParsingContext ctx) {
}
optional<type::Type> outputType;
- if (ctx.expected && *ctx.expected != type::Value) {
- outputType = ctx.expected;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
}
Coalesce::Args args;
args.reserve(length - 1);
for (std::size_t i = 1; i < length; i++) {
- auto parsed = ctx.concat(i, outputType).parse(arrayMember(value, i));
+ auto parsed = ctx.parse(arrayMember(value, i), i, outputType);
if (!parsed) {
return parsed;
}
diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp
index a0c4a1abfb..c5a9b80dd5 100644
--- a/src/mbgl/style/expression/coercion.cpp
+++ b/src/mbgl/style/expression/coercion.cpp
@@ -81,7 +81,7 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in
}
using namespace mbgl::style::conversion;
-ParseResult Coercion::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) {
static std::unordered_map<std::string, type::Type> types {
{"to-number", type::Number},
{"to-color", type::Color}
@@ -100,7 +100,7 @@ ParseResult Coercion::parse(const Convertible& value, ParsingContext ctx) {
std::vector<std::unique_ptr<Expression>> parsed;
parsed.reserve(length - 1);
for (std::size_t i = 1; i < length; i++) {
- ParseResult input = ctx.concat(i, {type::Value}).parse(arrayMember(value, i));
+ ParseResult input = ctx.parse(arrayMember(value, i), i, {type::Value});
if (!input) return ParseResult();
parsed.push_back(std::move(*input));
}
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index a08a556480..65ece14328 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/util.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/ignore.hpp>
@@ -437,7 +438,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
std::unordered_map<std::string, Definition> CompoundExpressionRegistry::definitions = initializeDefinitions();
using namespace mbgl::style::conversion;
-ParseResult parseCompoundExpression(const std::string name, const Convertible& value, ParsingContext ctx) {
+ParseResult parseCompoundExpression(const std::string name, const Convertible& value, ParsingContext& ctx) {
assert(isArray(value) && arrayLength(value) > 0);
auto it = CompoundExpressionRegistry::definitions.find(name);
@@ -483,7 +484,7 @@ ParseResult parseCompoundExpression(const std::string name, const Convertible& v
);
}
- auto parsed = ctx.concat(i, expected).parse(arrayMember(value, i));
+ auto parsed = ctx.parse(arrayMember(value, i), i, expected);
if (!parsed) {
return parsed;
}
@@ -495,7 +496,7 @@ ParseResult parseCompoundExpression(const std::string name, const Convertible& v
ParseResult createCompoundExpression(const std::string& name,
std::vector<std::unique_ptr<Expression>> args,
- ParsingContext ctx)
+ ParsingContext& ctx)
{
return createCompoundExpression(name, CompoundExpressionRegistry::definitions.at(name), std::move(args), ctx);
}
@@ -504,16 +505,12 @@ ParseResult createCompoundExpression(const std::string& name,
ParseResult createCompoundExpression(const std::string& name,
const Definition& definition,
std::vector<std::unique_ptr<Expression>> args,
- ParsingContext ctx)
+ ParsingContext& ctx)
{
- std::vector<ParsingError> currentSignatureErrors;
-
- ParsingContext signatureContext(currentSignatureErrors);
- signatureContext.key = ctx.key;
+ ParsingContext signatureContext(ctx.getKey());
for (const std::unique_ptr<detail::SignatureBase>& signature : definition) {
- currentSignatureErrors.clear();
-
+ signatureContext.clearErrors();
if (signature->params.is<std::vector<type::Type>>()) {
const std::vector<type::Type>& params = signature->params.get<std::vector<type::Type>>();
@@ -527,23 +524,29 @@ ParseResult createCompoundExpression(const std::string& name,
for (std::size_t i = 0; i < args.size(); i++) {
const std::unique_ptr<Expression>& arg = args[i];
- signatureContext.concat(i + 1, params.at(i)).checkType(arg->getType());
+ optional<std::string> err = type::checkSubtype(params.at(i), arg->getType());
+ if (err) {
+ signatureContext.error(*err, i + 1);
+ }
}
} else if (signature->params.is<VarargsType>()) {
const type::Type& paramType = signature->params.get<VarargsType>().type;
for (std::size_t i = 0; i < args.size(); i++) {
const std::unique_ptr<Expression>& arg = args[i];
- signatureContext.concat(i + 1, paramType).checkType(arg->getType());
+ optional<std::string> err = type::checkSubtype(paramType, arg->getType());
+ if (err) {
+ signatureContext.error(*err, i + 1);
+ }
}
}
- if (currentSignatureErrors.size() == 0) {
+ if (signatureContext.getErrors().size() == 0) {
return ParseResult(signature->makeExpression(name, std::move(args)));
}
}
if (definition.size() == 1) {
- ctx.errors.insert(ctx.errors.end(), currentSignatureErrors.begin(), currentSignatureErrors.end());
+ ctx.appendErrors(std::move(signatureContext));
} else {
std::string signatures;
for (const auto& signature : definition) {
diff --git a/src/mbgl/style/expression/curve.cpp b/src/mbgl/style/expression/curve.cpp
index d34ac1cadd..d786a147aa 100644
--- a/src/mbgl/style/expression/curve.cpp
+++ b/src/mbgl/style/expression/curve.cpp
@@ -11,7 +11,7 @@ using Interpolator = variant<StepInterpolator,
using namespace mbgl::style::conversion;
-ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
+ParseResult parseCurve(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
@@ -32,7 +32,6 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
bool isStep = false;
const optional<std::string> interpName = toString(arrayMember(interp, 0));
- ParsingContext interpContext = ctx.concat(1);
if (interpName && *interpName == "step") {
interpolator = StepInterpolator();
isStep = true;
@@ -44,7 +43,7 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
base = toDouble(arrayMember(interp, 1));
}
if (!base) {
- interpContext.error("Exponential interpolation requires a numeric base.", 1);
+ ctx.error("Exponential interpolation requires a numeric base.", 1, 1);
return ParseResult();
}
interpolator = ExponentialInterpolator(*base);
@@ -66,13 +65,13 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
*x2 < 0 || *x2 > 1 ||
*y2 < 0 || *y2 > 1
) {
- interpContext.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.");
+ ctx.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.", 1);
return ParseResult();
}
interpolator = CubicBezierInterpolator(*x1, *y1, *x2, *y2);
} else {
- interpContext.error("Unknown interpolation type " + (interpName ? *interpName : ""), 0);
+ ctx.error("Unknown interpolation type " + (interpName ? *interpName : ""), 1, 0);
return ParseResult();
}
@@ -90,15 +89,15 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
}
- ParseResult input = ctx.concat(2, {type::Number}).parse(arrayMember(value, 2));
+ ParseResult input = ctx.parse(arrayMember(value, 2), 2, {type::Number});
if (!input) {
return input;
}
std::map<double, std::unique_ptr<Expression>> stops;
optional<type::Type> outputType;
- if (ctx.expected && *ctx.expected != type::Value) {
- outputType = ctx.expected;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
}
double previous = - std::numeric_limits<double>::infinity();
@@ -107,7 +106,7 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
// than an input level, so consume that output value before proceeding into the
// "stops" loop below.
if (isStep) {
- auto output = ctx.concat(3, outputType).parse(arrayMember(value, 3));
+ auto output = ctx.parse(arrayMember(value, 3), 3, outputType);
if (!output) {
return ParseResult();
}
@@ -163,7 +162,7 @@ ParseResult parseCurve(const Convertible& value, ParsingContext ctx) {
}
previous = *label;
- auto output = ctx.concat(i + 1, outputType).parse(arrayMember(value, i + 1));
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
if (!output) {
return ParseResult();
}
diff --git a/src/mbgl/style/expression/let.cpp b/src/mbgl/style/expression/let.cpp
index d94d80f6d7..daebf5dd08 100644
--- a/src/mbgl/style/expression/let.cpp
+++ b/src/mbgl/style/expression/let.cpp
@@ -18,7 +18,7 @@ void Let::eachChild(const std::function<void(const Expression*)>& visit) const {
using namespace mbgl::style::conversion;
-ParseResult Let::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Let::parse(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
std::size_t length = arrayLength(value);
@@ -44,7 +44,7 @@ ParseResult Let::parse(const Convertible& value, ParsingContext ctx) {
return ParseResult();
}
- ParseResult bindingValue = ctx.concat(i + 1).parse(arrayMember(value, i + 1));
+ ParseResult bindingValue = ctx.parse(arrayMember(value, i + 1), i + 1);
if (!bindingValue) {
return ParseResult();
}
@@ -52,8 +52,7 @@ ParseResult Let::parse(const Convertible& value, ParsingContext ctx) {
bindings_.emplace(*name, std::move(*bindingValue));
}
- auto resultContext = ctx.concat(length - 1, ctx.expected, bindings_);
- ParseResult result_ = resultContext.parse(arrayMember(value, length - 1));
+ ParseResult result_ = ctx.parse(arrayMember(value, length - 1), length - 1, ctx.getExpected(), bindings_);
if (!result_) {
return ParseResult();
}
@@ -67,7 +66,7 @@ EvaluationResult Var::evaluate(const EvaluationContext& params) const {
void Var::eachChild(const std::function<void(const Expression*)>&) const {}
-ParseResult Var::parse(const Convertible& value_, ParsingContext ctx) {
+ParseResult Var::parse(const Convertible& value_, ParsingContext& ctx) {
assert(isArray(value_));
if (arrayLength(value_) != 2 || !toString(arrayMember(value_, 1))) {
diff --git a/src/mbgl/style/expression/literal.cpp b/src/mbgl/style/expression/literal.cpp
index 900ebe2afb..85664f0399 100644
--- a/src/mbgl/style/expression/literal.cpp
+++ b/src/mbgl/style/expression/literal.cpp
@@ -15,7 +15,7 @@ optional<Value> checkNumber(T n) {
}
using namespace mbgl::style::conversion;
-optional<Value> parseValue(const Convertible& value, ParsingContext ctx) {
+optional<Value> parseValue(const Convertible& value, ParsingContext& ctx) {
if (isUndefined(value)) return {Null};
if (isObject(value)) {
std::unordered_map<std::string, Value> result;
@@ -61,7 +61,7 @@ optional<Value> parseValue(const Convertible& value, ParsingContext ctx) {
);
}
-ParseResult Literal::parse(const Convertible& value, ParsingContext ctx) {
+ParseResult Literal::parse(const Convertible& value, ParsingContext& ctx) {
const optional<Value> parsedValue = parseValue(value, ctx);
if (!parsedValue) {
@@ -70,12 +70,12 @@ ParseResult Literal::parse(const Convertible& value, ParsingContext ctx) {
// special case: infer the item type if possible for zero-length arrays
if (
- ctx.expected &&
- ctx.expected->template is<type::Array>() &&
+ ctx.getExpected() &&
+ ctx.getExpected()->template is<type::Array>() &&
parsedValue->template is<std::vector<Value>>()
) {
auto type = typeOf(*parsedValue).template get<type::Array>();
- auto expected = ctx.expected->template get<type::Array>();
+ auto expected = ctx.getExpected()->template get<type::Array>();
if (
type.N && (*type.N == 0) &&
(!expected.N || (*expected.N == 0))
diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp
index 93947813ac..22f6a9f3e5 100644
--- a/src/mbgl/style/expression/match.cpp
+++ b/src/mbgl/style/expression/match.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
namespace mbgl {
@@ -52,7 +53,7 @@ template class Match<std::string>;
using InputType = variant<int64_t, std::string>;
using namespace mbgl::style::conversion;
-optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx, optional<type::Type>& inputType) {
+optional<InputType> parseInputValue(const Convertible& input, ParsingContext& parentContext, std::size_t index, optional<type::Type>& inputType) {
using namespace mbgl::style::conversion;
optional<InputType> result;
optional<type::Type> type;
@@ -63,7 +64,7 @@ optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx
value->match(
[&] (uint64_t n) {
if (!Value::isSafeInteger(n)) {
- ctx.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".");
+ parentContext.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".", index);
} else {
type = {type::Number};
result = {static_cast<int64_t>(n)};
@@ -71,7 +72,7 @@ optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx
},
[&] (int64_t n) {
if (!Value::isSafeInteger(n)) {
- ctx.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".");
+ parentContext.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".", index);
} else {
type = {type::Number};
result = {n};
@@ -79,9 +80,9 @@ optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx
},
[&] (double n) {
if (!Value::isSafeInteger(n)) {
- ctx.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".");
+ parentContext.error("Branch labels must be integers no larger than " + std::to_string(Value::maxSafeInteger()) + ".", index);
} else if (n != std::floor(n)) {
- ctx.error("Numeric branch labels must be integer values.");
+ parentContext.error("Numeric branch labels must be integer values.", index);
} else {
type = {type::Number};
result = {static_cast<int64_t>(n)};
@@ -92,11 +93,11 @@ optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx
result = {s};
},
[&] (const auto&) {
- ctx.error("Branch labels must be numbers or strings.");
+ parentContext.error("Branch labels must be numbers or strings.", index);
}
);
} else {
- ctx.error("Branch labels must be numbers or strings.");
+ parentContext.error("Branch labels must be numbers or strings.", index);
}
if (!type) {
@@ -105,8 +106,12 @@ optional<InputType> parseInputValue(const Convertible& input, ParsingContext ctx
if (!inputType) {
inputType = type;
- } else if (ctx.checkType(*type)) {
- return optional<InputType>();
+ } else {
+ optional<std::string> err = type::checkSubtype(*inputType, *type);
+ if (err) {
+ parentContext.error(*err, index);
+ return optional<InputType>();
+ }
}
return result;
@@ -118,7 +123,7 @@ static ParseResult create(type::Type outputType,
std::vector<std::pair<std::vector<InputType>,
std::unique_ptr<Expression>>> branches,
std::unique_ptr<Expression> otherwise,
- ParsingContext ctx) {
+ ParsingContext& ctx) {
typename Match<T>::Branches typedBranches;
std::size_t index = 2;
@@ -146,7 +151,7 @@ static ParseResult create(type::Type outputType,
));
}
-ParseResult parseMatch(const Convertible& value, ParsingContext ctx) {
+ParseResult parseMatch(const Convertible& value, ParsingContext& ctx) {
assert(isArray(value));
auto length = arrayLength(value);
if (length < 5) {
@@ -164,8 +169,8 @@ ParseResult parseMatch(const Convertible& value, ParsingContext ctx) {
optional<type::Type> inputType;
optional<type::Type> outputType;
- if (ctx.expected && *ctx.expected != type::Value) {
- outputType = ctx.expected;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
}
std::vector<std::pair<std::vector<InputType>,
@@ -181,27 +186,27 @@ ParseResult parseMatch(const Convertible& value, ParsingContext ctx) {
if (isArray(label)) {
auto groupLength = arrayLength(label);
if (groupLength == 0) {
- ctx.concat(i).error("Expected at least one branch label.");
+ ctx.error("Expected at least one branch label.", i);
return ParseResult();
}
labels.reserve(groupLength);
for (size_t j = 0; j < groupLength; j++) {
- const optional<InputType> inputValue = parseInputValue(arrayMember(label, j), ctx.concat(i, inputType), inputType);
+ const optional<InputType> inputValue = parseInputValue(arrayMember(label, j), ctx, i, inputType);
if (!inputValue) {
return ParseResult();
}
labels.push_back(*inputValue);
}
} else {
- const optional<InputType> inputValue = parseInputValue(label, ctx.concat(i, inputType), inputType);
+ const optional<InputType> inputValue = parseInputValue(label, ctx, i, inputType);
if (!inputValue) {
return ParseResult();
}
labels.push_back(*inputValue);
}
- ParseResult output = ctx.concat(i + 1, outputType).parse(arrayMember(value, i + 1));
+ ParseResult output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
if (!output) {
return ParseResult();
}
@@ -213,12 +218,12 @@ ParseResult parseMatch(const Convertible& value, ParsingContext ctx) {
branches.push_back(std::make_pair(std::move(labels), std::move(*output)));
}
- auto input = ctx.concat(1, inputType).parse(arrayMember(value, 1));
+ auto input = ctx.parse(arrayMember(value, 1), 1, inputType);
if (!input) {
return ParseResult();
}
- auto otherwise = ctx.concat(length - 1, outputType).parse(arrayMember(value, length - 1));
+ auto otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType);
if (!otherwise) {
return ParseResult();
}
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index e2447bd7e4..2f855a1ad9 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -50,6 +50,25 @@ bool isConstant(const Expression* expression) {
}
using namespace mbgl::style::conversion;
+
+ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_, optional<type::Type> expected_) {
+ ParsingContext child(key + "[" + std::to_string(index_) + "]",
+ errors,
+ std::move(expected_),
+ scope);
+ return child.parse(value);
+}
+
+ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_, optional<type::Type> expected_,
+ const std::map<std::string, std::shared_ptr<Expression>>& bindings) {
+ ParsingContext child(key + "[" + std::to_string(index_) + "]",
+ errors,
+ std::move(expected_),
+ std::make_shared<detail::Scope>(bindings, scope));
+ return child.parse(value);
+}
+
+using namespace mbgl::style::conversion;
ParseResult ParsingContext::parse(const Convertible& value)
{
ParseResult parsed;
@@ -117,7 +136,7 @@ ParseResult ParsingContext::parse(const Convertible& value)
}
if (!parsed) {
- assert(errors.size() > 0);
+ assert(errors->size() > 0);
} else if (expected) {
auto wrapForType = [&](const type::Type& target, std::unique_ptr<Expression> expression) -> std::unique_ptr<Expression> {
std::vector<std::unique_ptr<Expression>> args;
@@ -137,7 +156,7 @@ ParseResult ParsingContext::parse(const Convertible& value)
}
checkType((*parsed)->getType());
- if (errors.size() > 0) {
+ if (errors->size() > 0) {
return ParseResult();
}
}