Skip to main content

geam_core/plan/module/expression/
tuple.rs

1use super::{
2    BoolExpr, CallArg, CustomFieldAccess, FloatExpr, IntExpr, PanicExpr, StringExpr,
3    TupleFunctionExpr, TupleListExpr,
4};
5use crate::plan::{ConstantTupleReference, FunctionInstantiation, Step, TupleLocalId, ValueType};
6use ecow::EcoString;
7use num_bigint::BigInt;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct TupleExpr {
11    type_: Vec<ValueType>,
12    shape: Box<[crate::plan::ValueShape]>,
13    kind: TupleExprKind,
14}
15
16#[derive(Debug, Clone, PartialEq)]
17pub(crate) enum TupleExprKind {
18    Value(Vec<super::Expr>),
19    Constant(ConstantTupleReference),
20    LocalGet {
21        local: TupleLocalId,
22        name: EcoString,
23    },
24    Call {
25        function: FunctionInstantiation,
26        args: Vec<CallArg>,
27        site: crate::plan::HostCallSite,
28    },
29    FunctionCall {
30        function: Box<TupleFunctionExpr>,
31        args: Vec<CallArg>,
32        site: crate::plan::HostCallSite,
33    },
34    TupleIndex {
35        tuple: Box<TupleExpr>,
36        index: usize,
37    },
38    CustomField(CustomFieldAccess),
39    ListIndex {
40        list: Box<TupleListExpr>,
41        index: usize,
42    },
43    Panic(PanicExpr),
44    BoolCase {
45        subject: Box<BoolExpr>,
46        true_: Box<TupleExpr>,
47        false_: Box<TupleExpr>,
48    },
49    IntCase {
50        subject: Box<IntExpr>,
51        clauses: Vec<(BigInt, TupleExpr)>,
52        fallback: Box<TupleExpr>,
53    },
54    StringCase {
55        subject: Box<StringExpr>,
56        clauses: Vec<(EcoString, TupleExpr)>,
57        fallback: Box<TupleExpr>,
58    },
59    FloatCase {
60        subject: Box<FloatExpr>,
61        clauses: Vec<(f64, TupleExpr)>,
62        fallback: Box<TupleExpr>,
63    },
64    Block {
65        steps: Vec<Step>,
66        return_: Box<TupleExpr>,
67    },
68}
69
70impl TupleExpr {
71    pub(crate) fn value(elements: Vec<super::Expr>, type_: Vec<ValueType>) -> Self {
72        let shape = elements
73            .iter()
74            .map(|element| element.value_shape().clone())
75            .collect::<Vec<_>>()
76            .into_boxed_slice();
77        Self {
78            type_,
79            shape,
80            kind: TupleExprKind::Value(elements),
81        }
82    }
83
84    pub(in crate::plan::module) fn constant(reference: ConstantTupleReference) -> Self {
85        let type_ = reference
86            .shape()
87            .iter()
88            .map(crate::plan::ValueShape::value_type)
89            .collect();
90        let shape = reference.shape().to_vec().into_boxed_slice();
91        Self {
92            type_,
93            shape,
94            kind: TupleExprKind::Constant(reference),
95        }
96    }
97
98    pub(crate) fn local_get(local: TupleLocalId, name: EcoString, type_: Vec<ValueType>) -> Self {
99        Self::new(type_, TupleExprKind::LocalGet { local, name })
100    }
101
102    #[cfg(test)]
103    pub(crate) fn call(
104        function: FunctionInstantiation,
105        args: Vec<CallArg>,
106        type_: Vec<ValueType>,
107    ) -> Self {
108        Self::call_at(function, args, type_, crate::plan::HostCallSite::unknown())
109    }
110
111    pub(crate) fn call_at(
112        function: FunctionInstantiation,
113        args: Vec<CallArg>,
114        type_: Vec<ValueType>,
115        site: crate::plan::HostCallSite,
116    ) -> Self {
117        Self::new(
118            type_,
119            TupleExprKind::Call {
120                function,
121                args,
122                site,
123            },
124        )
125    }
126
127    #[cfg(test)]
128    pub(crate) fn function_call(
129        function: TupleFunctionExpr,
130        args: Vec<CallArg>,
131        type_: Vec<ValueType>,
132    ) -> Self {
133        Self::function_call_at(function, args, type_, crate::plan::HostCallSite::unknown())
134    }
135
136    pub(crate) fn function_call_at(
137        function: TupleFunctionExpr,
138        args: Vec<CallArg>,
139        type_: Vec<ValueType>,
140        site: crate::plan::HostCallSite,
141    ) -> Self {
142        Self::new(
143            type_,
144            TupleExprKind::FunctionCall {
145                function: Box::new(function),
146                args,
147                site,
148            },
149        )
150    }
151
152    pub(crate) fn tuple_index(tuple: TupleExpr, index: usize, type_: Vec<ValueType>) -> Self {
153        Self::new(
154            type_,
155            TupleExprKind::TupleIndex {
156                tuple: Box::new(tuple),
157                index,
158            },
159        )
160    }
161
162    pub(crate) fn custom_field(access: CustomFieldAccess, type_: Vec<ValueType>) -> Self {
163        Self::new(type_, TupleExprKind::CustomField(access))
164    }
165
166    pub(crate) fn list_index(
167        list: impl Into<TupleListExpr>,
168        index: usize,
169        type_: Vec<ValueType>,
170    ) -> Self {
171        Self::new(
172            type_,
173            TupleExprKind::ListIndex {
174                list: Box::new(list.into()),
175                index,
176            },
177        )
178    }
179
180    pub(crate) fn panic(panic: PanicExpr, type_: Vec<ValueType>) -> Self {
181        Self::new(type_, TupleExprKind::Panic(panic))
182    }
183
184    pub(crate) fn bool_case(subject: BoolExpr, true_: TupleExpr, false_: TupleExpr) -> Self {
185        Self::new(
186            true_.type_.clone(),
187            TupleExprKind::BoolCase {
188                subject: Box::new(subject),
189                true_: Box::new(true_),
190                false_: Box::new(false_),
191            },
192        )
193    }
194
195    pub(crate) fn int_case(
196        subject: IntExpr,
197        clauses: Vec<(BigInt, TupleExpr)>,
198        fallback: TupleExpr,
199    ) -> Self {
200        Self::new(
201            fallback.type_.clone(),
202            TupleExprKind::IntCase {
203                subject: Box::new(subject),
204                clauses,
205                fallback: Box::new(fallback),
206            },
207        )
208    }
209
210    pub(crate) fn string_case(
211        subject: StringExpr,
212        clauses: Vec<(EcoString, TupleExpr)>,
213        fallback: TupleExpr,
214    ) -> Self {
215        Self::new(
216            fallback.type_.clone(),
217            TupleExprKind::StringCase {
218                subject: Box::new(subject),
219                clauses,
220                fallback: Box::new(fallback),
221            },
222        )
223    }
224
225    pub(crate) fn float_case(
226        subject: FloatExpr,
227        clauses: Vec<(f64, TupleExpr)>,
228        fallback: TupleExpr,
229    ) -> Self {
230        Self::new(
231            fallback.type_.clone(),
232            TupleExprKind::FloatCase {
233                subject: Box::new(subject),
234                clauses,
235                fallback: Box::new(fallback),
236            },
237        )
238    }
239
240    pub(crate) fn block(steps: Vec<Step>, return_: TupleExpr) -> Self {
241        Self::new(
242            return_.type_.clone(),
243            TupleExprKind::Block {
244                steps,
245                return_: Box::new(return_),
246            },
247        )
248    }
249
250    pub fn type_(&self) -> &[ValueType] {
251        &self.type_
252    }
253
254    pub(crate) fn kind(&self) -> &TupleExprKind {
255        &self.kind
256    }
257
258    pub(crate) fn shape(&self) -> &[crate::plan::ValueShape] {
259        &self.shape
260    }
261
262    pub(crate) fn with_shape(mut self, shape: Box<[crate::plan::ValueShape]>) -> Self {
263        self.shape = shape;
264        self
265    }
266
267    fn new(type_: Vec<ValueType>, kind: TupleExprKind) -> Self {
268        let shape = type_
269            .iter()
270            .cloned()
271            .map(crate::plan::ValueShape::from_value_type)
272            .collect::<Vec<_>>()
273            .into_boxed_slice();
274        Self { type_, shape, kind }
275    }
276}
277
278#[cfg(test)]
279mod tests {
280    use super::{TupleExpr, TupleExprKind};
281    use crate::plan::{
282        BoolExpr, Expr, FunctionInstantiation, FunctionShape, FunctionType, IntExpr, Step,
283        TupleFunctionExpr, TupleFunctionReference, TupleLocalId, ValueShape, ValueType,
284        monomorphic_function_instantiation,
285    };
286
287    #[test]
288    fn tuple_expr_kind_accessors() {
289        assert_eq!(
290            tuple_value().kind(),
291            &TupleExprKind::Value(vec![Expr::int(IntExpr::value(1.into()))]),
292        );
293        assert_eq!(
294            TupleExpr::local_get(TupleLocalId(0), "pair".into(), tuple_type()).kind(),
295            &TupleExprKind::LocalGet {
296                local: TupleLocalId(0),
297                name: "pair".into(),
298            },
299        );
300        assert_eq!(
301            TupleExpr::call(function_instantiation(), Vec::new(), tuple_type()).kind(),
302            &TupleExprKind::Call {
303                function: function_instantiation(),
304                args: Vec::new(),
305                site: crate::plan::HostCallSite::unknown(),
306            },
307        );
308        assert_eq!(
309            TupleExpr::function_call(tuple_function_expr(), Vec::new(), tuple_type()).kind(),
310            &TupleExprKind::FunctionCall {
311                function: Box::new(tuple_function_expr()),
312                args: Vec::new(),
313                site: crate::plan::HostCallSite::unknown(),
314            },
315        );
316        assert_eq!(
317            TupleExpr::tuple_index(tuple_value(), 0, tuple_type()).kind(),
318            &TupleExprKind::TupleIndex {
319                tuple: Box::new(tuple_value()),
320                index: 0,
321            },
322        );
323        assert_eq!(
324            TupleExpr::bool_case(BoolExpr::value(true), tuple_value(), tuple_value()).kind(),
325            &TupleExprKind::BoolCase {
326                subject: Box::new(BoolExpr::value(true)),
327                true_: Box::new(tuple_value()),
328                false_: Box::new(tuple_value()),
329            },
330        );
331        assert_eq!(
332            TupleExpr::int_case(
333                IntExpr::value(1.into()),
334                vec![(1.into(), tuple_value())],
335                tuple_value(),
336            )
337            .kind(),
338            &TupleExprKind::IntCase {
339                subject: Box::new(IntExpr::value(1.into())),
340                clauses: vec![(1.into(), tuple_value())],
341                fallback: Box::new(tuple_value()),
342            },
343        );
344        assert_eq!(
345            TupleExpr::string_case(
346                crate::plan::StringExpr::value("one".into()),
347                vec![("one".into(), tuple_value())],
348                tuple_value(),
349            )
350            .kind(),
351            &TupleExprKind::StringCase {
352                subject: Box::new(crate::plan::StringExpr::value("one".into())),
353                clauses: vec![("one".into(), tuple_value())],
354                fallback: Box::new(tuple_value()),
355            },
356        );
357        assert_eq!(
358            TupleExpr::float_case(
359                crate::plan::FloatExpr::value(1.0),
360                vec![(1.0, tuple_value())],
361                tuple_value(),
362            )
363            .kind(),
364            &TupleExprKind::FloatCase {
365                subject: Box::new(crate::plan::FloatExpr::value(1.0)),
366                clauses: vec![(1.0, tuple_value())],
367                fallback: Box::new(tuple_value()),
368            },
369        );
370        assert_eq!(
371            TupleExpr::block(
372                vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
373                tuple_value(),
374            )
375            .kind(),
376            &TupleExprKind::Block {
377                steps: vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
378                return_: Box::new(tuple_value()),
379            },
380        );
381    }
382
383    #[test]
384    fn tuple_expr_type() {
385        assert_eq!(tuple_value().type_(), tuple_type());
386        assert_eq!(
387            TupleExpr::bool_case(BoolExpr::value(true), tuple_value(), tuple_value()).type_(),
388            tuple_type(),
389        );
390        assert_eq!(
391            TupleExpr::int_case(
392                IntExpr::value(1.into()),
393                vec![(1.into(), tuple_value())],
394                tuple_value(),
395            )
396            .type_(),
397            tuple_type(),
398        );
399        assert_eq!(
400            TupleExpr::string_case(
401                crate::plan::StringExpr::value("one".into()),
402                vec![("one".into(), tuple_value())],
403                tuple_value(),
404            )
405            .type_(),
406            tuple_type(),
407        );
408        assert_eq!(
409            TupleExpr::float_case(
410                crate::plan::FloatExpr::value(1.0),
411                vec![(1.0, tuple_value())],
412                tuple_value(),
413            )
414            .type_(),
415            tuple_type(),
416        );
417        assert_eq!(
418            TupleExpr::block(Vec::new(), tuple_value()).type_(),
419            tuple_type(),
420        );
421    }
422
423    fn tuple_value() -> TupleExpr {
424        TupleExpr::value(
425            vec![Expr::int(IntExpr::value(1.into()))],
426            vec![ValueType::Int],
427        )
428    }
429
430    fn tuple_type() -> Vec<ValueType> {
431        vec![ValueType::Int]
432    }
433
434    fn tuple_function_expr() -> TupleFunctionExpr {
435        TupleFunctionExpr::reference(TupleFunctionReference::new(function_instantiation()))
436    }
437
438    fn function_instantiation() -> FunctionInstantiation {
439        monomorphic_function_instantiation(
440            0,
441            FunctionShape::new(
442                Vec::new(),
443                ValueShape::Tuple(vec![ValueShape::Int].into_boxed_slice()),
444            ),
445        )
446    }
447
448    #[test]
449    fn tuple_function_value_type_fixture() {
450        assert_eq!(
451            tuple_function_expr().type_(),
452            &FunctionType::new(Vec::new(), ValueType::Tuple(tuple_type())),
453        );
454    }
455}