#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace expression { namespace detail { class ErrorExpression : public Expression { public: ErrorExpression(std::string message_) : Expression(type::Error), message(std::move(message_)) {} void eachChild(const std::function&) const override {} bool operator==(const Expression& e) const override { return dynamic_cast(&e); } EvaluationResult evaluate(const EvaluationContext&) const override { return EvaluationError{message}; } std::vector> possibleOutputs() const override { return {}; } std::string getOperator() const override { return "error"; } private: std::string message; }; } // namespace detail // Create expressions representing 'classic' (i.e. stop-based) style functions struct Convert { template static std::unique_ptr makeLiteral(const T& value) { return std::make_unique(Value(toExpressionValue(value))); } static std::unique_ptr makeGet(type::Type type, const std::string& property) { ParsingContext ctx; std::vector> getArgs; getArgs.push_back(makeLiteral(property)); ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx); assert(get); assert(ctx.getErrors().size() == 0); std::vector> assertionArgs; assertionArgs.push_back(std::move(*get)); return std::make_unique(type, std::move(assertionArgs)); } static std::unique_ptr makeZoom() { ParsingContext ctx; ParseResult zoom = createCompoundExpression("zoom", std::vector>(), ctx); assert(zoom); assert(ctx.getErrors().size() == 0); return std::move(*zoom); } static std::unique_ptr makeError(std::string message) { return std::make_unique(message); } template static ParseResult makeInterpolate(type::Type type, std::unique_ptr input, std::map> convertedStops, typename Interpolate::Interpolator interpolator) { ParseResult curve = ParseResult(std::make_unique>( std::move(type), std::move(interpolator), std::move(input), std::move(convertedStops) )); assert(curve); return std::move(*curve); } template static ParseResult makeMatch(type::Type type, std::unique_ptr input, std::map> stops) { // match expression typename Match::Branches branches; for(auto it = stops.begin(); it != stops.end(); it++) { assert(it->first.template is()); Key key = it->first.template get(); branches.emplace( std::move(key), std::move(it->second) ); } return ParseResult(std::make_unique>(std::move(type), std::move(input), std::move(branches), makeError("No matching label"))); } static ParseResult makeCase(type::Type type, std::unique_ptr input, std::map> stops) { // case expression std::vector branches; auto it = stops.find(true); std::unique_ptr true_case = it == stops.end() ? makeError("No matching label") : std::move(it->second); it = stops.find(false); std::unique_ptr false_case = it == stops.end() ? makeError("No matching label") : std::move(it->second); branches.push_back(std::make_pair(std::move(input), std::move(true_case))); return ParseResult(std::make_unique(std::move(type), std::move(branches), std::move(false_case))); } template static ParseResult fromCategoricalStops(std::map stops, const std::string& property) { assert(stops.size() > 0); std::map> convertedStops; for(const std::pair& stop : stops) { convertedStops.emplace( stop.first, makeLiteral(stop.second) ); } type::Type type = valueTypeToExpressionType(); const CategoricalValue& firstKey = stops.begin()->first; return firstKey.match( [&](bool) { return makeCase(type, makeGet(type::Boolean, property), std::move(convertedStops)); }, [&](const std::string&) { return makeMatch(type, makeGet(type::String, property), std::move(convertedStops)); }, [&](int64_t) { return makeMatch(type, makeGet(type::Number, property), std::move(convertedStops)); } ); } template static std::map> convertStops(const std::map& stops) { std::map> convertedStops; for(const auto& stop : stops) { convertedStops.emplace( stop.first, makeLiteral(stop.second) ); } return convertedStops; } template static std::unique_ptr toExpression(const ExponentialStops& stops) { ParseResult e = makeInterpolate::ExpressionType>( valueTypeToExpressionType(), makeZoom(), convertStops(stops.stops), ExponentialInterpolator(stops.base)); assert(e); return std::move(*e); } template static std::unique_ptr toExpression(const IntervalStops& stops) { ParseResult e(std::make_unique(valueTypeToExpressionType(), makeZoom(), convertStops(stops.stops))); assert(e); return std::move(*e); } template static std::unique_ptr toExpression(const std::string& property, const ExponentialStops& stops) { ParseResult e = makeInterpolate::ExpressionType>(valueTypeToExpressionType(), makeGet(type::Number, property), convertStops(stops.stops), ExponentialInterpolator(stops.base)); assert(e); return std::move(*e); } template static std::unique_ptr toExpression(const std::string& property, const IntervalStops& stops) { std::unique_ptr get = makeGet(type::Number, property); ParseResult e(std::make_unique(valueTypeToExpressionType(), std::move(get), convertStops(stops.stops))); assert(e); return std::move(*e); } template static std::unique_ptr toExpression(const std::string& property, const CategoricalStops& stops) { ParseResult expr = fromCategoricalStops(stops.stops, property); assert(expr); return std::move(*expr); } // interpolatable zoom curve template static typename std::enable_if_t::value, ParseResult> makeZoomCurve(std::map> stops) { return makeInterpolate::ExpressionType>(valueTypeToExpressionType(), makeZoom(), std::move(stops), ExponentialInterpolator(1.0)); } // non-interpolatable zoom curve template static typename std::enable_if_t::value, ParseResult> makeZoomCurve(std::map> stops) { return ParseResult(std::make_unique(valueTypeToExpressionType(), makeZoom(), std::move(stops))); } template static std::unique_ptr toExpression(const std::string& property, const CompositeExponentialStops& stops) { std::map> outerStops; for (const std::pair>& stop : stops.stops) { std::unique_ptr get = makeGet(type::Number, property); ParseResult innerInterpolate = makeInterpolate::ExpressionType>(valueTypeToExpressionType(), std::move(get), convertStops(stop.second), ExponentialInterpolator(stops.base)); assert(innerInterpolate); outerStops.emplace(stop.first, std::move(*innerInterpolate)); } ParseResult zoomCurve = makeZoomCurve(std::move(outerStops)); assert(zoomCurve); return std::move(*zoomCurve); } template static std::unique_ptr toExpression(const std::string& property, const CompositeIntervalStops& stops) { std::map> outerStops; for (const std::pair>& stop : stops.stops) { std::unique_ptr get = makeGet(type::Number, property); ParseResult innerInterpolate(std::make_unique(valueTypeToExpressionType(), std::move(get), convertStops(stop.second))); assert(innerInterpolate); outerStops.emplace(stop.first, std::move(*innerInterpolate)); } ParseResult zoomCurve = makeZoomCurve(std::move(outerStops)); assert(zoomCurve); return std::move(*zoomCurve); } template static std::unique_ptr toExpression(const std::string& property, const CompositeCategoricalStops& stops) { std::map> outerStops; for (const std::pair>& stop : stops.stops) { ParseResult innerInterpolate = fromCategoricalStops(stop.second, property); assert(innerInterpolate); outerStops.emplace(stop.first, std::move(*innerInterpolate)); } ParseResult zoomCurve = makeZoomCurve(std::move(outerStops)); assert(zoomCurve); return std::move(*zoomCurve); } static std::unique_ptr fromIdentityFunction(type::Type type, const std::string& property) { std::unique_ptr input = type.match( [&] (const type::StringType&) { return makeGet(type::String, property); }, [&] (const type::NumberType&) { return makeGet(type::Number, property); }, [&] (const type::BooleanType&) { return makeGet(type::Boolean, property); }, [&] (const type::ColorType&) { std::vector> args; args.push_back(makeGet(type::String, property)); return std::make_unique(type::Color, std::move(args)); }, [&] (const type::Array& arr) { std::vector> getArgs; getArgs.push_back(makeLiteral(property)); ParsingContext ctx; ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx); assert(get); assert(ctx.getErrors().size() == 0); return std::make_unique(arr, std::move(*get)); }, [&] (const auto&) -> std::unique_ptr { return makeLiteral(Null); } ); return input; } }; } // namespace expression } // namespace style } // namespace mbgl