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}