Skip to main content

maplibre_expr/
ast.rs

1//! The parsed expression tree.
2
3use crate::typ::Type;
4use crate::value::Value;
5
6/// A parsed MapLibre expression.
7///
8/// Most operators are represented uniformly as [`Expr::Call`]; the handful of
9/// operators with irregular argument shapes (bindings, unquoted match labels,
10/// stop lists) get dedicated variants so evaluation stays simple.
11#[derive(Debug, Clone)]
12pub enum Expr {
13    /// A constant value (bare literal or the `literal` operator).
14    Literal(Value),
15    /// A generic operator call whose arguments are all sub-expressions.
16    Call { op: String, args: Vec<Expr> },
17    /// `["let", name, value, ..., body]`
18    Let {
19        bindings: Vec<(String, Expr)>,
20        body: Box<Expr>,
21    },
22    /// `["var", name]`
23    Var(String),
24    /// `["match", input, label, output, ..., default]`
25    Match {
26        input: Box<Expr>,
27        arms: Vec<(Vec<Value>, Expr)>,
28        default: Box<Expr>,
29    },
30    /// `["step", input, output0, stop1, output1, ...]`
31    Step {
32        input: Box<Expr>,
33        output0: Box<Expr>,
34        stops: Vec<(f64, Expr)>,
35    },
36    /// `["interpolate"|"interpolate-hcl"|"interpolate-lab", type, input, stop, output, ...]`
37    Interpolate {
38        kind: InterpKind,
39        space: InterpSpace,
40        input: Box<Expr>,
41        stops: Vec<(f64, Expr)>,
42        /// Set when the output type is `projectionDefinition`, which is
43        /// interpolated specially (stop outputs stay raw).
44        projection: bool,
45    },
46    /// `["format", content, options?, ...]` — styled text sections.
47    Format(Vec<FormatArg>),
48    /// `["within", geojson]` — the argument polygons as `[lng, lat]` rings
49    /// (a multipolygon: list of polygons, each a list of rings).
50    Within(Vec<Vec<Vec<(f64, f64)>>>),
51    /// `["distance", geojson]` — the argument geometries in `[lng, lat]`.
52    Distance(Vec<crate::distance::SimpleGeom>),
53    /// `["collator", options]` — a locale-aware string collator.
54    Collator {
55        case_sensitive: Option<Box<Expr>>,
56        diacritic_sensitive: Option<Box<Expr>>,
57        locale: Option<Box<Expr>>,
58    },
59    /// `["number-format", value, options]`.
60    NumberFormat {
61        value: Box<Expr>,
62        locale: Option<Box<Expr>>,
63        currency: Option<Box<Expr>>,
64        min_fraction_digits: Option<Box<Expr>>,
65        max_fraction_digits: Option<Box<Expr>>,
66        unit: Option<Box<Expr>>,
67    },
68    /// A runtime type assertion inserted by type checking: the inner expression
69    /// must already produce the given type at runtime, or evaluation errors.
70    Assert(Type, Box<Expr>),
71    /// A runtime coercion inserted by type checking: the inner expression's
72    /// value is converted to the given type (e.g. string → color).
73    Coerce(Type, Box<Expr>),
74}
75
76/// One section of a `format` expression: content plus optional styling.
77#[derive(Debug, Clone)]
78pub struct FormatArg {
79    pub content: Expr,
80    pub scale: Option<Expr>,
81    pub font: Option<Expr>,
82    pub text_color: Option<Expr>,
83    pub vertical_align: Option<Expr>,
84}
85
86/// The interpolation curve used by an `interpolate` expression.
87#[derive(Debug, Clone, Copy)]
88pub enum InterpKind {
89    Linear,
90    Exponential(f64),
91    CubicBezier(f64, f64, f64, f64),
92}
93
94/// The color space an `interpolate` expression blends in.
95#[derive(Debug, Clone, Copy, PartialEq)]
96pub enum InterpSpace {
97    /// Plain component-wise interpolation (`interpolate`).
98    Rgb,
99    /// `interpolate-hcl`
100    Hcl,
101    /// `interpolate-lab`
102    Lab,
103}