Skip to main content

geam_core/plan/module/
expression.rs

1mod arg;
2mod bit_array;
3mod bool;
4mod case;
5mod custom;
6mod custom_field;
7mod external;
8mod float;
9mod function;
10mod generic;
11mod int;
12mod list;
13mod nil;
14mod panic;
15mod string;
16mod tuple;
17mod utf_codepoint;
18
19use crate::plan::{Step, ValueShape, ValueType};
20
21pub(crate) use self::case::{
22    BoolCaseBranches, FloatCaseBranches, IntCaseBranches, StringCaseBranches,
23};
24pub(crate) use self::function::TypedFunctionExpr;
25pub use self::{
26    arg::CallArg,
27    bit_array::BitArrayExpr,
28    bool::BoolExpr,
29    custom::CustomExpr,
30    external::ExternalExpr,
31    float::FloatExpr,
32    function::{
33        BitArrayFunctionExpr, BoolFunctionExpr, CustomFunctionExpr, ExternalFunctionExpr,
34        FloatFunctionExpr, FunctionExpr, FunctionFunctionExpr, IntFunctionExpr, ListFunctionExpr,
35        NilFunctionExpr, StringFunctionExpr, TupleFunctionExpr, UtfCodepointFunctionExpr,
36    },
37    int::IntExpr,
38    nil::NilExpr,
39    string::StringExpr,
40    tuple::TupleExpr,
41    utf_codepoint::UtfCodepointExpr,
42};
43pub(crate) use self::{
44    arg::{CallArgStorage, CaptureArg, PotentiallyUninhabitedCallArg},
45    bit_array::{
46        BitArrayBitsSize, BitArrayEvaluatedSize, BitArrayExprKind, BitArraySegment, Endianness,
47        FloatBitSize, StringEncoding,
48    },
49    bool::BoolExprKind,
50    custom::{
51        CustomBoolCaseBranches, CustomCaseBranches, CustomConstruction, CustomExprKind,
52        CustomLocalExpr, custom_constructor_expr,
53    },
54    custom_field::CustomFieldAccess,
55    external::ExternalExprKind,
56    float::FloatExprKind,
57    function::{
58        BitArrayFunctionExprKind, BoolFunctionExprKind, CustomFunctionExprKind,
59        ExternalFunctionExprKind, FloatFunctionExprKind, FunctionExprKind,
60        FunctionFunctionExprKind, GenericFunctionExpr, GenericFunctionExprKind,
61        IntFunctionExprKind, ListFunctionExprKind, NilFunctionExprKind, StringFunctionExprKind,
62        TupleFunctionExprKind, TypedFunctionExprKind, UtfCodepointFunctionExprKind,
63    },
64    generic::{GenericExpr, GenericExprKind},
65    int::IntExprKind,
66    list::{
67        BitArrayListExpr, BitArrayListItem, BoolListCaseBranches, BoolListExpr, BoolListItem,
68        CustomListExpr, CustomListItem, ExternalListExpr, ExternalListItem, FloatListExpr,
69        FloatListItem, FunctionListExpr, FunctionListItem, GenericListExpr, GenericListItem,
70        IntListExpr, IntListItem, ListCaseBranches, ListElements, ListExpr, ListItem, ListListExpr,
71        ListListItem, ListLocalExpr, ListSpreadConstructionError, ListSpreadElements, NilListExpr,
72        NilListItem, ParameterListListExpr, ParameterListListItem, StoredListExpr, StringListExpr,
73        StringListItem, TupleListExpr, TupleListItem, TypedListExpr, TypedListExprKind,
74        TypedListReturnKind, UtfCodepointListExpr, UtfCodepointListItem,
75    },
76    nil::NilExprKind,
77    panic::{PanicExpr, PanicExprKind},
78    string::StringExprKind,
79    tuple::TupleExprKind,
80    utf_codepoint::UtfCodepointExprKind,
81};
82
83#[derive(Debug, Clone, PartialEq)]
84pub struct Expr {
85    shape: crate::plan::ValueShape,
86    kind: ExprKind,
87}
88
89#[derive(Debug, Clone, PartialEq)]
90pub(crate) enum ExprKind {
91    Generic(GenericExpr),
92    Int(IntExpr),
93    String(StringExpr),
94    BitArray(BitArrayExpr),
95    UtfCodepoint(UtfCodepointExpr),
96    Custom(CustomExpr),
97    External(ExternalExpr),
98    Float(FloatExpr),
99    Bool(BoolExpr),
100    Nil(NilExpr),
101    Tuple(TupleExpr),
102    List(ListExpr),
103    Function(FunctionExpr),
104}
105
106impl Expr {
107    pub(crate) fn shape(&self) -> &crate::plan::ValueShape {
108        &self.shape
109    }
110
111    pub(crate) fn with_shape(self, shape: crate::plan::ValueShape) -> Option<Self> {
112        let Self {
113            shape: current,
114            kind,
115        } = self;
116        match (shape, kind) {
117            (crate::plan::ValueShape::Function(shape), ExprKind::Function(expression)) => {
118                let expression = expression.with_shape(*shape)?;
119                Some(Self {
120                    shape: crate::plan::ValueShape::Function(Box::new(expression.shape().clone())),
121                    kind: ExprKind::Function(expression),
122                })
123            }
124            (shape, kind) => {
125                if shape.value_type() != current.value_type() {
126                    return None;
127                }
128                let shape = current.refine(&shape)?;
129                Self {
130                    shape: current,
131                    kind,
132                }
133                .with_resolved_shape(shape)
134            }
135        }
136    }
137
138    pub(crate) fn with_resolved_shape(self, shape: crate::plan::ValueShape) -> Option<Self> {
139        let kind = match (shape.clone(), self.kind) {
140            (crate::plan::ValueShape::Parameter(parameter), ExprKind::Generic(expression))
141                if expression.parameter() == parameter =>
142            {
143                ExprKind::Generic(expression)
144            }
145            (crate::plan::ValueShape::Int, ExprKind::Int(expression)) => ExprKind::Int(expression),
146            (crate::plan::ValueShape::String, ExprKind::String(expression)) => {
147                ExprKind::String(expression)
148            }
149            (crate::plan::ValueShape::BitArray, ExprKind::BitArray(expression)) => {
150                ExprKind::BitArray(expression)
151            }
152            (crate::plan::ValueShape::UtfCodepoint, ExprKind::UtfCodepoint(expression)) => {
153                ExprKind::UtfCodepoint(expression)
154            }
155            (crate::plan::ValueShape::Custom(shape), ExprKind::Custom(expression)) => {
156                ExprKind::Custom(expression.with_shape(shape))
157            }
158            (crate::plan::ValueShape::External(shape), ExprKind::External(expression)) => {
159                ExprKind::External(expression.with_shape(shape))
160            }
161            (crate::plan::ValueShape::Float, ExprKind::Float(expression)) => {
162                ExprKind::Float(expression)
163            }
164            (crate::plan::ValueShape::Bool, ExprKind::Bool(expression)) => {
165                ExprKind::Bool(expression)
166            }
167            (crate::plan::ValueShape::Nil, ExprKind::Nil(expression)) => ExprKind::Nil(expression),
168            (crate::plan::ValueShape::Tuple(shape), ExprKind::Tuple(expression)) => {
169                ExprKind::Tuple(expression.with_shape(shape))
170            }
171            (crate::plan::ValueShape::List(item_shape), ExprKind::List(expression)) => {
172                ExprKind::List(expression.with_item_shape(*item_shape))
173            }
174            (crate::plan::ValueShape::Function(shape), ExprKind::Function(expression)) => {
175                ExprKind::Function(expression.with_resolved_shape(*shape)?)
176            }
177            _ => return None,
178        };
179        Some(Self { shape, kind })
180    }
181
182    pub(crate) fn int(expression: IntExpr) -> Self {
183        Self {
184            shape: crate::plan::ValueShape::Int,
185            kind: ExprKind::Int(expression),
186        }
187    }
188
189    pub(crate) fn generic(expression: GenericExpr) -> Self {
190        Self {
191            shape: crate::plan::ValueShape::Parameter(expression.parameter()),
192            kind: ExprKind::Generic(expression),
193        }
194    }
195
196    pub(crate) fn string(expression: StringExpr) -> Self {
197        Self {
198            shape: crate::plan::ValueShape::String,
199            kind: ExprKind::String(expression),
200        }
201    }
202
203    pub(crate) fn bit_array(expression: BitArrayExpr) -> Self {
204        Self {
205            shape: crate::plan::ValueShape::BitArray,
206            kind: ExprKind::BitArray(expression),
207        }
208    }
209
210    pub(crate) fn utf_codepoint(expression: UtfCodepointExpr) -> Self {
211        Self {
212            shape: crate::plan::ValueShape::UtfCodepoint,
213            kind: ExprKind::UtfCodepoint(expression),
214        }
215    }
216
217    pub(crate) fn custom(expression: CustomExpr) -> Self {
218        let shape = crate::plan::ValueShape::Custom(expression.shape().clone());
219        Self {
220            shape,
221            kind: ExprKind::Custom(expression),
222        }
223    }
224
225    pub(crate) fn external(expression: ExternalExpr) -> Self {
226        let shape = crate::plan::ValueShape::External(expression.shape().clone());
227        Self {
228            shape,
229            kind: ExprKind::External(expression),
230        }
231    }
232
233    pub(crate) fn float(expression: FloatExpr) -> Self {
234        Self {
235            shape: crate::plan::ValueShape::Float,
236            kind: ExprKind::Float(expression),
237        }
238    }
239
240    pub(crate) fn bool(expression: BoolExpr) -> Self {
241        Self {
242            shape: crate::plan::ValueShape::Bool,
243            kind: ExprKind::Bool(expression),
244        }
245    }
246
247    pub(crate) fn nil(expression: NilExpr) -> Self {
248        Self {
249            shape: crate::plan::ValueShape::Nil,
250            kind: ExprKind::Nil(expression),
251        }
252    }
253
254    pub(crate) fn tuple(expression: TupleExpr) -> Self {
255        let shape = crate::plan::ValueShape::Tuple(expression.shape().to_vec().into_boxed_slice());
256        Self {
257            shape,
258            kind: ExprKind::Tuple(expression),
259        }
260    }
261
262    pub(crate) fn list(expression: ListExpr) -> Self {
263        let shape = crate::plan::ValueShape::List(Box::new(expression.item_shape().clone()));
264        Self {
265            shape,
266            kind: ExprKind::List(expression),
267        }
268    }
269
270    pub(crate) fn function(expression: FunctionExpr) -> Self {
271        let shape = crate::plan::ValueShape::Function(Box::new(expression.shape().clone()));
272        Self {
273            shape,
274            kind: ExprKind::Function(expression),
275        }
276    }
277
278    #[cfg(test)]
279    pub(crate) fn call(function: crate::plan::FunctionInstantiation, args: Vec<CallArg>) -> Self {
280        Self::call_at(function, args, crate::plan::HostCallSite::unknown())
281    }
282
283    pub(crate) fn call_at(
284        function: crate::plan::FunctionInstantiation,
285        args: Vec<CallArg>,
286        site: crate::plan::HostCallSite,
287    ) -> Self {
288        match function.shape().return_shape().clone() {
289            ValueShape::Parameter(parameter) => {
290                Self::generic(GenericExpr::call_at(parameter, function, args, site))
291            }
292            ValueShape::Int => Self::int(IntExpr::call_at(function, args, site)),
293            ValueShape::String => Self::string(StringExpr::call_at(function, args, site)),
294            ValueShape::BitArray => Self::bit_array(BitArrayExpr::call_at(function, args, site)),
295            ValueShape::UtfCodepoint => {
296                Self::utf_codepoint(UtfCodepointExpr::call_at(function, args, site))
297            }
298            ValueShape::Custom(shape) => {
299                Self::custom(CustomExpr::call_at(function, args, shape, site))
300            }
301            ValueShape::External(shape) => {
302                Self::external(ExternalExpr::call_at(function, args, shape, site))
303            }
304            ValueShape::Float => Self::float(FloatExpr::call_at(function, args, site)),
305            ValueShape::Bool => Self::bool(BoolExpr::call_at(function, args, site)),
306            ValueShape::Nil => Self::nil(NilExpr::call_at(function, args, site)),
307            ValueShape::Tuple(shape) => {
308                let expression = TupleExpr::call_at(
309                    function,
310                    args,
311                    shape.iter().map(ValueShape::value_type).collect(),
312                    site,
313                );
314                Self {
315                    shape: ValueShape::Tuple(shape),
316                    kind: ExprKind::Tuple(expression),
317                }
318            }
319            ValueShape::List(item_shape) => Self::list(ListExpr::call_at(
320                function,
321                args,
322                (*item_shape).clone(),
323                site,
324            )),
325            ValueShape::Function(shape) => Self::function(FunctionExpr::call_at(
326                function,
327                args,
328                (*shape).clone(),
329                site,
330            )),
331        }
332    }
333
334    pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
335        let Self { shape, kind } = return_;
336        let kind = match kind {
337            ExprKind::Generic(return_) => ExprKind::Generic(GenericExpr::block(steps, return_)),
338            ExprKind::Int(return_) => ExprKind::Int(IntExpr::block(steps, return_)),
339            ExprKind::String(return_) => ExprKind::String(StringExpr::block(steps, return_)),
340            ExprKind::BitArray(return_) => ExprKind::BitArray(BitArrayExpr::block(steps, return_)),
341            ExprKind::UtfCodepoint(return_) => {
342                ExprKind::UtfCodepoint(UtfCodepointExpr::block(steps, return_))
343            }
344            ExprKind::Custom(return_) => ExprKind::Custom(CustomExpr::block(steps, return_)),
345            ExprKind::External(return_) => ExprKind::External(ExternalExpr::block(steps, return_)),
346            ExprKind::Float(return_) => ExprKind::Float(FloatExpr::block(steps, return_)),
347            ExprKind::Bool(return_) => ExprKind::Bool(BoolExpr::block(steps, return_)),
348            ExprKind::Nil(return_) => ExprKind::Nil(NilExpr::block(steps, return_)),
349            ExprKind::Tuple(return_) => ExprKind::Tuple(TupleExpr::block(steps, return_)),
350            ExprKind::List(return_) => ExprKind::List(ListExpr::block(steps, return_)),
351            ExprKind::Function(return_) => ExprKind::Function(FunctionExpr::block(steps, return_)),
352        };
353        Self { shape, kind }
354    }
355
356    pub(crate) fn custom_field_shape(access: CustomFieldAccess, shape: ValueShape) -> Self {
357        match shape {
358            ValueShape::Parameter(parameter) => {
359                Self::generic(GenericExpr::custom_field(parameter, access))
360            }
361            ValueShape::Int => Self::int(IntExpr::custom_field(access)),
362            ValueShape::String => Self::string(StringExpr::custom_field(access)),
363            ValueShape::BitArray => Self::bit_array(BitArrayExpr::custom_field(access)),
364            ValueShape::UtfCodepoint => Self::utf_codepoint(UtfCodepointExpr::custom_field(access)),
365            ValueShape::Custom(shape) => {
366                Self::custom(CustomExpr::custom_field_shape(access, shape))
367            }
368            ValueShape::External(shape) => {
369                Self::external(ExternalExpr::custom_field_shape(access, shape))
370            }
371            ValueShape::Float => Self::float(FloatExpr::custom_field(access)),
372            ValueShape::Bool => Self::bool(BoolExpr::custom_field(access)),
373            ValueShape::Nil => Self::nil(NilExpr::custom_field(access)),
374            ValueShape::Tuple(shape) => {
375                let type_ = shape.iter().map(ValueShape::value_type).collect();
376                Self::tuple(TupleExpr::custom_field(access, type_).with_shape(shape))
377            }
378            ValueShape::List(item_shape) => {
379                let item_type = item_shape.value_type();
380                Self::list(ListExpr::custom_field(access, item_type).with_item_shape(*item_shape))
381            }
382            ValueShape::Function(shape) => {
383                Self::function(FunctionExpr::custom_field_shape(access, *shape))
384            }
385        }
386    }
387
388    pub(crate) fn tuple_index_shape(tuple: TupleExpr, index: usize, shape: ValueShape) -> Self {
389        match shape {
390            ValueShape::Parameter(parameter) => {
391                Self::generic(GenericExpr::tuple_index(parameter, tuple, index))
392            }
393            ValueShape::Int => Self::int(IntExpr::tuple_index(tuple, index)),
394            ValueShape::String => Self::string(StringExpr::tuple_index(tuple, index)),
395            ValueShape::BitArray => Self::bit_array(BitArrayExpr::tuple_index(tuple, index)),
396            ValueShape::UtfCodepoint => {
397                Self::utf_codepoint(UtfCodepointExpr::tuple_index(tuple, index))
398            }
399            ValueShape::Custom(shape) => {
400                Self::custom(CustomExpr::tuple_index_shape(tuple, index, shape))
401            }
402            ValueShape::External(shape) => {
403                Self::external(ExternalExpr::tuple_index_shape(tuple, index, shape))
404            }
405            ValueShape::Float => Self::float(FloatExpr::tuple_index(tuple, index)),
406            ValueShape::Bool => Self::bool(BoolExpr::tuple_index(tuple, index)),
407            ValueShape::Nil => Self::nil(NilExpr::tuple_index(tuple, index)),
408            ValueShape::Tuple(shape) => {
409                let type_ = shape.iter().map(ValueShape::value_type).collect();
410                Self::tuple(TupleExpr::tuple_index(tuple, index, type_).with_shape(shape))
411            }
412            ValueShape::List(item_shape) => {
413                let item_type = item_shape.value_type();
414                Self::list(
415                    ListExpr::tuple_index(tuple, index, item_type).with_item_shape(*item_shape),
416                )
417            }
418            ValueShape::Function(shape) => {
419                Self::function(FunctionExpr::tuple_index_shape(tuple, index, *shape))
420            }
421        }
422    }
423
424    pub(crate) fn bool_case(subject: BoolExpr, branches: BoolCaseBranches) -> Self {
425        match branches {
426            BoolCaseBranches::Int { true_, false_ } => {
427                Self::int(IntExpr::bool_case(subject, true_, false_))
428            }
429            BoolCaseBranches::String { true_, false_ } => {
430                Self::string(StringExpr::bool_case(subject, true_, false_))
431            }
432            BoolCaseBranches::BitArray { true_, false_ } => {
433                Self::bit_array(BitArrayExpr::bool_case(subject, true_, false_))
434            }
435            BoolCaseBranches::UtfCodepoint { true_, false_ } => {
436                Self::utf_codepoint(UtfCodepointExpr::bool_case(subject, true_, false_))
437            }
438            BoolCaseBranches::Custom(branches) => {
439                Self::custom(CustomExpr::bool_case(subject, branches))
440            }
441            BoolCaseBranches::External { true_, false_ } => {
442                Self::external(ExternalExpr::bool_case(subject, true_, false_))
443            }
444            BoolCaseBranches::Float { true_, false_ } => {
445                Self::float(FloatExpr::bool_case(subject, true_, false_))
446            }
447            BoolCaseBranches::Bool { true_, false_ } => {
448                Self::bool(BoolExpr::bool_case(subject, true_, false_))
449            }
450            BoolCaseBranches::Nil { true_, false_ } => {
451                Self::nil(NilExpr::bool_case(subject, true_, false_))
452            }
453            BoolCaseBranches::Tuple { true_, false_ } => {
454                Self::tuple(TupleExpr::bool_case(subject, true_, false_))
455            }
456            BoolCaseBranches::List(branches) => Self::list(ListExpr::bool_case(subject, branches)),
457            BoolCaseBranches::IntFunction { true_, false_ } => Self::function(FunctionExpr::int(
458                IntFunctionExpr::bool_case(subject, true_, false_),
459            )),
460            BoolCaseBranches::StringFunction { true_, false_ } => Self::function(
461                FunctionExpr::string(StringFunctionExpr::bool_case(subject, true_, false_)),
462            ),
463            BoolCaseBranches::BitArrayFunction { true_, false_ } => Self::function(
464                FunctionExpr::bit_array(BitArrayFunctionExpr::bool_case(subject, true_, false_)),
465            ),
466            BoolCaseBranches::UtfCodepointFunction { true_, false_ } => {
467                Self::function(FunctionExpr::utf_codepoint(
468                    UtfCodepointFunctionExpr::bool_case(subject, true_, false_),
469                ))
470            }
471            BoolCaseBranches::CustomFunction { true_, false_ } => Self::function(
472                FunctionExpr::custom(CustomFunctionExpr::bool_case(subject, true_, false_)),
473            ),
474            BoolCaseBranches::ExternalFunction { true_, false_ } => Self::function(
475                FunctionExpr::external(ExternalFunctionExpr::bool_case(subject, true_, false_)),
476            ),
477            BoolCaseBranches::FloatFunction { true_, false_ } => Self::function(
478                FunctionExpr::float(FloatFunctionExpr::bool_case(subject, true_, false_)),
479            ),
480            BoolCaseBranches::BoolFunction { true_, false_ } => Self::function(FunctionExpr::bool(
481                BoolFunctionExpr::bool_case(subject, true_, false_),
482            )),
483            BoolCaseBranches::NilFunction { true_, false_ } => Self::function(FunctionExpr::nil(
484                NilFunctionExpr::bool_case(subject, true_, false_),
485            )),
486            BoolCaseBranches::TupleFunction { true_, false_ } => Self::function(
487                FunctionExpr::tuple(TupleFunctionExpr::bool_case(subject, true_, false_)),
488            ),
489            BoolCaseBranches::ListFunction { true_, false_ } => Self::function(FunctionExpr::list(
490                ListFunctionExpr::bool_case(subject, true_, false_),
491            )),
492            BoolCaseBranches::FunctionFunction { true_, false_ } => Self::function(
493                FunctionExpr::function(FunctionFunctionExpr::bool_case(subject, true_, false_)),
494            ),
495        }
496    }
497
498    pub(crate) fn int_case(subject: IntExpr, branches: IntCaseBranches) -> Self {
499        match branches {
500            IntCaseBranches::Int { clauses, fallback } => {
501                Self::int(IntExpr::int_case(subject, clauses, fallback))
502            }
503            IntCaseBranches::String { clauses, fallback } => {
504                Self::string(StringExpr::int_case(subject, clauses, fallback))
505            }
506            IntCaseBranches::BitArray { clauses, fallback } => {
507                Self::bit_array(BitArrayExpr::int_case(subject, clauses, fallback))
508            }
509            IntCaseBranches::UtfCodepoint { clauses, fallback } => {
510                Self::utf_codepoint(UtfCodepointExpr::int_case(subject, clauses, fallback))
511            }
512            IntCaseBranches::Custom(branches) => {
513                Self::custom(CustomExpr::int_case(subject, branches))
514            }
515            IntCaseBranches::External { clauses, fallback } => {
516                Self::external(ExternalExpr::int_case(subject, clauses, fallback))
517            }
518            IntCaseBranches::Float { clauses, fallback } => {
519                Self::float(FloatExpr::int_case(subject, clauses, fallback))
520            }
521            IntCaseBranches::Bool { clauses, fallback } => {
522                Self::bool(BoolExpr::int_case(subject, clauses, fallback))
523            }
524            IntCaseBranches::Nil { clauses, fallback } => {
525                Self::nil(NilExpr::int_case(subject, clauses, fallback))
526            }
527            IntCaseBranches::Tuple { clauses, fallback } => {
528                Self::tuple(TupleExpr::int_case(subject, clauses, fallback))
529            }
530            IntCaseBranches::List(branches) => Self::list(ListExpr::int_case(subject, branches)),
531            IntCaseBranches::IntFunction { clauses, fallback } => Self::function(
532                FunctionExpr::int(IntFunctionExpr::int_case(subject, clauses, fallback)),
533            ),
534            IntCaseBranches::StringFunction { clauses, fallback } => Self::function(
535                FunctionExpr::string(StringFunctionExpr::int_case(subject, clauses, fallback)),
536            ),
537            IntCaseBranches::BitArrayFunction { clauses, fallback } => Self::function(
538                FunctionExpr::bit_array(BitArrayFunctionExpr::int_case(subject, clauses, fallback)),
539            ),
540            IntCaseBranches::UtfCodepointFunction { clauses, fallback } => {
541                Self::function(FunctionExpr::utf_codepoint(
542                    UtfCodepointFunctionExpr::int_case(subject, clauses, fallback),
543                ))
544            }
545            IntCaseBranches::CustomFunction { clauses, fallback } => Self::function(
546                FunctionExpr::custom(CustomFunctionExpr::int_case(subject, clauses, fallback)),
547            ),
548            IntCaseBranches::ExternalFunction { clauses, fallback } => Self::function(
549                FunctionExpr::external(ExternalFunctionExpr::int_case(subject, clauses, fallback)),
550            ),
551            IntCaseBranches::FloatFunction { clauses, fallback } => Self::function(
552                FunctionExpr::float(FloatFunctionExpr::int_case(subject, clauses, fallback)),
553            ),
554            IntCaseBranches::BoolFunction { clauses, fallback } => Self::function(
555                FunctionExpr::bool(BoolFunctionExpr::int_case(subject, clauses, fallback)),
556            ),
557            IntCaseBranches::NilFunction { clauses, fallback } => Self::function(
558                FunctionExpr::nil(NilFunctionExpr::int_case(subject, clauses, fallback)),
559            ),
560            IntCaseBranches::TupleFunction { clauses, fallback } => Self::function(
561                FunctionExpr::tuple(TupleFunctionExpr::int_case(subject, clauses, fallback)),
562            ),
563            IntCaseBranches::ListFunction { clauses, fallback } => Self::function(
564                FunctionExpr::list(ListFunctionExpr::int_case(subject, clauses, fallback)),
565            ),
566            IntCaseBranches::FunctionFunction { clauses, fallback } => Self::function(
567                FunctionExpr::function(FunctionFunctionExpr::int_case(subject, clauses, fallback)),
568            ),
569        }
570    }
571
572    pub(crate) fn string_case(subject: StringExpr, branches: StringCaseBranches) -> Self {
573        match branches {
574            StringCaseBranches::Int { clauses, fallback } => {
575                Self::int(IntExpr::string_case(subject, clauses, fallback))
576            }
577            StringCaseBranches::String { clauses, fallback } => {
578                Self::string(StringExpr::string_case(subject, clauses, fallback))
579            }
580            StringCaseBranches::BitArray { clauses, fallback } => {
581                Self::bit_array(BitArrayExpr::string_case(subject, clauses, fallback))
582            }
583            StringCaseBranches::UtfCodepoint { clauses, fallback } => {
584                Self::utf_codepoint(UtfCodepointExpr::string_case(subject, clauses, fallback))
585            }
586            StringCaseBranches::Custom(branches) => {
587                Self::custom(CustomExpr::string_case(subject, branches))
588            }
589            StringCaseBranches::External { clauses, fallback } => {
590                Self::external(ExternalExpr::string_case(subject, clauses, fallback))
591            }
592            StringCaseBranches::Float { clauses, fallback } => {
593                Self::float(FloatExpr::string_case(subject, clauses, fallback))
594            }
595            StringCaseBranches::Bool { clauses, fallback } => {
596                Self::bool(BoolExpr::string_case(subject, clauses, fallback))
597            }
598            StringCaseBranches::Nil { clauses, fallback } => {
599                Self::nil(NilExpr::string_case(subject, clauses, fallback))
600            }
601            StringCaseBranches::Tuple { clauses, fallback } => {
602                Self::tuple(TupleExpr::string_case(subject, clauses, fallback))
603            }
604            StringCaseBranches::List(branches) => {
605                Self::list(ListExpr::string_case(subject, branches))
606            }
607            StringCaseBranches::IntFunction { clauses, fallback } => Self::function(
608                FunctionExpr::int(IntFunctionExpr::string_case(subject, clauses, fallback)),
609            ),
610            StringCaseBranches::StringFunction { clauses, fallback } => Self::function(
611                FunctionExpr::string(StringFunctionExpr::string_case(subject, clauses, fallback)),
612            ),
613            StringCaseBranches::BitArrayFunction { clauses, fallback } => {
614                Self::function(FunctionExpr::bit_array(BitArrayFunctionExpr::string_case(
615                    subject, clauses, fallback,
616                )))
617            }
618            StringCaseBranches::UtfCodepointFunction { clauses, fallback } => {
619                Self::function(FunctionExpr::utf_codepoint(
620                    UtfCodepointFunctionExpr::string_case(subject, clauses, fallback),
621                ))
622            }
623            StringCaseBranches::CustomFunction { clauses, fallback } => Self::function(
624                FunctionExpr::custom(CustomFunctionExpr::string_case(subject, clauses, fallback)),
625            ),
626            StringCaseBranches::ExternalFunction { clauses, fallback } => {
627                Self::function(FunctionExpr::external(ExternalFunctionExpr::string_case(
628                    subject, clauses, fallback,
629                )))
630            }
631            StringCaseBranches::FloatFunction { clauses, fallback } => Self::function(
632                FunctionExpr::float(FloatFunctionExpr::string_case(subject, clauses, fallback)),
633            ),
634            StringCaseBranches::BoolFunction { clauses, fallback } => Self::function(
635                FunctionExpr::bool(BoolFunctionExpr::string_case(subject, clauses, fallback)),
636            ),
637            StringCaseBranches::NilFunction { clauses, fallback } => Self::function(
638                FunctionExpr::nil(NilFunctionExpr::string_case(subject, clauses, fallback)),
639            ),
640            StringCaseBranches::TupleFunction { clauses, fallback } => Self::function(
641                FunctionExpr::tuple(TupleFunctionExpr::string_case(subject, clauses, fallback)),
642            ),
643            StringCaseBranches::ListFunction { clauses, fallback } => Self::function(
644                FunctionExpr::list(ListFunctionExpr::string_case(subject, clauses, fallback)),
645            ),
646            StringCaseBranches::FunctionFunction { clauses, fallback } => {
647                Self::function(FunctionExpr::function(FunctionFunctionExpr::string_case(
648                    subject, clauses, fallback,
649                )))
650            }
651        }
652    }
653
654    pub(crate) fn float_case(subject: FloatExpr, branches: FloatCaseBranches) -> Self {
655        match branches {
656            FloatCaseBranches::Int { clauses, fallback } => {
657                Self::int(IntExpr::float_case(subject, clauses, fallback))
658            }
659            FloatCaseBranches::String { clauses, fallback } => {
660                Self::string(StringExpr::float_case(subject, clauses, fallback))
661            }
662            FloatCaseBranches::BitArray { clauses, fallback } => {
663                Self::bit_array(BitArrayExpr::float_case(subject, clauses, fallback))
664            }
665            FloatCaseBranches::UtfCodepoint { clauses, fallback } => {
666                Self::utf_codepoint(UtfCodepointExpr::float_case(subject, clauses, fallback))
667            }
668            FloatCaseBranches::Custom(branches) => {
669                Self::custom(CustomExpr::float_case(subject, branches))
670            }
671            FloatCaseBranches::External { clauses, fallback } => {
672                Self::external(ExternalExpr::float_case(subject, clauses, fallback))
673            }
674            FloatCaseBranches::Float { clauses, fallback } => {
675                Self::float(FloatExpr::float_case(subject, clauses, fallback))
676            }
677            FloatCaseBranches::Bool { clauses, fallback } => {
678                Self::bool(BoolExpr::float_case(subject, clauses, fallback))
679            }
680            FloatCaseBranches::Nil { clauses, fallback } => {
681                Self::nil(NilExpr::float_case(subject, clauses, fallback))
682            }
683            FloatCaseBranches::Tuple { clauses, fallback } => {
684                Self::tuple(TupleExpr::float_case(subject, clauses, fallback))
685            }
686            FloatCaseBranches::List(branches) => {
687                Self::list(ListExpr::float_case(subject, branches))
688            }
689            FloatCaseBranches::IntFunction { clauses, fallback } => Self::function(
690                FunctionExpr::int(IntFunctionExpr::float_case(subject, clauses, fallback)),
691            ),
692            FloatCaseBranches::StringFunction { clauses, fallback } => Self::function(
693                FunctionExpr::string(StringFunctionExpr::float_case(subject, clauses, fallback)),
694            ),
695            FloatCaseBranches::BitArrayFunction { clauses, fallback } => {
696                Self::function(FunctionExpr::bit_array(BitArrayFunctionExpr::float_case(
697                    subject, clauses, fallback,
698                )))
699            }
700            FloatCaseBranches::UtfCodepointFunction { clauses, fallback } => {
701                Self::function(FunctionExpr::utf_codepoint(
702                    UtfCodepointFunctionExpr::float_case(subject, clauses, fallback),
703                ))
704            }
705            FloatCaseBranches::CustomFunction { clauses, fallback } => Self::function(
706                FunctionExpr::custom(CustomFunctionExpr::float_case(subject, clauses, fallback)),
707            ),
708            FloatCaseBranches::ExternalFunction { clauses, fallback } => {
709                Self::function(FunctionExpr::external(ExternalFunctionExpr::float_case(
710                    subject, clauses, fallback,
711                )))
712            }
713            FloatCaseBranches::FloatFunction { clauses, fallback } => Self::function(
714                FunctionExpr::float(FloatFunctionExpr::float_case(subject, clauses, fallback)),
715            ),
716            FloatCaseBranches::BoolFunction { clauses, fallback } => Self::function(
717                FunctionExpr::bool(BoolFunctionExpr::float_case(subject, clauses, fallback)),
718            ),
719            FloatCaseBranches::NilFunction { clauses, fallback } => Self::function(
720                FunctionExpr::nil(NilFunctionExpr::float_case(subject, clauses, fallback)),
721            ),
722            FloatCaseBranches::TupleFunction { clauses, fallback } => Self::function(
723                FunctionExpr::tuple(TupleFunctionExpr::float_case(subject, clauses, fallback)),
724            ),
725            FloatCaseBranches::ListFunction { clauses, fallback } => Self::function(
726                FunctionExpr::list(ListFunctionExpr::float_case(subject, clauses, fallback)),
727            ),
728            FloatCaseBranches::FunctionFunction { clauses, fallback } => {
729                Self::function(FunctionExpr::function(FunctionFunctionExpr::float_case(
730                    subject, clauses, fallback,
731                )))
732            }
733        }
734    }
735
736    pub(crate) fn kind(&self) -> &ExprKind {
737        &self.kind
738    }
739
740    pub(crate) fn into_kind(self) -> ExprKind {
741        self.kind
742    }
743
744    #[cfg(test)]
745    pub(crate) fn into_int(self) -> Option<IntExpr> {
746        match self.kind {
747            ExprKind::Int(expression) => Some(expression),
748            _ => None,
749        }
750    }
751
752    #[cfg(test)]
753    pub(crate) fn into_string(self) -> Option<StringExpr> {
754        match self.kind {
755            ExprKind::String(expression) => Some(expression),
756            _ => None,
757        }
758    }
759
760    #[cfg(test)]
761    pub(crate) fn into_utf_codepoint(self) -> Option<UtfCodepointExpr> {
762        match self.kind {
763            ExprKind::UtfCodepoint(expression) => Some(expression),
764            _ => None,
765        }
766    }
767
768    #[cfg(test)]
769    pub(crate) fn into_custom(self) -> Option<CustomExpr> {
770        match self.kind {
771            ExprKind::Custom(expression) => Some(expression),
772            _ => None,
773        }
774    }
775
776    #[cfg(test)]
777    pub(crate) fn into_float(self) -> Option<FloatExpr> {
778        match self.kind {
779            ExprKind::Float(expression) => Some(expression),
780            _ => None,
781        }
782    }
783
784    #[cfg(test)]
785    pub(crate) fn into_bool(self) -> Option<BoolExpr> {
786        match self.kind {
787            ExprKind::Bool(expression) => Some(expression),
788            _ => None,
789        }
790    }
791
792    #[cfg(test)]
793    pub(crate) fn into_tuple(self) -> Option<TupleExpr> {
794        match self.kind {
795            ExprKind::Tuple(expression) => Some(expression),
796            _ => None,
797        }
798    }
799
800    #[cfg(test)]
801    pub(crate) fn into_list(self) -> Option<ListExpr> {
802        match self.kind {
803            ExprKind::List(expression) => Some(expression),
804            _ => None,
805        }
806    }
807
808    #[cfg(test)]
809    pub(crate) fn into_function(self) -> Option<FunctionExpr> {
810        match self.kind {
811            ExprKind::Function(expression) => Some(expression),
812            _ => None,
813        }
814    }
815
816    #[cfg(test)]
817    pub(crate) fn into_nil(self) -> Option<NilExpr> {
818        match self.kind {
819            ExprKind::Nil(expression) => Some(expression),
820            _ => None,
821        }
822    }
823
824    pub fn value_type(&self) -> ValueType {
825        match self.kind() {
826            ExprKind::Generic(expression) => ValueType::Parameter(expression.parameter()),
827            ExprKind::Int(_) => ValueType::Int,
828            ExprKind::String(_) => ValueType::String,
829            ExprKind::BitArray(_) => ValueType::BitArray,
830            ExprKind::UtfCodepoint(_) => ValueType::UtfCodepoint,
831            ExprKind::Custom(expression) => ValueType::Custom(expression.type_().clone()),
832            ExprKind::External(expression) => ValueType::External(expression.type_().clone()),
833            ExprKind::Float(_) => ValueType::Float,
834            ExprKind::Bool(_) => ValueType::Bool,
835            ExprKind::Nil(_) => ValueType::Nil,
836            ExprKind::Tuple(expression) => ValueType::Tuple(expression.type_().to_vec()),
837            ExprKind::List(expression) => {
838                ValueType::List(Box::new(expression.element_type().clone()))
839            }
840            ExprKind::Function(expression) => {
841                ValueType::Function(Box::new(expression.type_().clone()))
842            }
843        }
844    }
845
846    pub(crate) fn value_shape(&self) -> &crate::plan::ValueShape {
847        &self.shape
848    }
849}
850
851#[cfg(test)]
852mod tests {
853    use super::{
854        BoolCaseBranches, BoolExpr, BoolFunctionExpr, BoolListCaseBranches, CustomExpr, Expr,
855        FloatCaseBranches, FloatExpr, FloatFunctionExpr, FunctionExpr, FunctionFunctionExpr,
856        IntCaseBranches, IntExpr, IntFunctionExpr, ListCaseBranches, ListExpr, ListFunctionExpr,
857        NilExpr, NilFunctionExpr, StringCaseBranches, StringExpr, StringFunctionExpr, TupleExpr,
858        UtfCodepointExpr,
859    };
860    use crate::plan::{
861        BoolFunctionReference, CustomConstructorRefinement, CustomLocal, CustomType,
862        CustomTypeName, CustomValueShape, FloatFunctionReference, FunctionFunctionReference,
863        FunctionInstantiation, FunctionReference, FunctionShape, FunctionType,
864        IntFunctionReference, ListFunctionReference, NilFunctionReference, StringFunctionReference,
865        UtfCodepointLocalId, ValueShape, ValueType, monomorphic_function_instantiation,
866    };
867    use num_bigint::BigInt;
868
869    #[test]
870    fn expression_shape_updates_reject_incompatible_value_families() {
871        let expression = Expr::int(IntExpr::value(BigInt::from(1)));
872
873        assert_eq!(expression.clone().into_bool(), None);
874        assert_eq!(expression.clone().into_tuple(), None);
875        assert_eq!(expression.clone().with_shape(ValueShape::String), None);
876        assert_eq!(expression.with_resolved_shape(ValueShape::String), None);
877
878        let type_ = CustomType::new(
879            CustomTypeName::new("geam".into(), "main".into(), "Choice".into()),
880            Vec::new(),
881        );
882        let first = CustomValueShape::new(
883            type_.type_name().clone(),
884            Vec::new(),
885            CustomConstructorRefinement::Exact(0),
886        );
887        let second = CustomValueShape::new(
888            type_.type_name().clone(),
889            Vec::new(),
890            CustomConstructorRefinement::Exact(1),
891        );
892        let expression = Expr::custom(CustomExpr::local_get(
893            CustomLocal::from_shape(crate::plan::CustomLocalId(0), first),
894            "choice".into(),
895        ));
896
897        assert_eq!(expression.with_shape(ValueShape::Custom(second)), None);
898
899        let expression = Expr::function(FunctionExpr::int(int_function_expr()));
900        let shape = ValueShape::Function(Box::new(crate::plan::FunctionShape::from_function_type(
901            FunctionType::new(vec![ValueType::Int], ValueType::Int),
902        )));
903
904        assert_eq!(
905            expression.clone().with_resolved_shape(shape.clone()),
906            Some(expression),
907        );
908
909        let expression = Expr::function(FunctionExpr::int(int_function_expr()));
910        assert_eq!(
911            expression.with_shape(ValueShape::Function(Box::new(
912                crate::plan::FunctionShape::from_function_type(FunctionType::new(
913                    vec![ValueType::String],
914                    ValueType::String,
915                )),
916            ))),
917            None,
918        );
919    }
920
921    #[test]
922    fn expr_bool_case_shapes() {
923        assert_eq!(
924            Expr::bool_case(
925                BoolExpr::value(true),
926                BoolCaseBranches::Int {
927                    true_: IntExpr::value(BigInt::from(1)),
928                    false_: IntExpr::value(BigInt::from(0)),
929                },
930            ),
931            Expr::int(IntExpr::bool_case(
932                BoolExpr::value(true),
933                IntExpr::value(BigInt::from(1)),
934                IntExpr::value(BigInt::from(0)),
935            )),
936        );
937        assert_eq!(
938            Expr::bool_case(
939                BoolExpr::value(true),
940                BoolCaseBranches::String {
941                    true_: StringExpr::value("yes".into()),
942                    false_: StringExpr::value("no".into()),
943                },
944            ),
945            Expr::string(StringExpr::bool_case(
946                BoolExpr::value(true),
947                StringExpr::value("yes".into()),
948                StringExpr::value("no".into()),
949            )),
950        );
951        assert_eq!(
952            Expr::bool_case(
953                BoolExpr::value(true),
954                BoolCaseBranches::Float {
955                    true_: FloatExpr::value(1.5),
956                    false_: FloatExpr::value(0.5),
957                },
958            ),
959            Expr::float(FloatExpr::bool_case(
960                BoolExpr::value(true),
961                FloatExpr::value(1.5),
962                FloatExpr::value(0.5),
963            )),
964        );
965        assert_eq!(
966            Expr::bool_case(
967                BoolExpr::value(true),
968                BoolCaseBranches::Bool {
969                    true_: BoolExpr::value(true),
970                    false_: BoolExpr::value(false),
971                },
972            ),
973            Expr::bool(BoolExpr::bool_case(
974                BoolExpr::value(true),
975                BoolExpr::value(true),
976                BoolExpr::value(false),
977            )),
978        );
979        assert_eq!(
980            Expr::bool_case(
981                BoolExpr::value(true),
982                BoolCaseBranches::Nil {
983                    true_: NilExpr::value(),
984                    false_: NilExpr::value(),
985                },
986            ),
987            Expr::nil(NilExpr::bool_case(
988                BoolExpr::value(true),
989                NilExpr::value(),
990                NilExpr::value(),
991            )),
992        );
993        assert_eq!(
994            Expr::bool_case(
995                BoolExpr::value(true),
996                BoolCaseBranches::List(BoolListCaseBranches::Int {
997                    true_: list_expr()
998                        .into_int()
999                        .expect("test list expression should be List(Int)"),
1000                    false_: list_expr()
1001                        .into_int()
1002                        .expect("test list expression should be List(Int)"),
1003                }),
1004            ),
1005            Expr::list(ListExpr::bool_case(
1006                BoolExpr::value(true),
1007                BoolListCaseBranches::Int {
1008                    true_: list_expr()
1009                        .into_int()
1010                        .expect("test list expression should be List(Int)"),
1011                    false_: list_expr()
1012                        .into_int()
1013                        .expect("test list expression should be List(Int)"),
1014                },
1015            )),
1016        );
1017        assert_eq!(
1018            Expr::bool_case(
1019                BoolExpr::value(true),
1020                BoolCaseBranches::IntFunction {
1021                    true_: int_function_expr(),
1022                    false_: int_function_expr(),
1023                },
1024            ),
1025            Expr::function(FunctionExpr::int(IntFunctionExpr::bool_case(
1026                BoolExpr::value(true),
1027                int_function_expr(),
1028                int_function_expr(),
1029            ))),
1030        );
1031        assert_eq!(
1032            Expr::bool_case(
1033                BoolExpr::value(true),
1034                BoolCaseBranches::StringFunction {
1035                    true_: string_function_expr(),
1036                    false_: string_function_expr(),
1037                },
1038            ),
1039            Expr::function(FunctionExpr::string(StringFunctionExpr::bool_case(
1040                BoolExpr::value(true),
1041                string_function_expr(),
1042                string_function_expr(),
1043            ))),
1044        );
1045        assert_eq!(
1046            Expr::bool_case(
1047                BoolExpr::value(true),
1048                BoolCaseBranches::FloatFunction {
1049                    true_: float_function_expr(),
1050                    false_: float_function_expr(),
1051                },
1052            ),
1053            Expr::function(FunctionExpr::float(FloatFunctionExpr::bool_case(
1054                BoolExpr::value(true),
1055                float_function_expr(),
1056                float_function_expr(),
1057            ))),
1058        );
1059        assert_eq!(
1060            Expr::bool_case(
1061                BoolExpr::value(true),
1062                BoolCaseBranches::BoolFunction {
1063                    true_: bool_function_expr(),
1064                    false_: bool_function_expr(),
1065                },
1066            ),
1067            Expr::function(FunctionExpr::bool(BoolFunctionExpr::bool_case(
1068                BoolExpr::value(true),
1069                bool_function_expr(),
1070                bool_function_expr(),
1071            ))),
1072        );
1073        assert_eq!(
1074            Expr::bool_case(
1075                BoolExpr::value(true),
1076                BoolCaseBranches::ListFunction {
1077                    true_: list_function_expr(),
1078                    false_: list_function_expr(),
1079                },
1080            ),
1081            Expr::function(FunctionExpr::list(ListFunctionExpr::bool_case(
1082                BoolExpr::value(true),
1083                list_function_expr(),
1084                list_function_expr(),
1085            ))),
1086        );
1087        assert_eq!(
1088            Expr::bool_case(
1089                BoolExpr::value(true),
1090                BoolCaseBranches::NilFunction {
1091                    true_: nil_function_expr(),
1092                    false_: nil_function_expr(),
1093                },
1094            ),
1095            Expr::function(FunctionExpr::nil(NilFunctionExpr::bool_case(
1096                BoolExpr::value(true),
1097                nil_function_expr(),
1098                nil_function_expr(),
1099            ))),
1100        );
1101    }
1102
1103    #[test]
1104    fn expr_int_case_shapes() {
1105        assert_eq!(
1106            Expr::int_case(
1107                IntExpr::value(BigInt::from(1)),
1108                IntCaseBranches::Int {
1109                    clauses: vec![(BigInt::from(1), IntExpr::value(BigInt::from(10)))],
1110                    fallback: IntExpr::value(BigInt::from(0)),
1111                },
1112            ),
1113            Expr::int(IntExpr::int_case(
1114                IntExpr::value(BigInt::from(1)),
1115                vec![(BigInt::from(1), IntExpr::value(BigInt::from(10)))],
1116                IntExpr::value(BigInt::from(0)),
1117            )),
1118        );
1119        assert_eq!(
1120            Expr::int_case(
1121                IntExpr::value(BigInt::from(1)),
1122                IntCaseBranches::String {
1123                    clauses: vec![(BigInt::from(1), StringExpr::value("one".into()))],
1124                    fallback: StringExpr::value("other".into()),
1125                },
1126            ),
1127            Expr::string(StringExpr::int_case(
1128                IntExpr::value(BigInt::from(1)),
1129                vec![(BigInt::from(1), StringExpr::value("one".into()))],
1130                StringExpr::value("other".into()),
1131            )),
1132        );
1133        assert_eq!(
1134            Expr::int_case(
1135                IntExpr::value(BigInt::from(1)),
1136                IntCaseBranches::Float {
1137                    clauses: vec![(BigInt::from(1), FloatExpr::value(1.5))],
1138                    fallback: FloatExpr::value(0.5),
1139                },
1140            ),
1141            Expr::float(FloatExpr::int_case(
1142                IntExpr::value(BigInt::from(1)),
1143                vec![(BigInt::from(1), FloatExpr::value(1.5))],
1144                FloatExpr::value(0.5),
1145            )),
1146        );
1147        assert_eq!(
1148            Expr::int_case(
1149                IntExpr::value(BigInt::from(1)),
1150                IntCaseBranches::Bool {
1151                    clauses: vec![(BigInt::from(1), BoolExpr::value(true))],
1152                    fallback: BoolExpr::value(false),
1153                },
1154            ),
1155            Expr::bool(BoolExpr::int_case(
1156                IntExpr::value(BigInt::from(1)),
1157                vec![(BigInt::from(1), BoolExpr::value(true))],
1158                BoolExpr::value(false),
1159            )),
1160        );
1161        assert_eq!(
1162            Expr::int_case(
1163                IntExpr::value(BigInt::from(1)),
1164                IntCaseBranches::Nil {
1165                    clauses: vec![(BigInt::from(1), NilExpr::value())],
1166                    fallback: NilExpr::value(),
1167                },
1168            ),
1169            Expr::nil(NilExpr::int_case(
1170                IntExpr::value(BigInt::from(1)),
1171                vec![(BigInt::from(1), NilExpr::value())],
1172                NilExpr::value(),
1173            )),
1174        );
1175        assert_eq!(
1176            Expr::int_case(
1177                IntExpr::value(BigInt::from(1)),
1178                IntCaseBranches::List(
1179                    ListCaseBranches::from_exprs(vec![(BigInt::from(1), list_expr())], list_expr())
1180                        .expect("list case branches"),
1181                ),
1182            ),
1183            Expr::list(ListExpr::int_case(
1184                IntExpr::value(BigInt::from(1)),
1185                ListCaseBranches::from_exprs(vec![(BigInt::from(1), list_expr())], list_expr())
1186                    .expect("list case branches"),
1187            )),
1188        );
1189        assert_eq!(
1190            Expr::int_case(
1191                IntExpr::value(BigInt::from(1)),
1192                IntCaseBranches::IntFunction {
1193                    clauses: vec![(BigInt::from(1), int_function_expr())],
1194                    fallback: int_function_expr(),
1195                },
1196            ),
1197            Expr::function(FunctionExpr::int(IntFunctionExpr::int_case(
1198                IntExpr::value(BigInt::from(1)),
1199                vec![(BigInt::from(1), int_function_expr())],
1200                int_function_expr(),
1201            ))),
1202        );
1203        assert_eq!(
1204            Expr::int_case(
1205                IntExpr::value(BigInt::from(1)),
1206                IntCaseBranches::StringFunction {
1207                    clauses: vec![(BigInt::from(1), string_function_expr())],
1208                    fallback: string_function_expr(),
1209                },
1210            ),
1211            Expr::function(FunctionExpr::string(StringFunctionExpr::int_case(
1212                IntExpr::value(BigInt::from(1)),
1213                vec![(BigInt::from(1), string_function_expr())],
1214                string_function_expr(),
1215            ))),
1216        );
1217        assert_eq!(
1218            Expr::int_case(
1219                IntExpr::value(BigInt::from(1)),
1220                IntCaseBranches::FloatFunction {
1221                    clauses: vec![(BigInt::from(1), float_function_expr())],
1222                    fallback: float_function_expr(),
1223                },
1224            ),
1225            Expr::function(FunctionExpr::float(FloatFunctionExpr::int_case(
1226                IntExpr::value(BigInt::from(1)),
1227                vec![(BigInt::from(1), float_function_expr())],
1228                float_function_expr(),
1229            ))),
1230        );
1231        assert_eq!(
1232            Expr::int_case(
1233                IntExpr::value(BigInt::from(1)),
1234                IntCaseBranches::BoolFunction {
1235                    clauses: vec![(BigInt::from(1), bool_function_expr())],
1236                    fallback: bool_function_expr(),
1237                },
1238            ),
1239            Expr::function(FunctionExpr::bool(BoolFunctionExpr::int_case(
1240                IntExpr::value(BigInt::from(1)),
1241                vec![(BigInt::from(1), bool_function_expr())],
1242                bool_function_expr(),
1243            ))),
1244        );
1245        assert_eq!(
1246            Expr::int_case(
1247                IntExpr::value(BigInt::from(1)),
1248                IntCaseBranches::ListFunction {
1249                    clauses: vec![(BigInt::from(1), list_function_expr())],
1250                    fallback: list_function_expr(),
1251                },
1252            ),
1253            Expr::function(FunctionExpr::list(ListFunctionExpr::int_case(
1254                IntExpr::value(BigInt::from(1)),
1255                vec![(BigInt::from(1), list_function_expr())],
1256                list_function_expr(),
1257            ))),
1258        );
1259        assert_eq!(
1260            Expr::int_case(
1261                IntExpr::value(BigInt::from(1)),
1262                IntCaseBranches::NilFunction {
1263                    clauses: vec![(BigInt::from(1), nil_function_expr())],
1264                    fallback: nil_function_expr(),
1265                },
1266            ),
1267            Expr::function(FunctionExpr::nil(NilFunctionExpr::int_case(
1268                IntExpr::value(BigInt::from(1)),
1269                vec![(BigInt::from(1), nil_function_expr())],
1270                nil_function_expr(),
1271            ))),
1272        );
1273    }
1274
1275    #[test]
1276    fn expr_float_case_shapes() {
1277        assert_eq!(
1278            Expr::float_case(
1279                FloatExpr::value(1.0),
1280                FloatCaseBranches::Int {
1281                    clauses: vec![(1.0, IntExpr::value(BigInt::from(10)))],
1282                    fallback: IntExpr::value(BigInt::from(0)),
1283                },
1284            ),
1285            Expr::int(IntExpr::float_case(
1286                FloatExpr::value(1.0),
1287                vec![(1.0, IntExpr::value(BigInt::from(10)))],
1288                IntExpr::value(BigInt::from(0)),
1289            )),
1290        );
1291        assert_eq!(
1292            Expr::float_case(
1293                FloatExpr::value(1.0),
1294                FloatCaseBranches::String {
1295                    clauses: vec![(1.0, StringExpr::value("one".into()))],
1296                    fallback: StringExpr::value("other".into()),
1297                },
1298            ),
1299            Expr::string(StringExpr::float_case(
1300                FloatExpr::value(1.0),
1301                vec![(1.0, StringExpr::value("one".into()))],
1302                StringExpr::value("other".into()),
1303            )),
1304        );
1305        assert_eq!(
1306            Expr::float_case(
1307                FloatExpr::value(1.0),
1308                FloatCaseBranches::Float {
1309                    clauses: vec![(1.0, FloatExpr::value(1.5))],
1310                    fallback: FloatExpr::value(0.5),
1311                },
1312            ),
1313            Expr::float(FloatExpr::float_case(
1314                FloatExpr::value(1.0),
1315                vec![(1.0, FloatExpr::value(1.5))],
1316                FloatExpr::value(0.5),
1317            )),
1318        );
1319        assert_eq!(
1320            Expr::float_case(
1321                FloatExpr::value(1.0),
1322                FloatCaseBranches::Bool {
1323                    clauses: vec![(1.0, BoolExpr::value(true))],
1324                    fallback: BoolExpr::value(false),
1325                },
1326            ),
1327            Expr::bool(BoolExpr::float_case(
1328                FloatExpr::value(1.0),
1329                vec![(1.0, BoolExpr::value(true))],
1330                BoolExpr::value(false),
1331            )),
1332        );
1333        assert_eq!(
1334            Expr::float_case(
1335                FloatExpr::value(1.0),
1336                FloatCaseBranches::Nil {
1337                    clauses: vec![(1.0, NilExpr::value())],
1338                    fallback: NilExpr::value(),
1339                },
1340            ),
1341            Expr::nil(NilExpr::float_case(
1342                FloatExpr::value(1.0),
1343                vec![(1.0, NilExpr::value())],
1344                NilExpr::value(),
1345            )),
1346        );
1347        assert_eq!(
1348            Expr::float_case(
1349                FloatExpr::value(1.0),
1350                FloatCaseBranches::List(
1351                    ListCaseBranches::from_exprs(vec![(1.0, list_expr())], list_expr())
1352                        .expect("list case branches"),
1353                ),
1354            ),
1355            Expr::list(ListExpr::float_case(
1356                FloatExpr::value(1.0),
1357                ListCaseBranches::from_exprs(vec![(1.0, list_expr())], list_expr())
1358                    .expect("list case branches"),
1359            )),
1360        );
1361        assert_eq!(
1362            Expr::float_case(
1363                FloatExpr::value(1.0),
1364                FloatCaseBranches::IntFunction {
1365                    clauses: vec![(1.0, int_function_expr())],
1366                    fallback: int_function_expr(),
1367                },
1368            ),
1369            Expr::function(FunctionExpr::int(IntFunctionExpr::float_case(
1370                FloatExpr::value(1.0),
1371                vec![(1.0, int_function_expr())],
1372                int_function_expr(),
1373            ))),
1374        );
1375        assert_eq!(
1376            Expr::float_case(
1377                FloatExpr::value(1.0),
1378                FloatCaseBranches::StringFunction {
1379                    clauses: vec![(1.0, string_function_expr())],
1380                    fallback: string_function_expr(),
1381                },
1382            ),
1383            Expr::function(FunctionExpr::string(StringFunctionExpr::float_case(
1384                FloatExpr::value(1.0),
1385                vec![(1.0, string_function_expr())],
1386                string_function_expr(),
1387            ))),
1388        );
1389        assert_eq!(
1390            Expr::float_case(
1391                FloatExpr::value(1.0),
1392                FloatCaseBranches::FloatFunction {
1393                    clauses: vec![(1.0, float_function_expr())],
1394                    fallback: float_function_expr(),
1395                },
1396            ),
1397            Expr::function(FunctionExpr::float(FloatFunctionExpr::float_case(
1398                FloatExpr::value(1.0),
1399                vec![(1.0, float_function_expr())],
1400                float_function_expr(),
1401            ))),
1402        );
1403        assert_eq!(
1404            Expr::float_case(
1405                FloatExpr::value(1.0),
1406                FloatCaseBranches::BoolFunction {
1407                    clauses: vec![(1.0, bool_function_expr())],
1408                    fallback: bool_function_expr(),
1409                },
1410            ),
1411            Expr::function(FunctionExpr::bool(BoolFunctionExpr::float_case(
1412                FloatExpr::value(1.0),
1413                vec![(1.0, bool_function_expr())],
1414                bool_function_expr(),
1415            ))),
1416        );
1417        assert_eq!(
1418            Expr::float_case(
1419                FloatExpr::value(1.0),
1420                FloatCaseBranches::NilFunction {
1421                    clauses: vec![(1.0, nil_function_expr())],
1422                    fallback: nil_function_expr(),
1423                },
1424            ),
1425            Expr::function(FunctionExpr::nil(NilFunctionExpr::float_case(
1426                FloatExpr::value(1.0),
1427                vec![(1.0, nil_function_expr())],
1428                nil_function_expr(),
1429            ))),
1430        );
1431        assert_eq!(
1432            Expr::float_case(
1433                FloatExpr::value(1.0),
1434                FloatCaseBranches::ListFunction {
1435                    clauses: vec![(1.0, list_function_expr())],
1436                    fallback: list_function_expr(),
1437                },
1438            ),
1439            Expr::function(FunctionExpr::list(ListFunctionExpr::float_case(
1440                FloatExpr::value(1.0),
1441                vec![(1.0, list_function_expr())],
1442                list_function_expr(),
1443            ))),
1444        );
1445        assert_eq!(
1446            Expr::float_case(
1447                FloatExpr::value(1.0),
1448                FloatCaseBranches::FunctionFunction {
1449                    clauses: vec![(1.0, function_function_expr())],
1450                    fallback: function_function_expr(),
1451                },
1452            ),
1453            Expr::function(FunctionExpr::function(FunctionFunctionExpr::float_case(
1454                FloatExpr::value(1.0),
1455                vec![(1.0, function_function_expr())],
1456                function_function_expr(),
1457            ))),
1458        );
1459    }
1460
1461    #[test]
1462    fn expr_string_case_shapes() {
1463        assert_eq!(
1464            Expr::string_case(
1465                StringExpr::value("one".into()),
1466                StringCaseBranches::Float {
1467                    clauses: vec![("one".into(), FloatExpr::value(1.5))],
1468                    fallback: FloatExpr::value(0.5),
1469                },
1470            ),
1471            Expr::float(FloatExpr::string_case(
1472                StringExpr::value("one".into()),
1473                vec![("one".into(), FloatExpr::value(1.5))],
1474                FloatExpr::value(0.5),
1475            )),
1476        );
1477        assert_eq!(
1478            Expr::string_case(
1479                StringExpr::value("one".into()),
1480                StringCaseBranches::List(
1481                    ListCaseBranches::from_exprs(vec![("one".into(), list_expr())], list_expr())
1482                        .expect("list case branches"),
1483                ),
1484            ),
1485            Expr::list(ListExpr::string_case(
1486                StringExpr::value("one".into()),
1487                ListCaseBranches::from_exprs(vec![("one".into(), list_expr())], list_expr())
1488                    .expect("list case branches"),
1489            )),
1490        );
1491        assert_eq!(
1492            Expr::string_case(
1493                StringExpr::value("one".into()),
1494                StringCaseBranches::ListFunction {
1495                    clauses: vec![("one".into(), list_function_expr())],
1496                    fallback: list_function_expr(),
1497                },
1498            ),
1499            Expr::function(FunctionExpr::list(ListFunctionExpr::string_case(
1500                StringExpr::value("one".into()),
1501                vec![("one".into(), list_function_expr())],
1502                list_function_expr(),
1503            ))),
1504        );
1505        assert_eq!(
1506            Expr::string_case(
1507                StringExpr::value("one".into()),
1508                StringCaseBranches::FloatFunction {
1509                    clauses: vec![("one".into(), float_function_expr())],
1510                    fallback: float_function_expr(),
1511                },
1512            ),
1513            Expr::function(FunctionExpr::float(FloatFunctionExpr::string_case(
1514                StringExpr::value("one".into()),
1515                vec![("one".into(), float_function_expr())],
1516                float_function_expr(),
1517            ))),
1518        );
1519    }
1520
1521    #[test]
1522    fn expr_value_type() {
1523        assert_eq!(
1524            Expr::int(IntExpr::value(BigInt::from(1))).value_type(),
1525            ValueType::Int
1526        );
1527        assert_eq!(
1528            Expr::string(StringExpr::value("geam".into())).value_type(),
1529            ValueType::String,
1530        );
1531        assert_eq!(
1532            Expr::float(FloatExpr::value(1.5)).value_type(),
1533            ValueType::Float
1534        );
1535        assert_eq!(
1536            Expr::bool(BoolExpr::value(true)).value_type(),
1537            ValueType::Bool
1538        );
1539        assert_eq!(Expr::nil(NilExpr::value()).value_type(), ValueType::Nil);
1540        assert_eq!(
1541            Expr::tuple(TupleExpr::value(
1542                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1543                vec![ValueType::Int],
1544            ))
1545            .value_type(),
1546            ValueType::Tuple(vec![ValueType::Int]),
1547        );
1548        assert_eq!(
1549            Expr::list(ListExpr::value(
1550                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1551                ValueType::Int,
1552            ))
1553            .value_type(),
1554            ValueType::List(Box::new(ValueType::Int)),
1555        );
1556        assert_eq!(
1557            Expr::function(FunctionExpr::reference(function_value())).value_type(),
1558            ValueType::Function(Box::new(function_type())),
1559        );
1560    }
1561
1562    #[test]
1563    fn expr_into_typed_expression() {
1564        assert_eq!(
1565            Expr::int(IntExpr::value(BigInt::from(1))).into_int(),
1566            Some(IntExpr::value(BigInt::from(1))),
1567        );
1568        assert_eq!(
1569            Expr::string(StringExpr::value("geam".into())).into_string(),
1570            Some(StringExpr::value("geam".into())),
1571        );
1572        assert_eq!(
1573            Expr::int(IntExpr::value(BigInt::from(1))).into_string(),
1574            None,
1575        );
1576        let codepoint = UtfCodepointExpr::local_get(UtfCodepointLocalId(0), "codepoint".into());
1577        assert_eq!(
1578            Expr::utf_codepoint(codepoint.clone()).into_utf_codepoint(),
1579            Some(codepoint),
1580        );
1581        assert_eq!(
1582            Expr::int(IntExpr::value(BigInt::from(1))).into_utf_codepoint(),
1583            None,
1584        );
1585        assert_eq!(
1586            Expr::int(IntExpr::value(BigInt::from(1))).into_custom(),
1587            None,
1588        );
1589        assert_eq!(
1590            Expr::float(FloatExpr::value(1.5)).into_float(),
1591            Some(FloatExpr::value(1.5)),
1592        );
1593        assert_eq!(
1594            Expr::int(IntExpr::value(BigInt::from(1))).into_float(),
1595            None
1596        );
1597        assert_eq!(
1598            Expr::bool(BoolExpr::value(true)).into_bool(),
1599            Some(BoolExpr::value(true)),
1600        );
1601        assert_eq!(
1602            Expr::nil(NilExpr::value()).into_nil(),
1603            Some(NilExpr::value())
1604        );
1605        assert_eq!(
1606            Expr::tuple(TupleExpr::value(
1607                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1608                vec![ValueType::Int],
1609            ))
1610            .into_tuple(),
1611            Some(TupleExpr::value(
1612                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1613                vec![ValueType::Int],
1614            )),
1615        );
1616        assert_eq!(
1617            Expr::list(ListExpr::value(
1618                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1619                ValueType::Int,
1620            ))
1621            .into_list(),
1622            Some(ListExpr::value(
1623                vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1624                ValueType::Int,
1625            )),
1626        );
1627        assert_eq!(Expr::int(IntExpr::value(BigInt::from(1))).into_list(), None);
1628        assert_eq!(Expr::nil(NilExpr::value()).into_int(), None);
1629        assert_eq!(Expr::int(IntExpr::value(BigInt::from(1))).into_nil(), None);
1630        assert_eq!(
1631            Expr::int(IntExpr::value(BigInt::from(1))).into_function(),
1632            None,
1633        );
1634        assert_eq!(
1635            Expr::function(FunctionExpr::reference(function_value())).into_function(),
1636            Some(FunctionExpr::reference(function_value())),
1637        );
1638    }
1639
1640    fn function_value() -> FunctionReference {
1641        FunctionReference::new(instantiation(function_type()))
1642    }
1643
1644    fn int_function_expr() -> IntFunctionExpr {
1645        IntFunctionExpr::reference(IntFunctionReference::new(instantiation(function_type())))
1646    }
1647
1648    fn string_function_expr() -> StringFunctionExpr {
1649        StringFunctionExpr::reference(StringFunctionReference::new(instantiation(
1650            FunctionType::new(vec![ValueType::String], ValueType::String),
1651        )))
1652    }
1653
1654    fn float_function_expr() -> FloatFunctionExpr {
1655        FloatFunctionExpr::reference(FloatFunctionReference::new(instantiation(
1656            FunctionType::new(vec![ValueType::Float], ValueType::Float),
1657        )))
1658    }
1659
1660    fn bool_function_expr() -> BoolFunctionExpr {
1661        BoolFunctionExpr::reference(BoolFunctionReference::new(instantiation(
1662            FunctionType::new(vec![ValueType::Bool], ValueType::Bool),
1663        )))
1664    }
1665
1666    fn nil_function_expr() -> NilFunctionExpr {
1667        NilFunctionExpr::reference(NilFunctionReference::new(instantiation(FunctionType::new(
1668            vec![ValueType::Nil],
1669            ValueType::Nil,
1670        ))))
1671    }
1672
1673    fn list_expr() -> ListExpr {
1674        ListExpr::value(
1675            vec![Expr::int(IntExpr::value(BigInt::from(1)))],
1676            ValueType::Int,
1677        )
1678    }
1679
1680    fn list_function_expr() -> ListFunctionExpr {
1681        ListFunctionExpr::reference(
1682            ListFunctionReference::new(instantiation(FunctionType::new(
1683                vec![ValueType::List(Box::new(ValueType::Int))],
1684                ValueType::List(Box::new(ValueType::Int)),
1685            ))),
1686            ValueType::Int,
1687        )
1688    }
1689
1690    fn function_function_expr() -> FunctionFunctionExpr {
1691        FunctionFunctionExpr::reference(
1692            FunctionFunctionReference::new(instantiation(FunctionType::new(
1693                Vec::new(),
1694                ValueType::Function(Box::new(function_type())),
1695            ))),
1696            function_type(),
1697        )
1698    }
1699
1700    fn instantiation(type_: FunctionType) -> FunctionInstantiation {
1701        monomorphic_function_instantiation(0, FunctionShape::from_function_type(type_))
1702    }
1703
1704    fn function_type() -> FunctionType {
1705        FunctionType::new(vec![ValueType::Int], ValueType::Int)
1706    }
1707}