#include #include #include #include #include #include #include namespace mbgl { namespace style { namespace expression { optional> findZoomCurve(const expression::Expression* e) { optional> result; switch (e->getKind()) { case Kind::Let: { auto let = static_cast(e); result = findZoomCurve(let->getResult()); break; } case Kind::Coalesce: { auto coalesce = static_cast(e); std::size_t length = coalesce->getLength(); for (std::size_t i = 0; i < length; i++) { result = findZoomCurve(coalesce->getChild(i)); if (result) { break; } } break; } case Kind::Interpolate: { auto curve = static_cast(e); if (curve->getInput()->getKind() == Kind::CompoundExpression) { auto z = static_cast(curve->getInput().get()); if (z && z->getName() == "zoom") { result = {curve}; } } break; } case Kind::Step: { auto step = static_cast(e); if (step->getInput()->getKind() == Kind::CompoundExpression) { auto z = static_cast(step->getInput().get()); if (z && z->getName() == "zoom") { result = {step}; } } break; } default: break; } if (result && result->is()) { return result; } e->eachChild([&](const Expression& child) { optional> childResult(findZoomCurve(&child)); if (childResult) { if (childResult->is()) { result = childResult; } else if (!result && childResult) { result = {ParsingError { R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)", "" }}; } else if (result && childResult && result != childResult) { result = {ParsingError { R"(Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.)", "" }}; } } }); return result; } variant findZoomCurveChecked(const expression::Expression* e) { if (isZoomConstant(*e)) { return nullptr; } return findZoomCurve(e)->match( [](const ParsingError&) -> variant { assert(false); return nullptr; }, [](auto zoomCurve) -> variant { return zoomCurve; } ); } } // namespace expression } // namespace style } // namespace mbgl