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}