Skip to main content

geam_core/plan/module/expression/
utf_codepoint.rs

1use super::{
2    BoolExpr, CallArg, CustomFieldAccess, FloatExpr, IntExpr, PanicExpr, StringExpr, TupleExpr,
3    UtfCodepointFunctionExpr, UtfCodepointListExpr,
4};
5use crate::plan::{FunctionInstantiation, HostCallSite, Step, UtfCodepointLocalId};
6use ecow::EcoString;
7use num_bigint::BigInt;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct UtfCodepointExpr {
11    kind: UtfCodepointExprKind,
12}
13
14#[derive(Debug, Clone, PartialEq)]
15pub(crate) enum UtfCodepointExprKind {
16    LocalGet {
17        local: UtfCodepointLocalId,
18        name: EcoString,
19    },
20    Call {
21        function: FunctionInstantiation,
22        args: Vec<CallArg>,
23        site: HostCallSite,
24    },
25    FunctionCall {
26        function: Box<UtfCodepointFunctionExpr>,
27        args: Vec<CallArg>,
28        site: HostCallSite,
29    },
30    TupleIndex {
31        tuple: Box<TupleExpr>,
32        index: usize,
33    },
34    CustomField(CustomFieldAccess),
35    ListIndex {
36        list: Box<UtfCodepointListExpr>,
37        index: usize,
38    },
39    Panic(PanicExpr),
40    BoolCase {
41        subject: Box<BoolExpr>,
42        true_: Box<UtfCodepointExpr>,
43        false_: Box<UtfCodepointExpr>,
44    },
45    IntCase {
46        subject: Box<IntExpr>,
47        clauses: Vec<(BigInt, UtfCodepointExpr)>,
48        fallback: Box<UtfCodepointExpr>,
49    },
50    StringCase {
51        subject: Box<StringExpr>,
52        clauses: Vec<(EcoString, UtfCodepointExpr)>,
53        fallback: Box<UtfCodepointExpr>,
54    },
55    FloatCase {
56        subject: Box<FloatExpr>,
57        clauses: Vec<(f64, UtfCodepointExpr)>,
58        fallback: Box<UtfCodepointExpr>,
59    },
60    Block {
61        steps: Vec<Step>,
62        return_: Box<UtfCodepointExpr>,
63    },
64}
65
66impl UtfCodepointExpr {
67    pub(crate) fn local_get(local: UtfCodepointLocalId, name: EcoString) -> Self {
68        Self::new(UtfCodepointExprKind::LocalGet { local, name })
69    }
70
71    #[cfg(test)]
72    pub(crate) fn call(function: FunctionInstantiation, args: Vec<CallArg>) -> Self {
73        Self::call_at(function, args, HostCallSite::unknown())
74    }
75
76    pub(crate) fn call_at(
77        function: FunctionInstantiation,
78        args: Vec<CallArg>,
79        site: HostCallSite,
80    ) -> Self {
81        Self::new(UtfCodepointExprKind::Call {
82            function,
83            args,
84            site,
85        })
86    }
87
88    #[cfg(test)]
89    pub(crate) fn function_call(function: UtfCodepointFunctionExpr, args: Vec<CallArg>) -> Self {
90        Self::function_call_at(function, args, HostCallSite::unknown())
91    }
92
93    pub(crate) fn function_call_at(
94        function: UtfCodepointFunctionExpr,
95        args: Vec<CallArg>,
96        site: HostCallSite,
97    ) -> Self {
98        Self::new(UtfCodepointExprKind::FunctionCall {
99            function: Box::new(function),
100            args,
101            site,
102        })
103    }
104
105    pub(crate) fn tuple_index(tuple: TupleExpr, index: usize) -> Self {
106        Self::new(UtfCodepointExprKind::TupleIndex {
107            tuple: Box::new(tuple),
108            index,
109        })
110    }
111
112    pub(crate) fn custom_field(access: CustomFieldAccess) -> Self {
113        Self::new(UtfCodepointExprKind::CustomField(access))
114    }
115
116    pub(crate) fn list_index(list: UtfCodepointListExpr, index: usize) -> Self {
117        Self::new(UtfCodepointExprKind::ListIndex {
118            list: Box::new(list),
119            index,
120        })
121    }
122
123    pub(crate) fn panic(panic: PanicExpr) -> Self {
124        Self::new(UtfCodepointExprKind::Panic(panic))
125    }
126
127    pub(crate) fn bool_case(subject: BoolExpr, true_: Self, false_: Self) -> Self {
128        Self::new(UtfCodepointExprKind::BoolCase {
129            subject: Box::new(subject),
130            true_: Box::new(true_),
131            false_: Box::new(false_),
132        })
133    }
134
135    pub(crate) fn int_case(subject: IntExpr, clauses: Vec<(BigInt, Self)>, fallback: Self) -> Self {
136        Self::new(UtfCodepointExprKind::IntCase {
137            subject: Box::new(subject),
138            clauses,
139            fallback: Box::new(fallback),
140        })
141    }
142
143    pub(crate) fn string_case(
144        subject: StringExpr,
145        clauses: Vec<(EcoString, Self)>,
146        fallback: Self,
147    ) -> Self {
148        Self::new(UtfCodepointExprKind::StringCase {
149            subject: Box::new(subject),
150            clauses,
151            fallback: Box::new(fallback),
152        })
153    }
154
155    pub(crate) fn float_case(
156        subject: FloatExpr,
157        clauses: Vec<(f64, Self)>,
158        fallback: Self,
159    ) -> Self {
160        Self::new(UtfCodepointExprKind::FloatCase {
161            subject: Box::new(subject),
162            clauses,
163            fallback: Box::new(fallback),
164        })
165    }
166
167    pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
168        Self::new(UtfCodepointExprKind::Block {
169            steps,
170            return_: Box::new(return_),
171        })
172    }
173
174    pub(crate) fn kind(&self) -> &UtfCodepointExprKind {
175        &self.kind
176    }
177
178    fn new(kind: UtfCodepointExprKind) -> Self {
179        Self { kind }
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::{UtfCodepointExpr, UtfCodepointExprKind};
186    use crate::plan::{
187        BoolExpr, Expr, FunctionInstantiation, FunctionShape, IntExpr, PanicExpr, PanicSite, Step,
188        StringExpr, TupleExpr, TupleLocalId, UtfCodepointFunctionExpr,
189        UtfCodepointFunctionReference, UtfCodepointListExpr, UtfCodepointListItem,
190        UtfCodepointListLocalId, UtfCodepointLocalId, ValueShape, ValueType,
191        monomorphic_function_instantiation,
192    };
193
194    #[test]
195    fn utf_codepoint_expr_kind_accessors() {
196        assert_eq!(
197            value().kind(),
198            &UtfCodepointExprKind::LocalGet {
199                local: UtfCodepointLocalId(0),
200                name: "value".into(),
201            },
202        );
203        assert_eq!(
204            UtfCodepointExpr::call(function_instantiation(), Vec::new()).kind(),
205            &UtfCodepointExprKind::Call {
206                function: function_instantiation(),
207                args: Vec::new(),
208                site: crate::plan::HostCallSite::unknown(),
209            },
210        );
211        assert_eq!(
212            UtfCodepointExpr::function_call(function(), Vec::new()).kind(),
213            &UtfCodepointExprKind::FunctionCall {
214                function: Box::new(function()),
215                args: Vec::new(),
216                site: crate::plan::HostCallSite::unknown(),
217            },
218        );
219        assert_eq!(
220            UtfCodepointExpr::tuple_index(tuple(), 0).kind(),
221            &UtfCodepointExprKind::TupleIndex {
222                tuple: Box::new(tuple()),
223                index: 0,
224            },
225        );
226        assert_eq!(
227            UtfCodepointExpr::list_index(list(), 0).kind(),
228            &UtfCodepointExprKind::ListIndex {
229                list: Box::new(list()),
230                index: 0,
231            },
232        );
233        let panic = PanicExpr::panic_at(None, PanicSite::unknown());
234        assert_eq!(
235            UtfCodepointExpr::panic(panic.clone()).kind(),
236            &UtfCodepointExprKind::Panic(panic),
237        );
238        assert_eq!(
239            UtfCodepointExpr::bool_case(BoolExpr::value(true), value(), value()).kind(),
240            &UtfCodepointExprKind::BoolCase {
241                subject: Box::new(BoolExpr::value(true)),
242                true_: Box::new(value()),
243                false_: Box::new(value()),
244            },
245        );
246        assert_eq!(
247            UtfCodepointExpr::int_case(
248                IntExpr::value(1.into()),
249                vec![(1.into(), value())],
250                value(),
251            )
252            .kind(),
253            &UtfCodepointExprKind::IntCase {
254                subject: Box::new(IntExpr::value(1.into())),
255                clauses: vec![(1.into(), value())],
256                fallback: Box::new(value()),
257            },
258        );
259        assert_eq!(
260            UtfCodepointExpr::string_case(
261                StringExpr::value("one".into()),
262                vec![("one".into(), value())],
263                value(),
264            )
265            .kind(),
266            &UtfCodepointExprKind::StringCase {
267                subject: Box::new(StringExpr::value("one".into())),
268                clauses: vec![("one".into(), value())],
269                fallback: Box::new(value()),
270            },
271        );
272        assert_eq!(
273            UtfCodepointExpr::float_case(
274                crate::plan::FloatExpr::value(1.0),
275                vec![(1.0, value())],
276                value(),
277            )
278            .kind(),
279            &UtfCodepointExprKind::FloatCase {
280                subject: Box::new(crate::plan::FloatExpr::value(1.0)),
281                clauses: vec![(1.0, value())],
282                fallback: Box::new(value()),
283            },
284        );
285        assert_eq!(
286            UtfCodepointExpr::block(
287                vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
288                value(),
289            )
290            .kind(),
291            &UtfCodepointExprKind::Block {
292                steps: vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
293                return_: Box::new(value()),
294            },
295        );
296    }
297
298    fn value() -> UtfCodepointExpr {
299        UtfCodepointExpr::local_get(UtfCodepointLocalId(0), "value".into())
300    }
301
302    fn function() -> UtfCodepointFunctionExpr {
303        UtfCodepointFunctionExpr::reference(UtfCodepointFunctionReference::new(
304            function_instantiation(),
305        ))
306    }
307
308    fn function_instantiation() -> FunctionInstantiation {
309        monomorphic_function_instantiation(
310            0,
311            FunctionShape::new(vec![ValueShape::UtfCodepoint], ValueShape::UtfCodepoint),
312        )
313    }
314
315    fn tuple() -> TupleExpr {
316        TupleExpr::local_get(
317            TupleLocalId(0),
318            "pair".into(),
319            vec![ValueType::UtfCodepoint],
320        )
321    }
322
323    fn list() -> UtfCodepointListExpr {
324        UtfCodepointListExpr::local_get(
325            UtfCodepointListItem,
326            UtfCodepointListLocalId(0),
327            "values".into(),
328        )
329    }
330}