1 #include <mbgl/style/expression/find_zoom_curve.hpp>
2 #include <mbgl/style/expression/compound_expression.hpp>
3 #include <mbgl/style/expression/let.hpp>
4 #include <mbgl/style/expression/coalesce.hpp>
5 #include <mbgl/style/expression/is_constant.hpp>
6
7 #include <mbgl/util/variant.hpp>
8 #include <mbgl/util/optional.hpp>
9
10 namespace mbgl {
11 namespace style {
12 namespace expression {
13
findZoomCurve(const expression::Expression * e)14 optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCurve(const expression::Expression* e) {
15 optional<variant<const Interpolate*, const Step*, ParsingError>> result;
16
17 switch (e->getKind()) {
18 case Kind::Let: {
19 auto let = static_cast<const Let*>(e);
20 result = findZoomCurve(let->getResult());
21 break;
22 }
23 case Kind::Coalesce: {
24 auto coalesce = static_cast<const Coalesce*>(e);
25 std::size_t length = coalesce->getLength();
26 for (std::size_t i = 0; i < length; i++) {
27 result = findZoomCurve(coalesce->getChild(i));
28 if (result) {
29 break;
30 }
31 }
32 break;
33 }
34 case Kind::Interpolate: {
35 auto curve = static_cast<const Interpolate*>(e);
36 if (curve->getInput()->getKind() == Kind::CompoundExpression) {
37 auto z = static_cast<CompoundExpressionBase*>(curve->getInput().get());
38 if (z && z->getName() == "zoom") {
39 result = {curve};
40 }
41 }
42 break;
43 }
44 case Kind::Step: {
45 auto step = static_cast<const Step*>(e);
46 if (step->getInput()->getKind() == Kind::CompoundExpression) {
47 auto z = static_cast<CompoundExpressionBase*>(step->getInput().get());
48 if (z && z->getName() == "zoom") {
49 result = {step};
50 }
51 }
52 break;
53 }
54 default:
55 break;
56 }
57
58 if (result && result->is<ParsingError>()) {
59 return result;
60 }
61
62 e->eachChild([&](const Expression& child) {
63 optional<variant<const Interpolate*, const Step*, ParsingError>> childResult(findZoomCurve(&child));
64 if (childResult) {
65 if (childResult->is<ParsingError>()) {
66 result = childResult;
67 } else if (!result && childResult) {
68 result = {ParsingError {
69 R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)", ""
70 }};
71 } else if (result && childResult && result != childResult) {
72 result = {ParsingError {
73 R"(Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.)", ""
74 }};
75 }
76 }
77 });
78
79 return result;
80 }
81
findZoomCurveChecked(const expression::Expression * e)82 variant<std::nullptr_t, const Interpolate*, const Step*> findZoomCurveChecked(const expression::Expression* e) {
83 if (isZoomConstant(*e)) {
84 return nullptr;
85 }
86 return findZoomCurve(e)->match(
87 [](const ParsingError&) -> variant<std::nullptr_t, const Interpolate*, const Step*> {
88 assert(false);
89 return nullptr;
90 },
91 [](auto zoomCurve) -> variant<std::nullptr_t, const Interpolate*, const Step*> {
92 return zoomCurve;
93 }
94 );
95 }
96
97 } // namespace expression
98 } // namespace style
99 } // namespace mbgl
100