1use super::expression::{
2 BitArrayExpr, BitArrayListExpr, BoolExpr, BoolListExpr, CallArg, CustomExpr, CustomListExpr,
3 ExternalExpr, ExternalListExpr, FloatExpr, FloatListExpr, FunctionListExpr, IntExpr,
4 IntListExpr, ListListExpr, NilExpr, NilListExpr, StringExpr, StringListExpr, TupleExpr,
5 TupleListExpr, UtfCodepointExpr, UtfCodepointListExpr,
6};
7use super::id::{
8 BitArrayFunctionLocalId, BitArrayLocalId, BoolFunctionLocalId, BoolLocalId,
9 CustomFunctionLocal, CustomLocal, CustomLocalId, ExternalFunctionLocal, ExternalLocal,
10 ExternalLocalId, FloatFunctionLocalId, FloatLocalId, FunctionFunctionLocal, FunctionTemplateId,
11 GenericFunctionLocal, GenericLocal, IntFunctionLocalId, IntLocalId, ListFunctionLocal,
12 ListLocal, NilFunctionLocalId, NilLocalId, StringFunctionLocalId, StringLocalId,
13 TupleFunctionLocalId, TupleLocalId, UtfCodepointFunctionLocalId, UtfCodepointLocalId,
14};
15use super::step::Step;
16use super::{FunctionInstantiation, FunctionTemplateSignature, TypeScheme};
17use crate::plan::{
18 CustomFunctionType, CustomType, ExternalFunctionType, ExternalType, FunctionFunctionType,
19 FunctionType, ValueStorageShape, ValueType,
20};
21use ecow::EcoString;
22use num_bigint::BigInt;
23
24#[cfg(test)]
25use super::expression::ListExpr;
26#[cfg(test)]
27use super::id::{BoolFunctionId, IntFunctionId};
28#[cfg(test)]
29use crate::plan::{ValueRepresentation, ValueShape};
30
31#[derive(Debug, PartialEq)]
32pub struct FunctionTemplate {
33 signature: FunctionTemplateSignature,
34 name: EcoString,
35 entry: FunctionEntry,
36 steps: Vec<Step>,
37 return_: ReturnExpr,
38}
39
40#[derive(Debug, PartialEq)]
41pub(crate) struct FunctionEntry {
42 params: Box<[Param]>,
43 captures: Box<[ParamSlot]>,
44}
45
46#[derive(Debug, PartialEq)]
47pub struct Param {
48 slot: ParamSlot,
49 binding: ParamBinding,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub(crate) struct ParamSlot {
54 local: ParamLocal,
55 shape: crate::plan::ValueShape,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub(crate) struct CapturePosition(usize);
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub enum ParamBinding {
63 Named(EcoString),
64 Discard,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub(crate) enum ParamLocal {
69 Generic(GenericLocal),
70 Int(IntLocalId),
71 Float(FloatLocalId),
72 String(StringLocalId),
73 BitArray(BitArrayLocalId),
74 UtfCodepoint(UtfCodepointLocalId),
75 Custom(CustomLocal),
76 External(ExternalLocal),
77 Bool(BoolLocalId),
78 Nil(NilLocalId),
79 Tuple {
80 local: TupleLocalId,
81 type_: Vec<ValueType>,
82 },
83 List(ListLocal),
84 IntFunction {
85 local: IntFunctionLocalId,
86 type_: FunctionType,
87 },
88 FloatFunction {
89 local: FloatFunctionLocalId,
90 type_: FunctionType,
91 },
92 StringFunction {
93 local: StringFunctionLocalId,
94 type_: FunctionType,
95 },
96 BitArrayFunction {
97 local: BitArrayFunctionLocalId,
98 type_: FunctionType,
99 },
100 UtfCodepointFunction {
101 local: UtfCodepointFunctionLocalId,
102 type_: FunctionType,
103 },
104 CustomFunction(CustomFunctionLocal),
105 ExternalFunction(ExternalFunctionLocal),
106 BoolFunction {
107 local: BoolFunctionLocalId,
108 type_: FunctionType,
109 },
110 NilFunction {
111 local: NilFunctionLocalId,
112 type_: FunctionType,
113 },
114 TupleFunction {
115 local: TupleFunctionLocalId,
116 type_: FunctionType,
117 },
118 ListFunction(ListFunctionLocal),
119 FunctionFunction(FunctionFunctionLocal),
120 GenericFunction(GenericFunctionLocal),
121}
122
123pub(crate) type GenericReturn =
124 ReturnBody<super::GenericExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
125pub(crate) type IntReturn =
126 ReturnBody<IntExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
127pub(crate) type FloatReturn =
128 ReturnBody<FloatExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
129pub(crate) type StringReturn =
130 ReturnBody<StringExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
131pub(crate) type BitArrayReturn =
132 ReturnBody<BitArrayExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
133pub(crate) type UtfCodepointReturn =
134 ReturnBody<UtfCodepointExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
135#[derive(Debug, Clone, PartialEq)]
136pub(crate) struct CustomReturn {
137 signature_shape: crate::plan::CustomValueShape,
138 body_shape: crate::plan::CustomValueShape,
139 body: ReturnBody<super::CustomExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>>,
140}
141#[derive(Debug, Clone, PartialEq)]
142pub(crate) struct ExternalReturn {
143 signature_shape: crate::plan::ExternalValueShape,
144 body_shape: crate::plan::ExternalValueShape,
145 body:
146 ReturnBody<super::ExternalExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>>,
147}
148pub(crate) type BoolReturn =
149 ReturnBody<BoolExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
150pub(crate) type NilReturn =
151 ReturnBody<NilExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
152pub(crate) type TupleReturn =
153 ReturnBody<TupleExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
154pub(crate) type GenericListReturn =
155 ReturnBody<super::GenericListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
156pub(crate) type ParameterListListReturn = ReturnBody<
157 super::ParameterListListExpr,
158 crate::plan::FunctionCallTarget<FunctionInstantiation>,
159>;
160pub(crate) type IntListReturn =
161 ReturnBody<IntListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
162pub(crate) type FloatListReturn =
163 ReturnBody<FloatListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
164pub(crate) type StringListReturn =
165 ReturnBody<StringListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
166pub(crate) type BitArrayListReturn =
167 ReturnBody<BitArrayListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
168pub(crate) type UtfCodepointListReturn =
169 ReturnBody<UtfCodepointListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
170pub(crate) type CustomListReturn =
171 ReturnBody<CustomListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
172pub(crate) type ExternalListReturn =
173 ReturnBody<ExternalListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
174pub(crate) type BoolListReturn =
175 ReturnBody<BoolListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
176pub(crate) type NilListReturn =
177 ReturnBody<NilListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
178pub(crate) type TupleListReturn =
179 ReturnBody<TupleListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
180pub(crate) type ListListReturn =
181 ReturnBody<ListListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
182pub(crate) type FunctionListReturn =
183 ReturnBody<FunctionListExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
184pub(crate) type GenericFunctionReturn =
185 ReturnBody<super::GenericFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
186pub(crate) type IntFunctionReturn =
187 ReturnBody<super::IntFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
188pub(crate) type FloatFunctionReturn =
189 ReturnBody<super::FloatFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
190pub(crate) type StringFunctionReturn =
191 ReturnBody<super::StringFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
192pub(crate) type BitArrayFunctionReturn =
193 ReturnBody<super::BitArrayFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
194pub(crate) type UtfCodepointFunctionReturn = ReturnBody<
195 super::UtfCodepointFunctionExpr,
196 crate::plan::FunctionCallTarget<FunctionInstantiation>,
197>;
198#[derive(Debug, Clone, PartialEq)]
199pub(crate) struct CustomFunctionReturn {
200 type_: CustomFunctionType,
201 body: ReturnBody<
202 super::CustomFunctionExprKind,
203 crate::plan::FunctionCallTarget<FunctionInstantiation>,
204 >,
205}
206#[derive(Debug, Clone, PartialEq)]
207pub(crate) struct ExternalFunctionReturn {
208 type_: ExternalFunctionType,
209 body: ReturnBody<
210 super::ExternalFunctionExprKind,
211 crate::plan::FunctionCallTarget<FunctionInstantiation>,
212 >,
213}
214pub(crate) type BoolFunctionReturn =
215 ReturnBody<super::BoolFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
216pub(crate) type NilFunctionReturn =
217 ReturnBody<super::NilFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
218pub(crate) type TupleFunctionReturn =
219 ReturnBody<super::TupleFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
220pub(crate) type ListFunctionReturn =
221 ReturnBody<super::ListFunctionExpr, crate::plan::FunctionCallTarget<FunctionInstantiation>>;
222#[derive(Debug, Clone, PartialEq)]
223pub(crate) struct FunctionFunctionReturn {
224 type_: FunctionFunctionType,
225 body: ReturnBody<
226 super::FunctionFunctionExprKind,
227 crate::plan::FunctionCallTarget<FunctionInstantiation>,
228 >,
229}
230
231#[cfg(test)]
232#[derive(Debug, Clone, PartialEq)]
233pub(crate) enum ListReturn {
234 Generic {
235 item_parameter: crate::plan::TypeParameterId,
236 body: GenericListReturn,
237 },
238 Int(IntListReturn),
239 Float(FloatListReturn),
240 String(StringListReturn),
241 BitArray(BitArrayListReturn),
242 UtfCodepoint(UtfCodepointListReturn),
243 Custom {
244 item_type: CustomType,
245 body: CustomListReturn,
246 },
247 External {
248 item_type: ExternalType,
249 body: ExternalListReturn,
250 },
251 Bool(BoolListReturn),
252 Nil(NilListReturn),
253 Tuple {
254 item_type: Vec<ValueType>,
255 body: TupleListReturn,
256 },
257 ParameterList {
258 item_parameter: crate::plan::TypeParameterId,
259 body: ParameterListListReturn,
260 },
261 List {
262 item_shape: ValueStorageShape,
263 body: ListListReturn,
264 },
265 Function {
266 item_type: FunctionType,
267 body: FunctionListReturn,
268 },
269}
270
271#[cfg(test)]
272impl ListReturn {
273 pub(crate) fn expr(expression: ListExpr) -> Self {
274 match expression {
275 ListExpr::Generic(expression) => Self::Generic {
276 item_parameter: expression.item().parameter(),
277 body: GenericListReturn::expr(expression),
278 },
279 ListExpr::Int(expression) => Self::Int(IntListReturn::expr(expression)),
280 ListExpr::Float(expression) => Self::Float(FloatListReturn::expr(expression)),
281 ListExpr::String(expression) => Self::String(StringListReturn::expr(expression)),
282 ListExpr::BitArray(expression) => Self::BitArray(BitArrayListReturn::expr(expression)),
283 ListExpr::UtfCodepoint(expression) => {
284 Self::UtfCodepoint(UtfCodepointListReturn::expr(expression))
285 }
286 ListExpr::Custom(expression) => Self::Custom {
287 item_type: expression.item().item_type(),
288 body: CustomListReturn::expr(expression),
289 },
290 ListExpr::External(expression) => Self::External {
291 item_type: expression.item().item_type(),
292 body: ExternalListReturn::expr(expression),
293 },
294 ListExpr::Bool(expression) => Self::Bool(BoolListReturn::expr(expression)),
295 ListExpr::Nil(expression) => Self::Nil(NilListReturn::expr(expression)),
296 ListExpr::Tuple(expression) => Self::Tuple {
297 item_type: expression.item().item_type(),
298 body: TupleListReturn::expr(expression),
299 },
300 ListExpr::ParameterList(expression) => Self::ParameterList {
301 item_parameter: expression.item().parameter(),
302 body: ParameterListListReturn::expr(expression),
303 },
304 ListExpr::List(expression) => Self::List {
305 item_shape: expression.item().item_shape().clone(),
306 body: ListListReturn::expr(expression),
307 },
308 ListExpr::Function(expression) => Self::Function {
309 item_type: expression.item().item_type(),
310 body: FunctionListReturn::expr(expression),
311 },
312 }
313 }
314
315 pub(crate) fn tail_call(
316 function: FunctionInstantiation,
317 item_type: ValueType,
318 args: Vec<CallArg>,
319 ) -> Self {
320 match item_type {
321 ValueType::Parameter(item_parameter) => Self::Generic {
322 item_parameter,
323 body: GenericListReturn::tail_call(function, args),
324 },
325 ValueType::Int => Self::Int(IntListReturn::tail_call(function, args)),
326 ValueType::Float => Self::Float(FloatListReturn::tail_call(function, args)),
327 ValueType::String => Self::String(StringListReturn::tail_call(function, args)),
328 ValueType::BitArray => Self::BitArray(BitArrayListReturn::tail_call(function, args)),
329 ValueType::UtfCodepoint => {
330 Self::UtfCodepoint(UtfCodepointListReturn::tail_call(function, args))
331 }
332 ValueType::Custom(item_type) => Self::Custom {
333 item_type,
334 body: CustomListReturn::tail_call(function, args),
335 },
336 ValueType::External(item_type) => Self::External {
337 item_type,
338 body: ExternalListReturn::tail_call(function, args),
339 },
340 ValueType::Bool => Self::Bool(BoolListReturn::tail_call(function, args)),
341 ValueType::Nil => Self::Nil(NilListReturn::tail_call(function, args)),
342 ValueType::Tuple(item_type) => Self::Tuple {
343 item_type,
344 body: TupleListReturn::tail_call(function, args),
345 },
346 ValueType::List(item_type) => {
347 match ValueShape::from_value_type(*item_type).representation() {
348 ValueRepresentation::Uninhabited(item_parameter) => Self::ParameterList {
349 item_parameter,
350 body: ParameterListListReturn::tail_call(function, args),
351 },
352 ValueRepresentation::Stored(item_shape) => Self::List {
353 item_shape,
354 body: ListListReturn::tail_call(function, args),
355 },
356 }
357 }
358 ValueType::Function(item_type) => Self::Function {
359 item_type: *item_type,
360 body: FunctionListReturn::tail_call(function, args),
361 },
362 }
363 }
364
365 pub(crate) fn try_bool_case(subject: BoolExpr, true_: Self, false_: Self) -> Option<Self> {
366 Some(match (true_, false_) {
367 (
368 Self::Generic {
369 item_parameter: true_parameter,
370 body: true_,
371 },
372 Self::Generic {
373 item_parameter: false_parameter,
374 body: false_,
375 },
376 ) if true_parameter == false_parameter => Self::Generic {
377 item_parameter: true_parameter,
378 body: GenericListReturn::bool_case(subject, true_, false_),
379 },
380 (Self::Int(true_), Self::Int(false_)) => {
381 Self::Int(IntListReturn::bool_case(subject, true_, false_))
382 }
383 (Self::Float(true_), Self::Float(false_)) => {
384 Self::Float(FloatListReturn::bool_case(subject, true_, false_))
385 }
386 (Self::String(true_), Self::String(false_)) => {
387 Self::String(StringListReturn::bool_case(subject, true_, false_))
388 }
389 (Self::BitArray(true_), Self::BitArray(false_)) => {
390 Self::BitArray(BitArrayListReturn::bool_case(subject, true_, false_))
391 }
392 (Self::UtfCodepoint(true_), Self::UtfCodepoint(false_)) => {
393 Self::UtfCodepoint(UtfCodepointListReturn::bool_case(subject, true_, false_))
394 }
395 (
396 Self::Custom {
397 item_type: true_type,
398 body: true_,
399 },
400 Self::Custom {
401 item_type: false_type,
402 body: false_,
403 },
404 ) if true_type == false_type => Self::Custom {
405 item_type: true_type,
406 body: CustomListReturn::bool_case(subject, true_, false_),
407 },
408 (
409 Self::External {
410 item_type: true_type,
411 body: true_,
412 },
413 Self::External {
414 item_type: false_type,
415 body: false_,
416 },
417 ) if true_type == false_type => Self::External {
418 item_type: true_type,
419 body: ExternalListReturn::bool_case(subject, true_, false_),
420 },
421 (Self::Bool(true_), Self::Bool(false_)) => {
422 Self::Bool(BoolListReturn::bool_case(subject, true_, false_))
423 }
424 (Self::Nil(true_), Self::Nil(false_)) => {
425 Self::Nil(NilListReturn::bool_case(subject, true_, false_))
426 }
427 (
428 Self::Tuple {
429 item_type: true_type,
430 body: true_,
431 },
432 Self::Tuple {
433 item_type: false_type,
434 body: false_,
435 },
436 ) if true_type == false_type => Self::Tuple {
437 item_type: true_type,
438 body: TupleListReturn::bool_case(subject, true_, false_),
439 },
440 (
441 Self::ParameterList {
442 item_parameter: true_parameter,
443 body: true_,
444 },
445 Self::ParameterList {
446 item_parameter: false_parameter,
447 body: false_,
448 },
449 ) if true_parameter == false_parameter => Self::ParameterList {
450 item_parameter: true_parameter,
451 body: ParameterListListReturn::bool_case(subject, true_, false_),
452 },
453 (
454 Self::List {
455 item_shape: true_shape,
456 body: true_,
457 },
458 Self::List {
459 item_shape: false_shape,
460 body: false_,
461 },
462 ) if true_shape == false_shape => Self::List {
463 item_shape: true_shape,
464 body: ListListReturn::bool_case(subject, true_, false_),
465 },
466 (
467 Self::Function {
468 item_type: true_type,
469 body: true_,
470 },
471 Self::Function {
472 item_type: false_type,
473 body: false_,
474 },
475 ) if true_type == false_type => Self::Function {
476 item_type: true_type,
477 body: FunctionListReturn::bool_case(subject, true_, false_),
478 },
479 _ => return None,
480 })
481 }
482
483 pub(crate) fn try_int_case(
484 subject: IntExpr,
485 clauses: Vec<(BigInt, Self)>,
486 fallback: Self,
487 ) -> Option<Self> {
488 match fallback {
489 Self::Generic {
490 item_parameter,
491 body: fallback,
492 } => {
493 let clauses = into_list_return_clauses(clauses, |branch| match branch {
494 Self::Generic {
495 item_parameter: branch_parameter,
496 body,
497 } if branch_parameter == item_parameter => Some(body),
498 _ => None,
499 })?;
500 Some(Self::Generic {
501 item_parameter,
502 body: GenericListReturn::int_case(subject, clauses, fallback),
503 })
504 }
505 Self::Int(fallback) => Some(Self::Int(IntListReturn::int_case(
506 subject,
507 into_list_return_clauses(clauses, |branch| match branch {
508 Self::Int(branch) => Some(branch),
509 _ => None,
510 })?,
511 fallback,
512 ))),
513 Self::Float(fallback) => Some(Self::Float(FloatListReturn::int_case(
514 subject,
515 into_list_return_clauses(clauses, |branch| match branch {
516 Self::Float(branch) => Some(branch),
517 _ => None,
518 })?,
519 fallback,
520 ))),
521 Self::String(fallback) => Some(Self::String(StringListReturn::int_case(
522 subject,
523 into_list_return_clauses(clauses, |branch| match branch {
524 Self::String(branch) => Some(branch),
525 _ => None,
526 })?,
527 fallback,
528 ))),
529 Self::BitArray(fallback) => Some(Self::BitArray(BitArrayListReturn::int_case(
530 subject,
531 into_list_return_clauses(clauses, |branch| match branch {
532 Self::BitArray(branch) => Some(branch),
533 _ => None,
534 })?,
535 fallback,
536 ))),
537 Self::UtfCodepoint(fallback) => {
538 Some(Self::UtfCodepoint(UtfCodepointListReturn::int_case(
539 subject,
540 into_list_return_clauses(clauses, |branch| match branch {
541 Self::UtfCodepoint(branch) => Some(branch),
542 _ => None,
543 })?,
544 fallback,
545 )))
546 }
547 Self::Custom {
548 item_type,
549 body: fallback,
550 } => {
551 let clauses = into_list_return_clauses(clauses, |branch| match branch {
552 Self::Custom {
553 item_type: branch_type,
554 body,
555 } if branch_type == item_type => Some(body),
556 _ => None,
557 })?;
558 Some(Self::Custom {
559 item_type,
560 body: CustomListReturn::int_case(subject, clauses, fallback),
561 })
562 }
563 Self::External {
564 item_type,
565 body: fallback,
566 } => {
567 let clauses = into_list_return_clauses(clauses, |branch| match branch {
568 Self::External {
569 item_type: branch_type,
570 body,
571 } if branch_type == item_type => Some(body),
572 _ => None,
573 })?;
574 Some(Self::External {
575 item_type,
576 body: ExternalListReturn::int_case(subject, clauses, fallback),
577 })
578 }
579 Self::Bool(fallback) => Some(Self::Bool(BoolListReturn::int_case(
580 subject,
581 into_list_return_clauses(clauses, |branch| match branch {
582 Self::Bool(branch) => Some(branch),
583 _ => None,
584 })?,
585 fallback,
586 ))),
587 Self::Nil(fallback) => Some(Self::Nil(NilListReturn::int_case(
588 subject,
589 into_list_return_clauses(clauses, |branch| match branch {
590 Self::Nil(branch) => Some(branch),
591 _ => None,
592 })?,
593 fallback,
594 ))),
595 Self::Tuple {
596 item_type,
597 body: fallback,
598 } => {
599 let clauses = into_list_return_clauses(clauses, |branch| match branch {
600 Self::Tuple {
601 item_type: branch_type,
602 body,
603 } if branch_type == item_type => Some(body),
604 _ => None,
605 })?;
606 Some(Self::Tuple {
607 item_type,
608 body: TupleListReturn::int_case(subject, clauses, fallback),
609 })
610 }
611 Self::ParameterList {
612 item_parameter,
613 body: fallback,
614 } => {
615 let clauses = into_list_return_clauses(clauses, |branch| match branch {
616 Self::ParameterList {
617 item_parameter: branch_parameter,
618 body,
619 } if branch_parameter == item_parameter => Some(body),
620 _ => None,
621 })?;
622 Some(Self::ParameterList {
623 item_parameter,
624 body: ParameterListListReturn::int_case(subject, clauses, fallback),
625 })
626 }
627 Self::List {
628 item_shape,
629 body: fallback,
630 } => {
631 let clauses = into_list_return_clauses(clauses, |branch| match branch {
632 Self::List {
633 item_shape: branch_shape,
634 body,
635 } if branch_shape == item_shape => Some(body),
636 _ => None,
637 })?;
638 Some(Self::List {
639 item_shape,
640 body: ListListReturn::int_case(subject, clauses, fallback),
641 })
642 }
643 Self::Function {
644 item_type,
645 body: fallback,
646 } => {
647 let clauses = into_list_return_clauses(clauses, |branch| match branch {
648 Self::Function {
649 item_type: branch_type,
650 body,
651 } if branch_type == item_type => Some(body),
652 _ => None,
653 })?;
654 Some(Self::Function {
655 item_type,
656 body: FunctionListReturn::int_case(subject, clauses, fallback),
657 })
658 }
659 }
660 }
661
662 pub(crate) fn try_float_case(
663 subject: FloatExpr,
664 clauses: Vec<(f64, Self)>,
665 fallback: Self,
666 ) -> Option<Self> {
667 match fallback {
668 Self::Generic {
669 item_parameter,
670 body: fallback,
671 } => {
672 let clauses = into_list_return_clauses(clauses, |branch| match branch {
673 Self::Generic {
674 item_parameter: branch_parameter,
675 body,
676 } if branch_parameter == item_parameter => Some(body),
677 _ => None,
678 })?;
679 Some(Self::Generic {
680 item_parameter,
681 body: GenericListReturn::float_case(subject, clauses, fallback),
682 })
683 }
684 Self::Int(fallback) => Some(Self::Int(IntListReturn::float_case(
685 subject,
686 into_list_return_clauses(clauses, |branch| match branch {
687 Self::Int(branch) => Some(branch),
688 _ => None,
689 })?,
690 fallback,
691 ))),
692 Self::Float(fallback) => Some(Self::Float(FloatListReturn::float_case(
693 subject,
694 into_list_return_clauses(clauses, |branch| match branch {
695 Self::Float(branch) => Some(branch),
696 _ => None,
697 })?,
698 fallback,
699 ))),
700 Self::String(fallback) => Some(Self::String(StringListReturn::float_case(
701 subject,
702 into_list_return_clauses(clauses, |branch| match branch {
703 Self::String(branch) => Some(branch),
704 _ => None,
705 })?,
706 fallback,
707 ))),
708 Self::BitArray(fallback) => Some(Self::BitArray(BitArrayListReturn::float_case(
709 subject,
710 into_list_return_clauses(clauses, |branch| match branch {
711 Self::BitArray(branch) => Some(branch),
712 _ => None,
713 })?,
714 fallback,
715 ))),
716 Self::UtfCodepoint(fallback) => {
717 Some(Self::UtfCodepoint(UtfCodepointListReturn::float_case(
718 subject,
719 into_list_return_clauses(clauses, |branch| match branch {
720 Self::UtfCodepoint(branch) => Some(branch),
721 _ => None,
722 })?,
723 fallback,
724 )))
725 }
726 Self::Custom {
727 item_type,
728 body: fallback,
729 } => {
730 let clauses = into_list_return_clauses(clauses, |branch| match branch {
731 Self::Custom {
732 item_type: branch_type,
733 body,
734 } if branch_type == item_type => Some(body),
735 _ => None,
736 })?;
737 Some(Self::Custom {
738 item_type,
739 body: CustomListReturn::float_case(subject, clauses, fallback),
740 })
741 }
742 Self::External {
743 item_type,
744 body: fallback,
745 } => {
746 let clauses = into_list_return_clauses(clauses, |branch| match branch {
747 Self::External {
748 item_type: branch_type,
749 body,
750 } if branch_type == item_type => Some(body),
751 _ => None,
752 })?;
753 Some(Self::External {
754 item_type,
755 body: ExternalListReturn::float_case(subject, clauses, fallback),
756 })
757 }
758 Self::Bool(fallback) => Some(Self::Bool(BoolListReturn::float_case(
759 subject,
760 into_list_return_clauses(clauses, |branch| match branch {
761 Self::Bool(branch) => Some(branch),
762 _ => None,
763 })?,
764 fallback,
765 ))),
766 Self::Nil(fallback) => Some(Self::Nil(NilListReturn::float_case(
767 subject,
768 into_list_return_clauses(clauses, |branch| match branch {
769 Self::Nil(branch) => Some(branch),
770 _ => None,
771 })?,
772 fallback,
773 ))),
774 Self::Tuple {
775 item_type,
776 body: fallback,
777 } => {
778 let clauses = into_list_return_clauses(clauses, |branch| match branch {
779 Self::Tuple {
780 item_type: branch_type,
781 body,
782 } if branch_type == item_type => Some(body),
783 _ => None,
784 })?;
785 Some(Self::Tuple {
786 item_type,
787 body: TupleListReturn::float_case(subject, clauses, fallback),
788 })
789 }
790 Self::ParameterList {
791 item_parameter,
792 body: fallback,
793 } => {
794 let clauses = into_list_return_clauses(clauses, |branch| match branch {
795 Self::ParameterList {
796 item_parameter: branch_parameter,
797 body,
798 } if branch_parameter == item_parameter => Some(body),
799 _ => None,
800 })?;
801 Some(Self::ParameterList {
802 item_parameter,
803 body: ParameterListListReturn::float_case(subject, clauses, fallback),
804 })
805 }
806 Self::List {
807 item_shape,
808 body: fallback,
809 } => {
810 let clauses = into_list_return_clauses(clauses, |branch| match branch {
811 Self::List {
812 item_shape: branch_shape,
813 body,
814 } if branch_shape == item_shape => Some(body),
815 _ => None,
816 })?;
817 Some(Self::List {
818 item_shape,
819 body: ListListReturn::float_case(subject, clauses, fallback),
820 })
821 }
822 Self::Function {
823 item_type,
824 body: fallback,
825 } => {
826 let clauses = into_list_return_clauses(clauses, |branch| match branch {
827 Self::Function {
828 item_type: branch_type,
829 body,
830 } if branch_type == item_type => Some(body),
831 _ => None,
832 })?;
833 Some(Self::Function {
834 item_type,
835 body: FunctionListReturn::float_case(subject, clauses, fallback),
836 })
837 }
838 }
839 }
840
841 pub(crate) fn try_string_case(
842 subject: StringExpr,
843 clauses: Vec<(EcoString, Self)>,
844 fallback: Self,
845 ) -> Option<Self> {
846 match fallback {
847 Self::Generic {
848 item_parameter,
849 body: fallback,
850 } => {
851 let clauses = into_list_return_clauses(clauses, |branch| match branch {
852 Self::Generic {
853 item_parameter: branch_parameter,
854 body,
855 } if branch_parameter == item_parameter => Some(body),
856 _ => None,
857 })?;
858 Some(Self::Generic {
859 item_parameter,
860 body: GenericListReturn::string_case(subject, clauses, fallback),
861 })
862 }
863 Self::Int(fallback) => Some(Self::Int(IntListReturn::string_case(
864 subject,
865 into_list_return_clauses(clauses, |branch| match branch {
866 Self::Int(branch) => Some(branch),
867 _ => None,
868 })?,
869 fallback,
870 ))),
871 Self::Float(fallback) => Some(Self::Float(FloatListReturn::string_case(
872 subject,
873 into_list_return_clauses(clauses, |branch| match branch {
874 Self::Float(branch) => Some(branch),
875 _ => None,
876 })?,
877 fallback,
878 ))),
879 Self::String(fallback) => Some(Self::String(StringListReturn::string_case(
880 subject,
881 into_list_return_clauses(clauses, |branch| match branch {
882 Self::String(branch) => Some(branch),
883 _ => None,
884 })?,
885 fallback,
886 ))),
887 Self::BitArray(fallback) => Some(Self::BitArray(BitArrayListReturn::string_case(
888 subject,
889 into_list_return_clauses(clauses, |branch| match branch {
890 Self::BitArray(branch) => Some(branch),
891 _ => None,
892 })?,
893 fallback,
894 ))),
895 Self::UtfCodepoint(fallback) => {
896 Some(Self::UtfCodepoint(UtfCodepointListReturn::string_case(
897 subject,
898 into_list_return_clauses(clauses, |branch| match branch {
899 Self::UtfCodepoint(branch) => Some(branch),
900 _ => None,
901 })?,
902 fallback,
903 )))
904 }
905 Self::Custom {
906 item_type,
907 body: fallback,
908 } => {
909 let clauses = into_list_return_clauses(clauses, |branch| match branch {
910 Self::Custom {
911 item_type: branch_type,
912 body,
913 } if branch_type == item_type => Some(body),
914 _ => None,
915 })?;
916 Some(Self::Custom {
917 item_type,
918 body: CustomListReturn::string_case(subject, clauses, fallback),
919 })
920 }
921 Self::External {
922 item_type,
923 body: fallback,
924 } => {
925 let clauses = into_list_return_clauses(clauses, |branch| match branch {
926 Self::External {
927 item_type: branch_type,
928 body,
929 } if branch_type == item_type => Some(body),
930 _ => None,
931 })?;
932 Some(Self::External {
933 item_type,
934 body: ExternalListReturn::string_case(subject, clauses, fallback),
935 })
936 }
937 Self::Bool(fallback) => Some(Self::Bool(BoolListReturn::string_case(
938 subject,
939 into_list_return_clauses(clauses, |branch| match branch {
940 Self::Bool(branch) => Some(branch),
941 _ => None,
942 })?,
943 fallback,
944 ))),
945 Self::Nil(fallback) => Some(Self::Nil(NilListReturn::string_case(
946 subject,
947 into_list_return_clauses(clauses, |branch| match branch {
948 Self::Nil(branch) => Some(branch),
949 _ => None,
950 })?,
951 fallback,
952 ))),
953 Self::Tuple {
954 item_type,
955 body: fallback,
956 } => {
957 let clauses = into_list_return_clauses(clauses, |branch| match branch {
958 Self::Tuple {
959 item_type: branch_type,
960 body,
961 } if branch_type == item_type => Some(body),
962 _ => None,
963 })?;
964 Some(Self::Tuple {
965 item_type,
966 body: TupleListReturn::string_case(subject, clauses, fallback),
967 })
968 }
969 Self::ParameterList {
970 item_parameter,
971 body: fallback,
972 } => {
973 let clauses = into_list_return_clauses(clauses, |branch| match branch {
974 Self::ParameterList {
975 item_parameter: branch_parameter,
976 body,
977 } if branch_parameter == item_parameter => Some(body),
978 _ => None,
979 })?;
980 Some(Self::ParameterList {
981 item_parameter,
982 body: ParameterListListReturn::string_case(subject, clauses, fallback),
983 })
984 }
985 Self::List {
986 item_shape,
987 body: fallback,
988 } => {
989 let clauses = into_list_return_clauses(clauses, |branch| match branch {
990 Self::List {
991 item_shape: branch_shape,
992 body,
993 } if branch_shape == item_shape => Some(body),
994 _ => None,
995 })?;
996 Some(Self::List {
997 item_shape,
998 body: ListListReturn::string_case(subject, clauses, fallback),
999 })
1000 }
1001 Self::Function {
1002 item_type,
1003 body: fallback,
1004 } => {
1005 let clauses = into_list_return_clauses(clauses, |branch| match branch {
1006 Self::Function {
1007 item_type: branch_type,
1008 body,
1009 } if branch_type == item_type => Some(body),
1010 _ => None,
1011 })?;
1012 Some(Self::Function {
1013 item_type,
1014 body: FunctionListReturn::string_case(subject, clauses, fallback),
1015 })
1016 }
1017 }
1018 }
1019
1020 pub(crate) fn try_block(steps: Vec<Step>, return_: Self) -> Self {
1021 match return_ {
1022 Self::Generic {
1023 item_parameter,
1024 body,
1025 } => Self::Generic {
1026 item_parameter,
1027 body: GenericListReturn::block(steps, body),
1028 },
1029 Self::Int(return_) => Self::Int(IntListReturn::block(steps, return_)),
1030 Self::Float(return_) => Self::Float(FloatListReturn::block(steps, return_)),
1031 Self::String(return_) => Self::String(StringListReturn::block(steps, return_)),
1032 Self::BitArray(return_) => Self::BitArray(BitArrayListReturn::block(steps, return_)),
1033 Self::UtfCodepoint(return_) => {
1034 Self::UtfCodepoint(UtfCodepointListReturn::block(steps, return_))
1035 }
1036 Self::Custom { item_type, body } => Self::Custom {
1037 item_type,
1038 body: CustomListReturn::block(steps, body),
1039 },
1040 Self::External { item_type, body } => Self::External {
1041 item_type,
1042 body: ExternalListReturn::block(steps, body),
1043 },
1044 Self::Bool(return_) => Self::Bool(BoolListReturn::block(steps, return_)),
1045 Self::Nil(return_) => Self::Nil(NilListReturn::block(steps, return_)),
1046 Self::Tuple { item_type, body } => Self::Tuple {
1047 item_type,
1048 body: TupleListReturn::block(steps, body),
1049 },
1050 Self::ParameterList {
1051 item_parameter,
1052 body,
1053 } => Self::ParameterList {
1054 item_parameter,
1055 body: ParameterListListReturn::block(steps, body),
1056 },
1057 Self::List { item_shape, body } => Self::List {
1058 item_shape,
1059 body: ListListReturn::block(steps, body),
1060 },
1061 Self::Function { item_type, body } => Self::Function {
1062 item_type,
1063 body: FunctionListReturn::block(steps, body),
1064 },
1065 }
1066 }
1067}
1068
1069#[cfg(test)]
1070fn into_list_return_clauses<Pattern, Body>(
1071 clauses: Vec<(Pattern, ListReturn)>,
1072 mut into_body: impl FnMut(ListReturn) -> Option<Body>,
1073) -> Option<Vec<(Pattern, Body)>> {
1074 clauses
1075 .into_iter()
1076 .map(|(pattern, branch)| into_body(branch).map(|branch| (pattern, branch)))
1077 .collect()
1078}
1079
1080#[derive(Debug, Clone, PartialEq)]
1081pub(crate) struct ReturnBody<Expression, Function> {
1082 kind: ReturnBodyKind<Expression, Function>,
1083}
1084
1085#[derive(Debug, Clone, PartialEq)]
1086pub(crate) enum ReturnBodyKind<Expression, Function> {
1087 Expr(Expression),
1088 TailCall {
1089 function: Function,
1090 args: Vec<CallArg>,
1091 },
1092 BoolCase {
1093 subject: BoolExpr,
1094 true_: Box<ReturnBody<Expression, Function>>,
1095 false_: Box<ReturnBody<Expression, Function>>,
1096 },
1097 IntCase {
1098 subject: IntExpr,
1099 clauses: Vec<(BigInt, ReturnBody<Expression, Function>)>,
1100 fallback: Box<ReturnBody<Expression, Function>>,
1101 },
1102 FloatCase {
1103 subject: FloatExpr,
1104 clauses: Vec<(f64, ReturnBody<Expression, Function>)>,
1105 fallback: Box<ReturnBody<Expression, Function>>,
1106 },
1107 StringCase {
1108 subject: StringExpr,
1109 clauses: Vec<(EcoString, ReturnBody<Expression, Function>)>,
1110 fallback: Box<ReturnBody<Expression, Function>>,
1111 },
1112 Block {
1113 steps: Vec<Step>,
1114 return_: Box<ReturnBody<Expression, Function>>,
1115 },
1116}
1117
1118#[derive(Debug, Clone, PartialEq)]
1119pub struct ReturnExpr {
1120 kind: ReturnExprKind,
1121}
1122
1123#[derive(Debug, Clone, PartialEq)]
1124pub(crate) enum ReturnExprKind {
1125 Generic {
1126 parameter: crate::plan::TypeParameterId,
1127 body: GenericReturn,
1128 },
1129 Int {
1130 body: IntReturn,
1131 },
1132 Float {
1133 body: FloatReturn,
1134 },
1135 String {
1136 body: StringReturn,
1137 },
1138 BitArray {
1139 body: BitArrayReturn,
1140 },
1141 UtfCodepoint {
1142 body: UtfCodepointReturn,
1143 },
1144 Custom {
1145 body: CustomReturn,
1146 },
1147 External {
1148 body: ExternalReturn,
1149 },
1150 Bool {
1151 body: BoolReturn,
1152 },
1153 Nil {
1154 body: NilReturn,
1155 },
1156 Tuple {
1157 type_: Vec<ValueType>,
1158 body: TupleReturn,
1159 },
1160 GenericList {
1161 parameter: crate::plan::TypeParameterId,
1162 body: GenericListReturn,
1163 },
1164 ParameterListList {
1165 parameter: crate::plan::TypeParameterId,
1166 body: ParameterListListReturn,
1167 },
1168 IntList {
1169 body: IntListReturn,
1170 },
1171 StringList {
1172 body: StringListReturn,
1173 },
1174 BitArrayList {
1175 body: BitArrayListReturn,
1176 },
1177 UtfCodepointList {
1178 body: UtfCodepointListReturn,
1179 },
1180 CustomList {
1181 item_type: CustomType,
1182 body: CustomListReturn,
1183 },
1184 ExternalList {
1185 item_type: ExternalType,
1186 body: ExternalListReturn,
1187 },
1188 FloatList {
1189 body: FloatListReturn,
1190 },
1191 BoolList {
1192 body: BoolListReturn,
1193 },
1194 NilList {
1195 body: NilListReturn,
1196 },
1197 TupleList {
1198 item_type: Vec<ValueType>,
1199 body: TupleListReturn,
1200 },
1201 ListList {
1202 item_shape: ValueStorageShape,
1203 body: ListListReturn,
1204 },
1205 FunctionList {
1206 item_type: FunctionType,
1207 body: FunctionListReturn,
1208 },
1209 GenericFunction {
1210 shape: crate::plan::FunctionShape,
1211 body: GenericFunctionReturn,
1212 },
1213 IntFunction {
1214 shape: crate::plan::FunctionShape,
1215 body: IntFunctionReturn,
1216 },
1217 FloatFunction {
1218 shape: crate::plan::FunctionShape,
1219 body: FloatFunctionReturn,
1220 },
1221 StringFunction {
1222 shape: crate::plan::FunctionShape,
1223 body: StringFunctionReturn,
1224 },
1225 BitArrayFunction {
1226 shape: crate::plan::FunctionShape,
1227 body: BitArrayFunctionReturn,
1228 },
1229 UtfCodepointFunction {
1230 shape: crate::plan::FunctionShape,
1231 body: UtfCodepointFunctionReturn,
1232 },
1233 CustomFunction {
1234 shape: crate::plan::FunctionShape,
1235 body: CustomFunctionReturn,
1236 },
1237 ExternalFunction {
1238 shape: crate::plan::FunctionShape,
1239 body: ExternalFunctionReturn,
1240 },
1241 BoolFunction {
1242 shape: crate::plan::FunctionShape,
1243 body: BoolFunctionReturn,
1244 },
1245 NilFunction {
1246 shape: crate::plan::FunctionShape,
1247 body: NilFunctionReturn,
1248 },
1249 TupleFunction {
1250 shape: crate::plan::FunctionShape,
1251 body: TupleFunctionReturn,
1252 },
1253 ListFunction {
1254 shape: crate::plan::FunctionShape,
1255 item_type: ValueType,
1256 body: ListFunctionReturn,
1257 },
1258 FunctionFunction {
1259 shape: crate::plan::FunctionShape,
1260 body: FunctionFunctionReturn,
1261 },
1262}
1263
1264impl FunctionTemplate {
1265 #[cfg(test)]
1266 pub(crate) fn new(
1267 id: FunctionTemplateId,
1268 name: EcoString,
1269 params: Vec<Param>,
1270 steps: Vec<Step>,
1271 return_: ReturnExpr,
1272 ) -> Self {
1273 Self::with_captures(id, name, params, Vec::new(), steps, return_)
1274 }
1275
1276 #[cfg(test)]
1277 pub(crate) fn with_captures(
1278 id: FunctionTemplateId,
1279 name: EcoString,
1280 params: Vec<Param>,
1281 captures: Vec<ParamSlot>,
1282 steps: Vec<Step>,
1283 return_: ReturnExpr,
1284 ) -> Self {
1285 let signature = FunctionTemplateSignature::new(
1286 id,
1287 TypeScheme::new(0),
1288 crate::plan::FunctionShape::new(
1289 params.iter().map(|param| param.shape().clone()).collect(),
1290 crate::plan::ValueShape::from_value_type(return_.value_type()),
1291 ),
1292 );
1293 Self::from_signature(signature, name, params, captures, steps, return_)
1294 }
1295
1296 pub(crate) fn from_signature(
1297 signature: FunctionTemplateSignature,
1298 name: EcoString,
1299 params: Vec<Param>,
1300 captures: Vec<ParamSlot>,
1301 steps: Vec<Step>,
1302 return_: ReturnExpr,
1303 ) -> Self {
1304 Self {
1305 signature,
1306 name,
1307 entry: FunctionEntry::new(params, captures),
1308 steps,
1309 return_,
1310 }
1311 }
1312
1313 pub fn id(&self) -> FunctionTemplateId {
1314 self.signature.id()
1315 }
1316
1317 pub fn scheme(&self) -> &TypeScheme {
1318 self.signature.scheme()
1319 }
1320
1321 pub fn name(&self) -> &EcoString {
1322 &self.name
1323 }
1324
1325 pub fn params(&self) -> &[Param] {
1326 self.entry.params()
1327 }
1328
1329 pub fn steps(&self) -> &[Step] {
1330 &self.steps
1331 }
1332
1333 pub fn return_(&self) -> &ReturnExpr {
1334 &self.return_
1335 }
1336
1337 pub(crate) fn signature(&self) -> &FunctionTemplateSignature {
1338 &self.signature
1339 }
1340
1341 pub(crate) fn entry(&self) -> &FunctionEntry {
1342 &self.entry
1343 }
1344}
1345
1346impl ReturnExpr {
1347 pub(crate) fn generic_body(
1348 parameter: crate::plan::TypeParameterId,
1349 body: GenericReturn,
1350 ) -> Self {
1351 Self {
1352 kind: ReturnExprKind::Generic { parameter, body },
1353 }
1354 }
1355
1356 #[cfg(test)]
1357 pub(crate) fn int(_runtime_id: IntFunctionId, expression: IntExpr) -> Self {
1358 Self::int_body(ReturnBody::expr(expression))
1359 }
1360
1361 pub(crate) fn int_body(body: IntReturn) -> Self {
1362 Self {
1363 kind: ReturnExprKind::Int { body },
1364 }
1365 }
1366
1367 pub(crate) fn float_body(body: FloatReturn) -> Self {
1368 Self {
1369 kind: ReturnExprKind::Float { body },
1370 }
1371 }
1372
1373 pub(crate) fn string_body(body: StringReturn) -> Self {
1374 Self {
1375 kind: ReturnExprKind::String { body },
1376 }
1377 }
1378
1379 pub(crate) fn bit_array_body(body: BitArrayReturn) -> Self {
1380 Self {
1381 kind: ReturnExprKind::BitArray { body },
1382 }
1383 }
1384
1385 pub(crate) fn utf_codepoint_body(body: UtfCodepointReturn) -> Self {
1386 Self {
1387 kind: ReturnExprKind::UtfCodepoint { body },
1388 }
1389 }
1390
1391 pub(crate) fn custom_body(body: CustomReturn) -> Self {
1392 Self {
1393 kind: ReturnExprKind::Custom { body },
1394 }
1395 }
1396
1397 pub(crate) fn external_body(body: ExternalReturn) -> Self {
1398 Self {
1399 kind: ReturnExprKind::External { body },
1400 }
1401 }
1402
1403 #[cfg(test)]
1404 pub(crate) fn bool(_runtime_id: BoolFunctionId, expression: BoolExpr) -> Self {
1405 Self::bool_body(ReturnBody::expr(expression))
1406 }
1407
1408 pub(crate) fn bool_body(body: BoolReturn) -> Self {
1409 Self {
1410 kind: ReturnExprKind::Bool { body },
1411 }
1412 }
1413
1414 pub(crate) fn nil_body(body: NilReturn) -> Self {
1415 Self {
1416 kind: ReturnExprKind::Nil { body },
1417 }
1418 }
1419
1420 pub(crate) fn tuple_body(type_: Vec<ValueType>, body: TupleReturn) -> Self {
1421 Self {
1422 kind: ReturnExprKind::Tuple { type_, body },
1423 }
1424 }
1425
1426 pub(crate) fn generic_list_body(
1427 parameter: crate::plan::TypeParameterId,
1428 body: GenericListReturn,
1429 ) -> Self {
1430 Self {
1431 kind: ReturnExprKind::GenericList { parameter, body },
1432 }
1433 }
1434
1435 pub(crate) fn parameter_list_list_body(
1436 parameter: crate::plan::TypeParameterId,
1437 body: ParameterListListReturn,
1438 ) -> Self {
1439 Self {
1440 kind: ReturnExprKind::ParameterListList { parameter, body },
1441 }
1442 }
1443
1444 pub(crate) fn int_list_body(body: IntListReturn) -> Self {
1445 Self {
1446 kind: ReturnExprKind::IntList { body },
1447 }
1448 }
1449
1450 pub(crate) fn string_list_body(body: StringListReturn) -> Self {
1451 Self {
1452 kind: ReturnExprKind::StringList { body },
1453 }
1454 }
1455
1456 pub(crate) fn bit_array_list_body(body: BitArrayListReturn) -> Self {
1457 Self {
1458 kind: ReturnExprKind::BitArrayList { body },
1459 }
1460 }
1461
1462 pub(crate) fn utf_codepoint_list_body(body: UtfCodepointListReturn) -> Self {
1463 Self {
1464 kind: ReturnExprKind::UtfCodepointList { body },
1465 }
1466 }
1467
1468 pub(crate) fn custom_list_body(item_type: CustomType, body: CustomListReturn) -> Self {
1469 Self {
1470 kind: ReturnExprKind::CustomList { item_type, body },
1471 }
1472 }
1473
1474 pub(crate) fn external_list_body(item_type: ExternalType, body: ExternalListReturn) -> Self {
1475 Self {
1476 kind: ReturnExprKind::ExternalList { item_type, body },
1477 }
1478 }
1479
1480 pub(crate) fn float_list_body(body: FloatListReturn) -> Self {
1481 Self {
1482 kind: ReturnExprKind::FloatList { body },
1483 }
1484 }
1485
1486 pub(crate) fn bool_list_body(body: BoolListReturn) -> Self {
1487 Self {
1488 kind: ReturnExprKind::BoolList { body },
1489 }
1490 }
1491
1492 pub(crate) fn nil_list_body(body: NilListReturn) -> Self {
1493 Self {
1494 kind: ReturnExprKind::NilList { body },
1495 }
1496 }
1497
1498 pub(crate) fn tuple_list_body(item_type: Vec<ValueType>, body: TupleListReturn) -> Self {
1499 Self {
1500 kind: ReturnExprKind::TupleList { item_type, body },
1501 }
1502 }
1503
1504 pub(crate) fn list_list_body(item_shape: ValueStorageShape, body: ListListReturn) -> Self {
1505 Self {
1506 kind: ReturnExprKind::ListList { item_shape, body },
1507 }
1508 }
1509
1510 pub(crate) fn function_list_body(item_type: FunctionType, body: FunctionListReturn) -> Self {
1511 Self {
1512 kind: ReturnExprKind::FunctionList { item_type, body },
1513 }
1514 }
1515
1516 pub(crate) fn generic_function_shape_body(
1517 shape: crate::plan::FunctionShape,
1518 body: GenericFunctionReturn,
1519 ) -> Self {
1520 Self {
1521 kind: ReturnExprKind::GenericFunction { shape, body },
1522 }
1523 }
1524
1525 pub(crate) fn int_function_shape_body(
1526 shape: crate::plan::FunctionShape,
1527 body: IntFunctionReturn,
1528 ) -> Self {
1529 Self {
1530 kind: ReturnExprKind::IntFunction { shape, body },
1531 }
1532 }
1533
1534 pub(crate) fn float_function_shape_body(
1535 shape: crate::plan::FunctionShape,
1536 body: FloatFunctionReturn,
1537 ) -> Self {
1538 Self {
1539 kind: ReturnExprKind::FloatFunction { shape, body },
1540 }
1541 }
1542
1543 pub(crate) fn string_function_shape_body(
1544 shape: crate::plan::FunctionShape,
1545 body: StringFunctionReturn,
1546 ) -> Self {
1547 Self {
1548 kind: ReturnExprKind::StringFunction { shape, body },
1549 }
1550 }
1551
1552 pub(crate) fn bit_array_function_shape_body(
1553 shape: crate::plan::FunctionShape,
1554 body: BitArrayFunctionReturn,
1555 ) -> Self {
1556 Self {
1557 kind: ReturnExprKind::BitArrayFunction { shape, body },
1558 }
1559 }
1560
1561 pub(crate) fn utf_codepoint_function_shape_body(
1562 shape: crate::plan::FunctionShape,
1563 body: UtfCodepointFunctionReturn,
1564 ) -> Self {
1565 Self {
1566 kind: ReturnExprKind::UtfCodepointFunction { shape, body },
1567 }
1568 }
1569
1570 pub(crate) fn custom_function_shape_body(
1571 shape: crate::plan::FunctionShape,
1572 body: CustomFunctionReturn,
1573 ) -> Self {
1574 Self {
1575 kind: ReturnExprKind::CustomFunction { shape, body },
1576 }
1577 }
1578
1579 pub(crate) fn external_function_shape_body(
1580 shape: crate::plan::FunctionShape,
1581 body: ExternalFunctionReturn,
1582 ) -> Self {
1583 Self {
1584 kind: ReturnExprKind::ExternalFunction { shape, body },
1585 }
1586 }
1587
1588 pub(crate) fn bool_function_shape_body(
1589 shape: crate::plan::FunctionShape,
1590 body: BoolFunctionReturn,
1591 ) -> Self {
1592 Self {
1593 kind: ReturnExprKind::BoolFunction { shape, body },
1594 }
1595 }
1596
1597 pub(crate) fn nil_function_shape_body(
1598 shape: crate::plan::FunctionShape,
1599 body: NilFunctionReturn,
1600 ) -> Self {
1601 Self {
1602 kind: ReturnExprKind::NilFunction { shape, body },
1603 }
1604 }
1605
1606 pub(crate) fn tuple_function_shape_body(
1607 shape: crate::plan::FunctionShape,
1608 body: TupleFunctionReturn,
1609 ) -> Self {
1610 Self {
1611 kind: ReturnExprKind::TupleFunction { shape, body },
1612 }
1613 }
1614
1615 pub(crate) fn list_function_shape_body(
1616 shape: crate::plan::FunctionShape,
1617 item_type: ValueType,
1618 body: ListFunctionReturn,
1619 ) -> Self {
1620 Self {
1621 kind: ReturnExprKind::ListFunction {
1622 shape,
1623 item_type,
1624 body,
1625 },
1626 }
1627 }
1628
1629 pub(crate) fn function_function_shape_body(
1630 shape: crate::plan::FunctionShape,
1631 body: FunctionFunctionReturn,
1632 ) -> Self {
1633 Self {
1634 kind: ReturnExprKind::FunctionFunction { shape, body },
1635 }
1636 }
1637
1638 pub fn value_type(&self) -> ValueType {
1639 match self.kind() {
1640 ReturnExprKind::Generic { parameter, .. } => ValueType::Parameter(*parameter),
1641 ReturnExprKind::Int { .. } => ValueType::Int,
1642 ReturnExprKind::Float { .. } => ValueType::Float,
1643 ReturnExprKind::String { .. } => ValueType::String,
1644 ReturnExprKind::BitArray { .. } => ValueType::BitArray,
1645 ReturnExprKind::UtfCodepoint { .. } => ValueType::UtfCodepoint,
1646 ReturnExprKind::Custom { body } => ValueType::Custom(body.shape().type_().clone()),
1647 ReturnExprKind::External { body } => ValueType::External(body.shape().type_().clone()),
1648 ReturnExprKind::Bool { .. } => ValueType::Bool,
1649 ReturnExprKind::Nil { .. } => ValueType::Nil,
1650 ReturnExprKind::Tuple { type_, .. } => ValueType::Tuple(type_.clone()),
1651 ReturnExprKind::GenericList { parameter, .. } => {
1652 ValueType::List(Box::new(ValueType::Parameter(*parameter)))
1653 }
1654 ReturnExprKind::ParameterListList { parameter, .. } => ValueType::List(Box::new(
1655 ValueType::List(Box::new(ValueType::Parameter(*parameter))),
1656 )),
1657 ReturnExprKind::IntList { .. } => ValueType::List(Box::new(ValueType::Int)),
1658 ReturnExprKind::StringList { .. } => ValueType::List(Box::new(ValueType::String)),
1659 ReturnExprKind::BitArrayList { .. } => ValueType::List(Box::new(ValueType::BitArray)),
1660 ReturnExprKind::UtfCodepointList { .. } => {
1661 ValueType::List(Box::new(ValueType::UtfCodepoint))
1662 }
1663 ReturnExprKind::CustomList { item_type, .. } => {
1664 ValueType::List(Box::new(ValueType::Custom(item_type.clone())))
1665 }
1666 ReturnExprKind::ExternalList { item_type, .. } => {
1667 ValueType::List(Box::new(ValueType::External(item_type.clone())))
1668 }
1669 ReturnExprKind::FloatList { .. } => ValueType::List(Box::new(ValueType::Float)),
1670 ReturnExprKind::BoolList { .. } => ValueType::List(Box::new(ValueType::Bool)),
1671 ReturnExprKind::NilList { .. } => ValueType::List(Box::new(ValueType::Nil)),
1672 ReturnExprKind::TupleList { item_type, .. } => {
1673 ValueType::List(Box::new(ValueType::Tuple(item_type.clone())))
1674 }
1675 ReturnExprKind::ListList { item_shape, .. } => {
1676 ValueType::List(Box::new(ValueType::List(Box::new(item_shape.value_type()))))
1677 }
1678 ReturnExprKind::FunctionList { item_type, .. } => {
1679 ValueType::List(Box::new(ValueType::Function(Box::new(item_type.clone()))))
1680 }
1681 ReturnExprKind::GenericFunction { shape, .. }
1682 | ReturnExprKind::IntFunction { shape, .. }
1683 | ReturnExprKind::FloatFunction { shape, .. }
1684 | ReturnExprKind::StringFunction { shape, .. }
1685 | ReturnExprKind::BitArrayFunction { shape, .. }
1686 | ReturnExprKind::UtfCodepointFunction { shape, .. }
1687 | ReturnExprKind::CustomFunction { shape, .. }
1688 | ReturnExprKind::ExternalFunction { shape, .. }
1689 | ReturnExprKind::BoolFunction { shape, .. }
1690 | ReturnExprKind::NilFunction { shape, .. }
1691 | ReturnExprKind::TupleFunction { shape, .. }
1692 | ReturnExprKind::ListFunction { shape, .. }
1693 | ReturnExprKind::FunctionFunction { shape, .. } => {
1694 ValueType::Function(Box::new(shape.type_()))
1695 }
1696 }
1697 }
1698
1699 pub(crate) fn kind(&self) -> &ReturnExprKind {
1700 &self.kind
1701 }
1702}
1703
1704impl CustomReturn {
1705 #[cfg(test)]
1706 pub(crate) fn expr(expression: CustomExpr) -> Self {
1707 let shape = expression.shape().clone();
1708 Self::with_signature_shape(shape, expression)
1709 }
1710
1711 pub(crate) fn with_signature_shape(
1712 signature_shape: crate::plan::CustomValueShape,
1713 expression: CustomExpr,
1714 ) -> Self {
1715 let (body_shape, kind) = expression.into_parts();
1716 Self {
1717 signature_shape,
1718 body_shape,
1719 body: custom_return_body(kind),
1720 }
1721 }
1722
1723 #[cfg(test)]
1724 pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
1725 Self {
1726 signature_shape: return_.signature_shape,
1727 body_shape: return_.body_shape,
1728 body: ReturnBody::block(steps, return_.body),
1729 }
1730 }
1731
1732 pub(crate) fn shape(&self) -> &crate::plan::CustomValueShape {
1733 &self.body_shape
1734 }
1735
1736 pub(crate) fn signature_shape(&self) -> &crate::plan::CustomValueShape {
1737 &self.signature_shape
1738 }
1739
1740 pub(crate) fn body(
1741 &self,
1742 ) -> &ReturnBody<super::CustomExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>>
1743 {
1744 &self.body
1745 }
1746}
1747
1748fn custom_return_body(
1749 kind: super::CustomExprKind,
1750) -> ReturnBody<super::CustomExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>> {
1751 use super::CustomExprKind as K;
1752
1753 match kind {
1754 K::Call {
1755 function,
1756 args,
1757 site,
1758 } => ReturnBody::tail_call(crate::plan::FunctionCallTarget::new(function, site), args),
1759 K::BoolCase {
1760 subject,
1761 true_,
1762 false_,
1763 } => ReturnBody::bool_case(
1764 *subject,
1765 custom_return_body(*true_),
1766 custom_return_body(*false_),
1767 ),
1768 K::IntCase {
1769 subject,
1770 clauses,
1771 fallback,
1772 } => ReturnBody::int_case(
1773 *subject,
1774 clauses
1775 .into_iter()
1776 .map(|(pattern, branch)| (pattern, custom_return_body(branch)))
1777 .collect(),
1778 custom_return_body(*fallback),
1779 ),
1780 K::FloatCase {
1781 subject,
1782 clauses,
1783 fallback,
1784 } => ReturnBody::float_case(
1785 *subject,
1786 clauses
1787 .into_iter()
1788 .map(|(pattern, branch)| (pattern, custom_return_body(branch)))
1789 .collect(),
1790 custom_return_body(*fallback),
1791 ),
1792 K::StringCase {
1793 subject,
1794 clauses,
1795 fallback,
1796 } => ReturnBody::string_case(
1797 *subject,
1798 clauses
1799 .into_iter()
1800 .map(|(pattern, branch)| (pattern, custom_return_body(branch)))
1801 .collect(),
1802 custom_return_body(*fallback),
1803 ),
1804 K::Block { steps, return_ } => ReturnBody::block(steps, custom_return_body(*return_)),
1805 kind => ReturnBody::expr(kind),
1806 }
1807}
1808
1809impl ExternalReturn {
1810 pub(crate) fn with_signature_shape(
1811 signature_shape: crate::plan::ExternalValueShape,
1812 expression: ExternalExpr,
1813 ) -> Self {
1814 let (body_shape, kind) = expression.into_parts();
1815 Self {
1816 signature_shape,
1817 body_shape,
1818 body: external_return_body(kind),
1819 }
1820 }
1821
1822 pub(crate) fn shape(&self) -> &crate::plan::ExternalValueShape {
1823 &self.body_shape
1824 }
1825
1826 pub(crate) fn signature_shape(&self) -> &crate::plan::ExternalValueShape {
1827 &self.signature_shape
1828 }
1829
1830 pub(crate) fn body(
1831 &self,
1832 ) -> &ReturnBody<super::ExternalExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>>
1833 {
1834 &self.body
1835 }
1836}
1837
1838fn external_return_body(
1839 kind: super::ExternalExprKind,
1840) -> ReturnBody<super::ExternalExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>> {
1841 use super::ExternalExprKind as K;
1842
1843 match kind {
1844 K::Call {
1845 function,
1846 args,
1847 site,
1848 } => ReturnBody::tail_call(crate::plan::FunctionCallTarget::new(function, site), args),
1849 K::BoolCase {
1850 subject,
1851 true_,
1852 false_,
1853 } => ReturnBody::bool_case(
1854 *subject,
1855 external_return_expression(*true_),
1856 external_return_expression(*false_),
1857 ),
1858 K::IntCase {
1859 subject,
1860 clauses,
1861 fallback,
1862 } => ReturnBody::int_case(
1863 *subject,
1864 clauses
1865 .into_iter()
1866 .map(|(pattern, branch)| (pattern, external_return_expression(branch)))
1867 .collect(),
1868 external_return_expression(*fallback),
1869 ),
1870 K::FloatCase {
1871 subject,
1872 clauses,
1873 fallback,
1874 } => ReturnBody::float_case(
1875 *subject,
1876 clauses
1877 .into_iter()
1878 .map(|(pattern, branch)| (pattern, external_return_expression(branch)))
1879 .collect(),
1880 external_return_expression(*fallback),
1881 ),
1882 K::StringCase {
1883 subject,
1884 clauses,
1885 fallback,
1886 } => ReturnBody::string_case(
1887 *subject,
1888 clauses
1889 .into_iter()
1890 .map(|(pattern, branch)| (pattern, external_return_expression(branch)))
1891 .collect(),
1892 external_return_expression(*fallback),
1893 ),
1894 K::Block { steps, return_ } => {
1895 ReturnBody::block(steps, external_return_expression(*return_))
1896 }
1897 kind => ReturnBody::expr(kind),
1898 }
1899}
1900
1901fn external_return_expression(
1902 expression: ExternalExpr,
1903) -> ReturnBody<super::ExternalExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>> {
1904 let (_, kind) = expression.into_parts();
1905 external_return_body(kind)
1906}
1907
1908impl CustomFunctionReturn {
1909 pub(crate) fn expr(expression: super::CustomFunctionExpr) -> Self {
1910 let (type_, kind) = expression.into_parts();
1911 Self {
1912 type_,
1913 body: custom_function_return_body(kind),
1914 }
1915 }
1916
1917 pub(crate) fn type_(&self) -> &CustomFunctionType {
1918 &self.type_
1919 }
1920
1921 pub(crate) fn body(
1922 &self,
1923 ) -> &ReturnBody<
1924 super::CustomFunctionExprKind,
1925 crate::plan::FunctionCallTarget<FunctionInstantiation>,
1926 > {
1927 &self.body
1928 }
1929}
1930
1931fn custom_function_return_body(
1932 kind: super::CustomFunctionExprKind,
1933) -> ReturnBody<super::CustomFunctionExprKind, crate::plan::FunctionCallTarget<FunctionInstantiation>>
1934{
1935 use super::CustomFunctionExprKind as K;
1936
1937 match kind {
1938 K::Call {
1939 function,
1940 args,
1941 site,
1942 } => ReturnBody::tail_call(crate::plan::FunctionCallTarget::new(function, site), args),
1943 K::BoolCase {
1944 subject,
1945 true_,
1946 false_,
1947 } => ReturnBody::bool_case(
1948 *subject,
1949 custom_function_return_body(*true_),
1950 custom_function_return_body(*false_),
1951 ),
1952 K::IntCase {
1953 subject,
1954 clauses,
1955 fallback,
1956 } => ReturnBody::int_case(
1957 *subject,
1958 clauses
1959 .into_iter()
1960 .map(|(pattern, branch)| (pattern, custom_function_return_body(branch)))
1961 .collect(),
1962 custom_function_return_body(*fallback),
1963 ),
1964 K::FloatCase {
1965 subject,
1966 clauses,
1967 fallback,
1968 } => ReturnBody::float_case(
1969 *subject,
1970 clauses
1971 .into_iter()
1972 .map(|(pattern, branch)| (pattern, custom_function_return_body(branch)))
1973 .collect(),
1974 custom_function_return_body(*fallback),
1975 ),
1976 K::StringCase {
1977 subject,
1978 clauses,
1979 fallback,
1980 } => ReturnBody::string_case(
1981 *subject,
1982 clauses
1983 .into_iter()
1984 .map(|(pattern, branch)| (pattern, custom_function_return_body(branch)))
1985 .collect(),
1986 custom_function_return_body(*fallback),
1987 ),
1988 K::Block { steps, return_ } => {
1989 ReturnBody::block(steps, custom_function_return_body(*return_))
1990 }
1991 kind => ReturnBody::expr(kind),
1992 }
1993}
1994
1995impl ExternalFunctionReturn {
1996 pub(crate) fn expr(expression: super::ExternalFunctionExpr) -> Self {
1997 let (type_, kind) = expression.into_parts();
1998 Self {
1999 type_,
2000 body: external_function_return_body(kind),
2001 }
2002 }
2003
2004 pub(crate) fn type_(&self) -> &ExternalFunctionType {
2005 &self.type_
2006 }
2007
2008 pub(crate) fn body(
2009 &self,
2010 ) -> &ReturnBody<
2011 super::ExternalFunctionExprKind,
2012 crate::plan::FunctionCallTarget<FunctionInstantiation>,
2013 > {
2014 &self.body
2015 }
2016}
2017
2018fn external_function_return_body(
2019 kind: super::ExternalFunctionExprKind,
2020) -> ReturnBody<
2021 super::ExternalFunctionExprKind,
2022 crate::plan::FunctionCallTarget<FunctionInstantiation>,
2023> {
2024 use super::ExternalFunctionExprKind as K;
2025
2026 match kind {
2027 K::Call {
2028 function,
2029 args,
2030 site,
2031 } => ReturnBody::tail_call(crate::plan::FunctionCallTarget::new(function, site), args),
2032 K::BoolCase {
2033 subject,
2034 true_,
2035 false_,
2036 } => ReturnBody::bool_case(
2037 *subject,
2038 external_function_return_body(*true_),
2039 external_function_return_body(*false_),
2040 ),
2041 K::IntCase {
2042 subject,
2043 clauses,
2044 fallback,
2045 } => ReturnBody::int_case(
2046 *subject,
2047 clauses
2048 .into_iter()
2049 .map(|(pattern, branch)| (pattern, external_function_return_body(branch)))
2050 .collect(),
2051 external_function_return_body(*fallback),
2052 ),
2053 K::FloatCase {
2054 subject,
2055 clauses,
2056 fallback,
2057 } => ReturnBody::float_case(
2058 *subject,
2059 clauses
2060 .into_iter()
2061 .map(|(pattern, branch)| (pattern, external_function_return_body(branch)))
2062 .collect(),
2063 external_function_return_body(*fallback),
2064 ),
2065 K::StringCase {
2066 subject,
2067 clauses,
2068 fallback,
2069 } => ReturnBody::string_case(
2070 *subject,
2071 clauses
2072 .into_iter()
2073 .map(|(pattern, branch)| (pattern, external_function_return_body(branch)))
2074 .collect(),
2075 external_function_return_body(*fallback),
2076 ),
2077 K::Block { steps, return_ } => {
2078 ReturnBody::block(steps, external_function_return_body(*return_))
2079 }
2080 kind => ReturnBody::expr(kind),
2081 }
2082}
2083
2084impl FunctionFunctionReturn {
2085 pub(crate) fn expr(expression: super::FunctionFunctionExpr) -> Self {
2086 let (type_, kind) = expression.into_parts();
2087 Self {
2088 type_,
2089 body: function_function_return_body(kind),
2090 }
2091 }
2092
2093 #[cfg(test)]
2094 pub(crate) fn int_case(subject: IntExpr, clauses: Vec<(BigInt, Self)>, fallback: Self) -> Self {
2095 let clauses = clauses
2096 .into_iter()
2097 .map(|(pattern, branch)| (pattern, branch.body))
2098 .collect();
2099 Self {
2100 type_: fallback.type_,
2101 body: ReturnBody::int_case(subject, clauses, fallback.body),
2102 }
2103 }
2104
2105 #[cfg(test)]
2106 pub(crate) fn string_case(
2107 subject: StringExpr,
2108 clauses: Vec<(EcoString, Self)>,
2109 fallback: Self,
2110 ) -> Self {
2111 let clauses = clauses
2112 .into_iter()
2113 .map(|(pattern, branch)| (pattern, branch.body))
2114 .collect();
2115 Self {
2116 type_: fallback.type_,
2117 body: ReturnBody::string_case(subject, clauses, fallback.body),
2118 }
2119 }
2120
2121 #[cfg(test)]
2122 pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
2123 Self {
2124 type_: return_.type_,
2125 body: ReturnBody::block(steps, return_.body),
2126 }
2127 }
2128
2129 pub(crate) fn type_(&self) -> &FunctionFunctionType {
2130 &self.type_
2131 }
2132
2133 pub(crate) fn body(
2134 &self,
2135 ) -> &ReturnBody<
2136 super::FunctionFunctionExprKind,
2137 crate::plan::FunctionCallTarget<FunctionInstantiation>,
2138 > {
2139 &self.body
2140 }
2141}
2142
2143fn function_function_return_body(
2144 kind: super::FunctionFunctionExprKind,
2145) -> ReturnBody<
2146 super::FunctionFunctionExprKind,
2147 crate::plan::FunctionCallTarget<FunctionInstantiation>,
2148> {
2149 use super::FunctionFunctionExprKind as K;
2150
2151 match kind {
2152 K::Call {
2153 function,
2154 args,
2155 site,
2156 } => ReturnBody::tail_call(crate::plan::FunctionCallTarget::new(function, site), args),
2157 K::BoolCase {
2158 subject,
2159 true_,
2160 false_,
2161 } => ReturnBody::bool_case(
2162 *subject,
2163 function_function_return_body(*true_),
2164 function_function_return_body(*false_),
2165 ),
2166 K::IntCase {
2167 subject,
2168 clauses,
2169 fallback,
2170 } => ReturnBody::int_case(
2171 *subject,
2172 clauses
2173 .into_iter()
2174 .map(|(pattern, branch)| (pattern, function_function_return_body(branch)))
2175 .collect(),
2176 function_function_return_body(*fallback),
2177 ),
2178 K::FloatCase {
2179 subject,
2180 clauses,
2181 fallback,
2182 } => ReturnBody::float_case(
2183 *subject,
2184 clauses
2185 .into_iter()
2186 .map(|(pattern, branch)| (pattern, function_function_return_body(branch)))
2187 .collect(),
2188 function_function_return_body(*fallback),
2189 ),
2190 K::StringCase {
2191 subject,
2192 clauses,
2193 fallback,
2194 } => ReturnBody::string_case(
2195 *subject,
2196 clauses
2197 .into_iter()
2198 .map(|(pattern, branch)| (pattern, function_function_return_body(branch)))
2199 .collect(),
2200 function_function_return_body(*fallback),
2201 ),
2202 K::Block { steps, return_ } => {
2203 ReturnBody::block(steps, function_function_return_body(*return_))
2204 }
2205 kind => ReturnBody::expr(kind),
2206 }
2207}
2208
2209impl<Expression, Function> ReturnBody<Expression, Function> {
2210 pub(crate) fn expr(expression: Expression) -> Self {
2211 Self {
2212 kind: ReturnBodyKind::Expr(expression),
2213 }
2214 }
2215
2216 pub(crate) fn tail_call(function: impl Into<Function>, args: Vec<CallArg>) -> Self {
2217 Self {
2218 kind: ReturnBodyKind::TailCall {
2219 function: function.into(),
2220 args,
2221 },
2222 }
2223 }
2224
2225 pub(crate) fn bool_case(subject: BoolExpr, true_: Self, false_: Self) -> Self {
2226 Self {
2227 kind: ReturnBodyKind::BoolCase {
2228 subject,
2229 true_: Box::new(true_),
2230 false_: Box::new(false_),
2231 },
2232 }
2233 }
2234
2235 pub(crate) fn int_case(subject: IntExpr, clauses: Vec<(BigInt, Self)>, fallback: Self) -> Self {
2236 Self {
2237 kind: ReturnBodyKind::IntCase {
2238 subject,
2239 clauses,
2240 fallback: Box::new(fallback),
2241 },
2242 }
2243 }
2244
2245 pub(crate) fn float_case(
2246 subject: FloatExpr,
2247 clauses: Vec<(f64, Self)>,
2248 fallback: Self,
2249 ) -> Self {
2250 Self {
2251 kind: ReturnBodyKind::FloatCase {
2252 subject,
2253 clauses,
2254 fallback: Box::new(fallback),
2255 },
2256 }
2257 }
2258
2259 pub(crate) fn string_case(
2260 subject: StringExpr,
2261 clauses: Vec<(EcoString, Self)>,
2262 fallback: Self,
2263 ) -> Self {
2264 Self {
2265 kind: ReturnBodyKind::StringCase {
2266 subject,
2267 clauses,
2268 fallback: Box::new(fallback),
2269 },
2270 }
2271 }
2272
2273 pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
2274 Self {
2275 kind: ReturnBodyKind::Block {
2276 steps,
2277 return_: Box::new(return_),
2278 },
2279 }
2280 }
2281
2282 pub(crate) fn kind(&self) -> &ReturnBodyKind<Expression, Function> {
2283 &self.kind
2284 }
2285}
2286
2287impl Param {
2288 #[cfg(test)]
2289 pub(crate) fn named(local: ParamLocal, name: EcoString) -> Self {
2290 let shape = local.value_shape();
2291 Self::named_shape(local, name, shape)
2292 }
2293
2294 pub(crate) fn named_shape(
2295 local: ParamLocal,
2296 name: EcoString,
2297 shape: crate::plan::ValueShape,
2298 ) -> Self {
2299 Self {
2300 slot: ParamSlot::new(local, shape),
2301 binding: ParamBinding::Named(name),
2302 }
2303 }
2304
2305 #[cfg(test)]
2306 pub(crate) fn discard(local: ParamLocal) -> Self {
2307 let shape = local.value_shape();
2308 Self::discard_shape(local, shape)
2309 }
2310
2311 pub(crate) fn discard_shape(local: ParamLocal, shape: crate::plan::ValueShape) -> Self {
2312 Self {
2313 slot: ParamSlot::new(local, shape),
2314 binding: ParamBinding::Discard,
2315 }
2316 }
2317
2318 pub fn name(&self) -> Option<&EcoString> {
2319 match &self.binding {
2320 ParamBinding::Named(name) => Some(name),
2321 ParamBinding::Discard => None,
2322 }
2323 }
2324
2325 pub fn binding(&self) -> &ParamBinding {
2326 &self.binding
2327 }
2328
2329 pub(crate) fn local(&self) -> &ParamLocal {
2330 self.slot.local()
2331 }
2332
2333 pub(crate) fn shape(&self) -> &crate::plan::ValueShape {
2334 self.slot.shape()
2335 }
2336}
2337
2338impl FunctionEntry {
2339 pub(crate) fn new(params: Vec<Param>, captures: Vec<ParamSlot>) -> Self {
2340 Self {
2341 params: params.into_boxed_slice(),
2342 captures: captures.into_boxed_slice(),
2343 }
2344 }
2345
2346 pub(crate) fn params(&self) -> &[Param] {
2347 &self.params
2348 }
2349
2350 pub(crate) fn captures(&self) -> &[ParamSlot] {
2351 &self.captures
2352 }
2353}
2354
2355impl CapturePosition {
2356 pub(crate) fn new(index: usize) -> Self {
2357 Self(index)
2358 }
2359
2360 pub(crate) fn index(self) -> usize {
2361 self.0
2362 }
2363}
2364
2365impl ParamSlot {
2366 pub(crate) fn new(local: ParamLocal, shape: crate::plan::ValueShape) -> Self {
2367 Self { local, shape }
2368 }
2369
2370 pub(crate) fn local(&self) -> &ParamLocal {
2371 &self.local
2372 }
2373
2374 pub(crate) fn shape(&self) -> &crate::plan::ValueShape {
2375 &self.shape
2376 }
2377
2378 #[cfg(test)]
2379 pub(crate) fn from_local(local: ParamLocal) -> Self {
2380 let shape = local.value_shape();
2381 Self::new(local, shape)
2382 }
2383}
2384
2385impl ParamLocal {
2386 pub(crate) fn generic(local: GenericLocal) -> Self {
2387 Self::Generic(local)
2388 }
2389
2390 pub(crate) fn int(local: IntLocalId) -> Self {
2391 Self::Int(local)
2392 }
2393
2394 pub(crate) fn float(local: FloatLocalId) -> Self {
2395 Self::Float(local)
2396 }
2397
2398 pub(crate) fn string(local: StringLocalId) -> Self {
2399 Self::String(local)
2400 }
2401
2402 pub(crate) fn bit_array(local: BitArrayLocalId) -> Self {
2403 Self::BitArray(local)
2404 }
2405
2406 pub(crate) fn utf_codepoint(local: UtfCodepointLocalId) -> Self {
2407 Self::UtfCodepoint(local)
2408 }
2409
2410 #[cfg(test)]
2411 pub(crate) fn custom(local: CustomLocalId, type_: CustomType) -> Self {
2412 Self::Custom(CustomLocal::new(local, type_))
2413 }
2414
2415 pub(crate) fn custom_shape(local: CustomLocalId, shape: crate::plan::CustomValueShape) -> Self {
2416 Self::Custom(CustomLocal::from_shape(local, shape))
2417 }
2418
2419 pub(crate) fn external_shape(
2420 local: ExternalLocalId,
2421 shape: crate::plan::ExternalValueShape,
2422 ) -> Self {
2423 Self::External(ExternalLocal::from_shape(local, shape))
2424 }
2425
2426 pub(crate) fn bool(local: BoolLocalId) -> Self {
2427 Self::Bool(local)
2428 }
2429
2430 pub(crate) fn nil(local: NilLocalId) -> Self {
2431 Self::Nil(local)
2432 }
2433
2434 pub(crate) fn tuple(local: TupleLocalId, type_: Vec<ValueType>) -> Self {
2435 Self::Tuple { local, type_ }
2436 }
2437
2438 pub(crate) fn list(local: ListLocal) -> Self {
2439 Self::List(local)
2440 }
2441
2442 pub(crate) fn int_function(local: IntFunctionLocalId, type_: FunctionType) -> Self {
2443 Self::IntFunction { local, type_ }
2444 }
2445
2446 pub(crate) fn float_function(local: FloatFunctionLocalId, type_: FunctionType) -> Self {
2447 Self::FloatFunction { local, type_ }
2448 }
2449
2450 pub(crate) fn string_function(local: StringFunctionLocalId, type_: FunctionType) -> Self {
2451 Self::StringFunction { local, type_ }
2452 }
2453
2454 pub(crate) fn bit_array_function(local: BitArrayFunctionLocalId, type_: FunctionType) -> Self {
2455 Self::BitArrayFunction { local, type_ }
2456 }
2457
2458 pub(crate) fn utf_codepoint_function(
2459 local: UtfCodepointFunctionLocalId,
2460 type_: FunctionType,
2461 ) -> Self {
2462 Self::UtfCodepointFunction { local, type_ }
2463 }
2464
2465 pub(crate) fn custom_function(local: CustomFunctionLocal) -> Self {
2466 Self::CustomFunction(local)
2467 }
2468
2469 pub(crate) fn external_function(local: ExternalFunctionLocal) -> Self {
2470 Self::ExternalFunction(local)
2471 }
2472
2473 pub(crate) fn bool_function(local: BoolFunctionLocalId, type_: FunctionType) -> Self {
2474 Self::BoolFunction { local, type_ }
2475 }
2476
2477 pub(crate) fn nil_function(local: NilFunctionLocalId, type_: FunctionType) -> Self {
2478 Self::NilFunction { local, type_ }
2479 }
2480
2481 pub(crate) fn tuple_function(local: TupleFunctionLocalId, type_: FunctionType) -> Self {
2482 Self::TupleFunction { local, type_ }
2483 }
2484
2485 pub(crate) fn list_function(local: ListFunctionLocal) -> Self {
2486 Self::ListFunction(local)
2487 }
2488
2489 pub(crate) fn function_function(local: FunctionFunctionLocal) -> Self {
2490 Self::FunctionFunction(local)
2491 }
2492
2493 pub(crate) fn generic_function(local: GenericFunctionLocal) -> Self {
2494 Self::GenericFunction(local)
2495 }
2496
2497 pub(crate) fn value_type(&self) -> ValueType {
2498 match self {
2499 Self::Generic(local) => ValueType::Parameter(local.parameter()),
2500 Self::Int(_) => ValueType::Int,
2501 Self::Float(_) => ValueType::Float,
2502 Self::String(_) => ValueType::String,
2503 Self::BitArray(_) => ValueType::BitArray,
2504 Self::UtfCodepoint(_) => ValueType::UtfCodepoint,
2505 Self::Custom(local) => ValueType::Custom(local.type_().clone()),
2506 Self::External(local) => ValueType::External(local.type_().clone()),
2507 Self::Bool(_) => ValueType::Bool,
2508 Self::Nil(_) => ValueType::Nil,
2509 Self::Tuple { type_, .. } => ValueType::Tuple(type_.clone()),
2510 Self::List(local) => local.value_type(),
2511 Self::IntFunction { type_, .. }
2512 | Self::FloatFunction { type_, .. }
2513 | Self::StringFunction { type_, .. }
2514 | Self::BitArrayFunction { type_, .. }
2515 | Self::UtfCodepointFunction { type_, .. }
2516 | Self::BoolFunction { type_, .. }
2517 | Self::NilFunction { type_, .. }
2518 | Self::TupleFunction { type_, .. } => ValueType::Function(Box::new(type_.clone())),
2519 Self::CustomFunction(local) => {
2520 ValueType::Function(Box::new(local.type_().to_function_type()))
2521 }
2522 Self::ExternalFunction(local) => {
2523 ValueType::Function(Box::new(local.type_().to_function_type()))
2524 }
2525 Self::ListFunction(local) => local.value_type(),
2526 Self::FunctionFunction(local) => {
2527 ValueType::Function(Box::new(local.type_().to_function_type()))
2528 }
2529 Self::GenericFunction(local) => {
2530 ValueType::Function(Box::new(local.type_().shape().type_()))
2531 }
2532 }
2533 }
2534
2535 #[cfg(test)]
2536 pub(crate) fn value_shape(&self) -> crate::plan::ValueShape {
2537 match self {
2538 Self::Generic(local) => crate::plan::ValueShape::Parameter(local.parameter()),
2539 Self::Custom(local) => crate::plan::ValueShape::Custom(local.shape().clone()),
2540 Self::External(local) => crate::plan::ValueShape::External(local.shape().clone()),
2541 Self::CustomFunction(local) => {
2542 crate::plan::ValueShape::Function(Box::new(crate::plan::FunctionShape::new(
2543 local.type_().argument_shapes().to_vec(),
2544 crate::plan::ValueShape::Custom(local.type_().return_().clone()),
2545 )))
2546 }
2547 Self::ExternalFunction(local) => {
2548 crate::plan::ValueShape::Function(Box::new(crate::plan::FunctionShape::new(
2549 local.type_().argument_shapes().to_vec(),
2550 crate::plan::ValueShape::External(local.type_().return_().clone()),
2551 )))
2552 }
2553 Self::GenericFunction(local) => {
2554 crate::plan::ValueShape::Function(Box::new(local.type_().shape()))
2555 }
2556 _ => crate::plan::ValueShape::from_value_type(self.value_type()),
2557 }
2558 }
2559}
2560
2561#[cfg(test)]
2562mod tests {
2563 use super::{
2564 BitArrayFunctionReturn, BitArrayListReturn, BoolListReturn, CapturePosition,
2565 CustomFunctionReturn, CustomListReturn, CustomReturn, ExternalFunctionReturn,
2566 ExternalListReturn, ExternalReturn, FloatListReturn, FunctionFunctionReturn,
2567 FunctionListReturn, FunctionTemplate, GenericFunctionReturn, GenericListReturn,
2568 GenericReturn, IntListReturn, ListListReturn, ListReturn, NilListReturn, Param,
2569 ParamBinding, ParamLocal, ParamSlot, ParameterListListReturn, ReturnBody, ReturnBodyKind,
2570 ReturnExpr, StringListReturn, TupleListReturn, UtfCodepointFunctionReturn,
2571 };
2572 use crate::plan::{
2573 BitArrayExpr, BoolExpr, BoolFunctionLocalId, BoolLocalId, CustomConstructorRefinement,
2574 CustomExpr, CustomFunctionExpr, CustomFunctionLocal, CustomFunctionLocalId,
2575 CustomFunctionType, CustomType, CustomTypeName, CustomValueShape, ExternalExpr,
2576 ExternalFunctionExpr, ExternalFunctionLocal, ExternalFunctionLocalId, ExternalFunctionType,
2577 ExternalLocalId, ExternalType, ExternalTypeName, ExternalValueShape, FloatExpr,
2578 FloatFunctionLocalId, FloatLocalId, FunctionFunctionExpr, FunctionFunctionLocal,
2579 FunctionFunctionLocalId, FunctionFunctionType, FunctionShape, FunctionTemplateId,
2580 FunctionType, GenericFunctionLocal, GenericFunctionLocalId, GenericFunctionType,
2581 GenericLocal, GenericLocalId, IntExpr, IntFunctionLocalId, IntListLocalId, IntLocalId,
2582 ListExpr, ListLocal, NilExpr, NilFunctionLocalId, PanicExpr, PanicSite, StringExpr,
2583 StringFunctionLocalId, TupleExpr, TupleFunctionLocalId, TypeParameterId, UtfCodepointExpr,
2584 UtfCodepointListReturn, UtfCodepointLocalId, ValueShape, ValueStorageShape, ValueType,
2585 };
2586 use num_bigint::BigInt;
2587
2588 fn custom_type() -> CustomType {
2589 CustomType::new(
2590 CustomTypeName::new("geam".into(), "main".into(), "Boxed".into()),
2591 Vec::new(),
2592 )
2593 }
2594
2595 fn external_type(name: &str) -> ExternalType {
2596 ExternalType::new(
2597 ExternalTypeName::new("geam".into(), "main".into(), name.into()),
2598 Vec::new(),
2599 )
2600 }
2601
2602 #[test]
2603 fn custom_function_parameter_helpers_preserve_recursive_value_shape() {
2604 let type_ = custom_type();
2605 let return_shape = CustomValueShape::new(
2606 type_.type_name().clone(),
2607 Vec::new(),
2608 CustomConstructorRefinement::Exact(0),
2609 );
2610 let type_ = CustomFunctionType::from_shapes(
2611 vec![ValueShape::Custom(return_shape.clone())],
2612 return_shape.clone(),
2613 );
2614 let local =
2615 ParamLocal::custom_function(CustomFunctionLocal::new(CustomFunctionLocalId(0), type_));
2616
2617 assert_eq!(
2618 local.value_shape(),
2619 ValueShape::Function(Box::new(crate::plan::FunctionShape::new(
2620 vec![ValueShape::Custom(return_shape.clone())],
2621 ValueShape::Custom(return_shape),
2622 ))),
2623 );
2624 }
2625
2626 #[test]
2627 fn callable_returns_own_exact_type_around_itemless_bodies() {
2628 let custom_function_type = CustomFunctionType::new(vec![ValueType::Int], custom_type());
2629 let custom_function_shape = crate::plan::FunctionShape::new(
2630 custom_function_type.argument_shapes().to_vec(),
2631 ValueShape::Custom(custom_function_type.return_().clone()),
2632 );
2633 let custom_instantiation = crate::plan::monomorphic_function_instantiation(
2634 7,
2635 crate::plan::FunctionShape::new(
2636 Vec::new(),
2637 ValueShape::Function(Box::new(custom_function_shape)),
2638 ),
2639 );
2640 let custom_return = CustomFunctionReturn::expr(CustomFunctionExpr::block(
2641 Vec::new(),
2642 CustomFunctionExpr::call(
2643 custom_instantiation.clone(),
2644 Vec::new(),
2645 custom_function_type.clone(),
2646 ),
2647 ));
2648
2649 assert_eq!(
2650 custom_return,
2651 CustomFunctionReturn {
2652 type_: custom_function_type,
2653 body: ReturnBody {
2654 kind: ReturnBodyKind::Block {
2655 steps: Vec::new(),
2656 return_: Box::new(ReturnBody {
2657 kind: ReturnBodyKind::TailCall {
2658 function: custom_instantiation.into(),
2659 args: Vec::new(),
2660 },
2661 }),
2662 },
2663 },
2664 },
2665 );
2666
2667 let returned = FunctionType::new(vec![ValueType::String], ValueType::Int);
2668 let function_function_type = FunctionFunctionType::new(vec![ValueType::Bool], returned);
2669 let function_instantiation = crate::plan::monomorphic_function_instantiation(
2670 9,
2671 crate::plan::FunctionShape::new(
2672 Vec::new(),
2673 ValueShape::Function(Box::new(crate::plan::FunctionShape::from_function_type(
2674 function_function_type.to_function_type(),
2675 ))),
2676 ),
2677 );
2678 let function_return = FunctionFunctionReturn::expr(FunctionFunctionExpr::call(
2679 function_instantiation.clone(),
2680 Vec::new(),
2681 function_function_type.clone(),
2682 ));
2683
2684 assert_eq!(
2685 function_return,
2686 FunctionFunctionReturn {
2687 type_: function_function_type,
2688 body: ReturnBody {
2689 kind: ReturnBodyKind::TailCall {
2690 function: function_instantiation.into(),
2691 args: Vec::new(),
2692 },
2693 },
2694 },
2695 );
2696 }
2697
2698 #[test]
2699 fn function_function_returns_convert_float_case_tail_calls() {
2700 let returned = FunctionType::new(Vec::new(), ValueType::Int);
2701 let type_ = FunctionFunctionType::new(Vec::new(), returned);
2702 let function = crate::plan::monomorphic_function_instantiation(
2703 9,
2704 crate::plan::FunctionShape::new(
2705 Vec::new(),
2706 ValueShape::Function(Box::new(crate::plan::FunctionShape::from_function_type(
2707 type_.to_function_type(),
2708 ))),
2709 ),
2710 );
2711 let branch = FunctionFunctionExpr::call(function.clone(), Vec::new(), type_.clone());
2712 let fallback = FunctionFunctionExpr::call(function.clone(), Vec::new(), type_.clone());
2713
2714 assert_eq!(
2715 FunctionFunctionReturn::expr(FunctionFunctionExpr::float_case(
2716 FloatExpr::value(1.5),
2717 vec![(1.5, branch)],
2718 fallback,
2719 )),
2720 FunctionFunctionReturn {
2721 type_,
2722 body: ReturnBody::float_case(
2723 FloatExpr::value(1.5),
2724 vec![(1.5, ReturnBody::tail_call(function.clone(), Vec::new()))],
2725 ReturnBody::tail_call(function, Vec::new()),
2726 ),
2727 },
2728 );
2729 }
2730
2731 #[test]
2732 fn custom_returns_own_one_type_around_itemless_tail_calls() {
2733 let type_ = custom_type();
2734 let custom_shape = CustomValueShape::any(type_.clone());
2735 let function = crate::plan::monomorphic_function_instantiation(
2736 7,
2737 crate::plan::FunctionShape::new(Vec::new(), ValueShape::Custom(custom_shape.clone())),
2738 );
2739 let body = CustomReturn::expr(CustomExpr::block(
2740 Vec::new(),
2741 CustomExpr::bool_case(
2742 BoolExpr::value(true),
2743 crate::plan::CustomBoolCaseBranches::from_resolved_shape(
2744 custom_shape.clone(),
2745 CustomExpr::call(function.clone(), Vec::new(), custom_shape.clone()),
2746 CustomExpr::call(function.clone(), Vec::new(), custom_shape.clone()),
2747 ),
2748 ),
2749 ));
2750
2751 assert_eq!(
2752 body,
2753 CustomReturn {
2754 signature_shape: custom_shape.clone(),
2755 body_shape: custom_shape,
2756 body: ReturnBody {
2757 kind: ReturnBodyKind::Block {
2758 steps: Vec::new(),
2759 return_: Box::new(ReturnBody {
2760 kind: ReturnBodyKind::BoolCase {
2761 subject: BoolExpr::value(true),
2762 true_: Box::new(ReturnBody {
2763 kind: ReturnBodyKind::TailCall {
2764 function: function.clone().into(),
2765 args: Vec::new(),
2766 },
2767 }),
2768 false_: Box::new(ReturnBody {
2769 kind: ReturnBodyKind::TailCall {
2770 function: function.into(),
2771 args: Vec::new(),
2772 },
2773 }),
2774 },
2775 }),
2776 },
2777 },
2778 },
2779 );
2780 }
2781
2782 #[test]
2783 fn function_plan_accessors() {
2784 let param = Param::named(ParamLocal::int(IntLocalId(0)), "x".into());
2785 let return_ = ReturnExpr::int_body(ReturnBody::expr(IntExpr::value(BigInt::from(1))));
2786 let function = FunctionTemplate::new(
2787 FunctionTemplateId::new(0),
2788 "main".into(),
2789 vec![param],
2790 Vec::new(),
2791 return_,
2792 );
2793
2794 assert_eq!(function.id(), FunctionTemplateId::new(0));
2795 assert_eq!(function.name(), "main");
2796 assert_eq!(function.params().len(), 1);
2797 assert_eq!(function.params()[0].name(), Some(&"x".into()));
2798 assert_eq!(function.steps(), &[]);
2799 assert_eq!(
2800 function.return_(),
2801 &ReturnExpr::int_body(ReturnBody::expr(IntExpr::value(BigInt::from(1))))
2802 );
2803 }
2804
2805 #[test]
2806 fn function_entry_owns_ordered_parameter_and_capture_destinations() {
2807 let function = FunctionTemplate::with_captures(
2808 FunctionTemplateId::new(0),
2809 "anonymous".into(),
2810 vec![
2811 Param::named(ParamLocal::int(IntLocalId(0)), "first".into()),
2812 Param::discard(ParamLocal::string(crate::plan::StringLocalId(0))),
2813 ],
2814 vec![
2815 ParamSlot::from_local(ParamLocal::bool(BoolLocalId(0))),
2816 ParamSlot::from_local(ParamLocal::utf_codepoint(UtfCodepointLocalId(0))),
2817 ],
2818 Vec::new(),
2819 ReturnExpr::int_body(ReturnBody::expr(IntExpr::value(BigInt::from(1)))),
2820 );
2821 let entry = function.entry();
2822
2823 assert_eq!(
2824 entry.params(),
2825 &[
2826 Param::named(ParamLocal::int(IntLocalId(0)), "first".into()),
2827 Param::discard(ParamLocal::string(crate::plan::StringLocalId(0))),
2828 ],
2829 );
2830 assert_eq!(
2831 entry.captures(),
2832 &[
2833 ParamSlot::from_local(ParamLocal::bool(BoolLocalId(0))),
2834 ParamSlot::from_local(ParamLocal::utf_codepoint(UtfCodepointLocalId(0))),
2835 ],
2836 );
2837 assert_eq!(CapturePosition::new(1).index(), 1);
2838 }
2839
2840 #[test]
2841 fn return_expr_value_type_preserves_parametric_and_compound_families() {
2842 let parameter = TypeParameterId(0);
2843 let custom = custom_type();
2844 let external = external_type("Token");
2845 let external_shape = ExternalValueShape::any(external.clone());
2846 let tuple = vec![ValueType::Int, ValueType::String];
2847 let nested_type = Box::new(ValueType::List(Box::new(ValueType::Bool)));
2848 let nested_shape = ValueStorageShape::List(Box::new(ValueShape::Bool));
2849 let function = FunctionType::new(vec![ValueType::Int], ValueType::String);
2850 let function_shape = crate::plan::FunctionShape::new(
2851 vec![ValueShape::Parameter(parameter)],
2852 ValueShape::Parameter(parameter),
2853 );
2854 let tail_call = crate::plan::monomorphic_function_instantiation(
2855 0,
2856 crate::plan::FunctionShape::new(Vec::new(), ValueShape::Nil),
2857 );
2858
2859 let returns = [
2860 ReturnExpr::generic_body(
2861 parameter,
2862 GenericReturn::tail_call(tail_call.clone(), Vec::new()),
2863 ),
2864 ReturnExpr::generic_list_body(
2865 parameter,
2866 GenericListReturn::tail_call(tail_call.clone(), Vec::new()),
2867 ),
2868 ReturnExpr::parameter_list_list_body(
2869 parameter,
2870 ParameterListListReturn::tail_call(tail_call.clone(), Vec::new()),
2871 ),
2872 ReturnExpr::string_list_body(StringListReturn::tail_call(
2873 tail_call.clone(),
2874 Vec::new(),
2875 )),
2876 ReturnExpr::bit_array_list_body(BitArrayListReturn::tail_call(
2877 tail_call.clone(),
2878 Vec::new(),
2879 )),
2880 ReturnExpr::utf_codepoint_list_body(UtfCodepointListReturn::tail_call(
2881 tail_call.clone(),
2882 Vec::new(),
2883 )),
2884 ReturnExpr::custom_list_body(
2885 custom.clone(),
2886 CustomListReturn::tail_call(tail_call.clone(), Vec::new()),
2887 ),
2888 ReturnExpr::external_body(ExternalReturn::with_signature_shape(
2889 external_shape.clone(),
2890 ExternalExpr::panic_shape(
2891 PanicExpr::panic_at(None, PanicSite::unknown()),
2892 external_shape.clone(),
2893 ),
2894 )),
2895 ReturnExpr::external_list_body(
2896 external.clone(),
2897 ExternalListReturn::tail_call(tail_call.clone(), Vec::new()),
2898 ),
2899 ReturnExpr::float_list_body(FloatListReturn::tail_call(tail_call.clone(), Vec::new())),
2900 ReturnExpr::bool_list_body(BoolListReturn::tail_call(tail_call.clone(), Vec::new())),
2901 ReturnExpr::nil_list_body(NilListReturn::tail_call(tail_call.clone(), Vec::new())),
2902 ReturnExpr::tuple_list_body(
2903 tuple.clone(),
2904 TupleListReturn::tail_call(tail_call.clone(), Vec::new()),
2905 ),
2906 ReturnExpr::list_list_body(
2907 nested_shape,
2908 ListListReturn::tail_call(tail_call.clone(), Vec::new()),
2909 ),
2910 ReturnExpr::function_list_body(
2911 function.clone(),
2912 FunctionListReturn::tail_call(tail_call.clone(), Vec::new()),
2913 ),
2914 ReturnExpr::generic_function_shape_body(
2915 function_shape.clone(),
2916 GenericFunctionReturn::tail_call(tail_call.clone(), Vec::new()),
2917 ),
2918 ReturnExpr::external_function_shape_body(
2919 FunctionShape::new(
2920 vec![ValueShape::Int],
2921 ValueShape::External(external_shape.clone()),
2922 ),
2923 ExternalFunctionReturn::expr(ExternalFunctionExpr::panic(
2924 PanicExpr::panic_at(None, PanicSite::unknown()),
2925 ExternalFunctionType::from_shapes(
2926 vec![ValueShape::Int],
2927 external_shape.clone(),
2928 ),
2929 )),
2930 ),
2931 ReturnExpr::bit_array_function_shape_body(
2932 function_shape.clone(),
2933 BitArrayFunctionReturn::tail_call(tail_call.clone(), Vec::new()),
2934 ),
2935 ReturnExpr::utf_codepoint_function_shape_body(
2936 function_shape.clone(),
2937 UtfCodepointFunctionReturn::tail_call(tail_call, Vec::new()),
2938 ),
2939 ];
2940
2941 assert_eq!(
2942 returns.map(|return_| return_.value_type()),
2943 [
2944 ValueType::Parameter(parameter),
2945 ValueType::List(Box::new(ValueType::Parameter(parameter))),
2946 ValueType::List(Box::new(ValueType::List(Box::new(ValueType::Parameter(
2947 parameter,
2948 ))))),
2949 ValueType::List(Box::new(ValueType::String)),
2950 ValueType::List(Box::new(ValueType::BitArray)),
2951 ValueType::List(Box::new(ValueType::UtfCodepoint)),
2952 ValueType::List(Box::new(ValueType::Custom(custom))),
2953 ValueType::External(external.clone()),
2954 ValueType::List(Box::new(ValueType::External(external.clone()))),
2955 ValueType::List(Box::new(ValueType::Float)),
2956 ValueType::List(Box::new(ValueType::Bool)),
2957 ValueType::List(Box::new(ValueType::Nil)),
2958 ValueType::List(Box::new(ValueType::Tuple(tuple))),
2959 ValueType::List(Box::new(ValueType::List(nested_type))),
2960 ValueType::List(Box::new(ValueType::Function(Box::new(function)))),
2961 ValueType::Function(Box::new(function_shape.type_())),
2962 ValueType::Function(Box::new(FunctionType::new(
2963 vec![ValueType::Int],
2964 ValueType::External(external),
2965 ))),
2966 ValueType::Function(Box::new(function_shape.type_())),
2967 ValueType::Function(Box::new(function_shape.type_())),
2968 ],
2969 );
2970 }
2971
2972 #[test]
2973 fn param_binding_accessors() {
2974 let named = Param::named(ParamLocal::int(IntLocalId(0)), "x".into());
2975 let discard = Param::discard(ParamLocal::int(IntLocalId(1)));
2976
2977 assert_eq!(named.name(), Some(&"x".into()));
2978 assert_eq!(named.binding(), &ParamBinding::Named("x".into()));
2979 assert_eq!(discard.name(), None);
2980 assert_eq!(discard.binding(), &ParamBinding::Discard);
2981 }
2982
2983 #[test]
2984 fn param_local_value_type() {
2985 let parameter = TypeParameterId(0);
2986 let generic = ParamLocal::generic(GenericLocal::new(GenericLocalId(0), parameter));
2987 assert_eq!(generic.value_type(), ValueType::Parameter(parameter));
2988 assert_eq!(generic.value_shape(), ValueShape::Parameter(parameter));
2989
2990 let generic_function_type = GenericFunctionType::new(vec![ValueShape::Int], parameter);
2991 let generic_function = ParamLocal::generic_function(GenericFunctionLocal::new(
2992 GenericFunctionLocalId(0),
2993 generic_function_type.clone(),
2994 ));
2995 assert_eq!(
2996 generic_function.value_type(),
2997 ValueType::Function(Box::new(FunctionType::new(
2998 vec![ValueType::Int],
2999 ValueType::Parameter(parameter),
3000 ))),
3001 );
3002 assert_eq!(
3003 generic_function.value_shape(),
3004 ValueShape::Function(Box::new(generic_function_type.shape())),
3005 );
3006
3007 let external_shape = ExternalValueShape::any(external_type("Token"));
3008 let external = ParamLocal::external_shape(ExternalLocalId(0), external_shape.clone());
3009 assert_eq!(
3010 external.value_type(),
3011 ValueType::External(external_shape.type_().clone()),
3012 );
3013 assert_eq!(
3014 external.value_shape(),
3015 ValueShape::External(external_shape.clone()),
3016 );
3017
3018 let external_function_type =
3019 ExternalFunctionType::from_shapes(vec![ValueShape::Int], external_shape.clone());
3020 let external_function = ParamLocal::external_function(ExternalFunctionLocal::new(
3021 ExternalFunctionLocalId(0),
3022 external_function_type.clone(),
3023 ));
3024 assert_eq!(
3025 external_function.value_type(),
3026 ValueType::Function(Box::new(external_function_type.to_function_type())),
3027 );
3028 assert_eq!(
3029 external_function.value_shape(),
3030 ValueShape::Function(Box::new(FunctionShape::new(
3031 vec![ValueShape::Int],
3032 ValueShape::External(external_shape),
3033 ))),
3034 );
3035
3036 assert_eq!(ParamLocal::int(IntLocalId(0)).value_type(), ValueType::Int);
3037 assert_eq!(
3038 ParamLocal::string(crate::plan::StringLocalId(0)).value_type(),
3039 ValueType::String,
3040 );
3041 assert_eq!(
3042 ParamLocal::utf_codepoint(UtfCodepointLocalId(0)).value_type(),
3043 ValueType::UtfCodepoint,
3044 );
3045 assert_eq!(
3046 ParamLocal::float(FloatLocalId(0)).value_type(),
3047 ValueType::Float,
3048 );
3049 assert_eq!(
3050 ParamLocal::bool(BoolLocalId(0)).value_type(),
3051 ValueType::Bool,
3052 );
3053 assert_eq!(
3054 ParamLocal::nil(crate::plan::NilLocalId(0)).value_type(),
3055 ValueType::Nil,
3056 );
3057 assert_eq!(
3058 ParamLocal::list(ListLocal::int(IntListLocalId(0))).value_type(),
3059 ValueType::List(Box::new(ValueType::Int)),
3060 );
3061 assert_eq!(
3062 ParamLocal::int_function(
3063 IntFunctionLocalId(0),
3064 FunctionType::new(vec![ValueType::Int], ValueType::Int),
3065 )
3066 .value_type(),
3067 ValueType::Function(Box::new(FunctionType::new(
3068 vec![ValueType::Int],
3069 ValueType::Int,
3070 ))),
3071 );
3072 assert_eq!(
3073 ParamLocal::string_function(
3074 StringFunctionLocalId(0),
3075 FunctionType::new(vec![ValueType::String], ValueType::String),
3076 )
3077 .value_type(),
3078 ValueType::Function(Box::new(FunctionType::new(
3079 vec![ValueType::String],
3080 ValueType::String,
3081 ))),
3082 );
3083 assert_eq!(
3084 ParamLocal::utf_codepoint_function(
3085 crate::plan::UtfCodepointFunctionLocalId(0),
3086 FunctionType::new(vec![ValueType::UtfCodepoint], ValueType::UtfCodepoint,),
3087 )
3088 .value_type(),
3089 ValueType::Function(Box::new(FunctionType::new(
3090 vec![ValueType::UtfCodepoint],
3091 ValueType::UtfCodepoint,
3092 ))),
3093 );
3094 assert_eq!(
3095 ParamLocal::float_function(
3096 FloatFunctionLocalId(0),
3097 FunctionType::new(vec![ValueType::Float], ValueType::Float),
3098 )
3099 .value_type(),
3100 ValueType::Function(Box::new(FunctionType::new(
3101 vec![ValueType::Float],
3102 ValueType::Float,
3103 ))),
3104 );
3105 assert_eq!(
3106 ParamLocal::bool_function(
3107 BoolFunctionLocalId(0),
3108 FunctionType::new(vec![ValueType::Bool], ValueType::Bool),
3109 )
3110 .value_type(),
3111 ValueType::Function(Box::new(FunctionType::new(
3112 vec![ValueType::Bool],
3113 ValueType::Bool,
3114 ))),
3115 );
3116 assert_eq!(
3117 ParamLocal::nil_function(
3118 NilFunctionLocalId(0),
3119 FunctionType::new(vec![ValueType::Nil], ValueType::Nil),
3120 )
3121 .value_type(),
3122 ValueType::Function(Box::new(FunctionType::new(
3123 vec![ValueType::Nil],
3124 ValueType::Nil,
3125 ))),
3126 );
3127 assert_eq!(
3128 ParamLocal::tuple_function(
3129 TupleFunctionLocalId(0),
3130 FunctionType::new(
3131 vec![ValueType::Tuple(vec![ValueType::Int])],
3132 ValueType::Tuple(vec![ValueType::String]),
3133 ),
3134 )
3135 .value_type(),
3136 ValueType::Function(Box::new(FunctionType::new(
3137 vec![ValueType::Tuple(vec![ValueType::Int])],
3138 ValueType::Tuple(vec![ValueType::String]),
3139 ))),
3140 );
3141 assert_eq!(
3142 ParamLocal::list_function(crate::plan::ListFunctionLocal::from_item_type(
3143 0,
3144 FunctionType::new(
3145 vec![ValueType::List(Box::new(ValueType::Int))],
3146 ValueType::List(Box::new(ValueType::String)),
3147 ),
3148 ValueType::String,
3149 ))
3150 .value_type(),
3151 ValueType::Function(Box::new(FunctionType::new(
3152 vec![ValueType::List(Box::new(ValueType::Int))],
3153 ValueType::List(Box::new(ValueType::String)),
3154 ))),
3155 );
3156 assert_eq!(
3157 ParamLocal::function_function(FunctionFunctionLocal::new(
3158 FunctionFunctionLocalId(0),
3159 FunctionFunctionType::new(
3160 Vec::new(),
3161 FunctionType::new(Vec::new(), ValueType::Int),
3162 ),
3163 ),)
3164 .value_type(),
3165 ValueType::Function(Box::new(FunctionType::new(
3166 Vec::new(),
3167 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::Int))),
3168 ))),
3169 );
3170 }
3171
3172 #[test]
3173 fn list_return_expr_preserves_item_family() {
3174 let parameter = crate::plan::TypeParameterId(0);
3175 let generic = ListExpr::value(Vec::new(), ValueType::Parameter(parameter));
3176 assert_eq!(
3177 ListReturn::expr(generic.clone()),
3178 ListReturn::Generic {
3179 item_parameter: parameter,
3180 body: super::GenericListReturn::expr(generic.into_generic().expect("generic list"),),
3181 },
3182 );
3183
3184 let int = ListExpr::value(
3185 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3186 ValueType::Int,
3187 );
3188 assert_eq!(
3189 ListReturn::expr(int.clone()),
3190 ListReturn::Int(IntListReturn::expr(int.into_int().expect("int list"))),
3191 );
3192
3193 let float = ListExpr::value(
3194 vec![crate::plan::Expr::float(FloatExpr::value(1.5))],
3195 ValueType::Float,
3196 );
3197 assert_eq!(
3198 ListReturn::expr(float.clone()),
3199 ListReturn::Float(FloatListReturn::expr(
3200 float.into_float().expect("float list")
3201 )),
3202 );
3203
3204 let string = ListExpr::value(
3205 vec![crate::plan::Expr::string(StringExpr::value("one".into()))],
3206 ValueType::String,
3207 );
3208 assert_eq!(
3209 ListReturn::expr(string.clone()),
3210 ListReturn::String(StringListReturn::expr(
3211 string.into_string().expect("string list"),
3212 )),
3213 );
3214
3215 let bit_array = ListExpr::value(
3216 vec![crate::plan::Expr::bit_array(
3217 BitArrayExpr::value(Vec::new()),
3218 )],
3219 ValueType::BitArray,
3220 );
3221 assert_eq!(
3222 ListReturn::expr(bit_array.clone()),
3223 ListReturn::BitArray(BitArrayListReturn::expr(
3224 bit_array.into_bit_array().expect("bit array list"),
3225 )),
3226 );
3227
3228 let utf_codepoint = ListExpr::value(
3229 vec![crate::plan::Expr::utf_codepoint(
3230 UtfCodepointExpr::local_get(UtfCodepointLocalId(0), "codepoint".into()),
3231 )],
3232 ValueType::UtfCodepoint,
3233 );
3234 assert_eq!(
3235 ListReturn::expr(utf_codepoint.clone()),
3236 ListReturn::UtfCodepoint(UtfCodepointListReturn::expr(
3237 utf_codepoint
3238 .into_utf_codepoint()
3239 .expect("UTF codepoint list"),
3240 )),
3241 );
3242
3243 let custom_type = custom_type();
3244 let custom = ListExpr::value(Vec::new(), ValueType::Custom(custom_type.clone()));
3245 assert_eq!(
3246 ListReturn::expr(custom.clone()),
3247 ListReturn::Custom {
3248 item_type: custom_type,
3249 body: CustomListReturn::expr(custom.into_custom().expect("custom list")),
3250 },
3251 );
3252
3253 let external_type = external_type("Token");
3254 let external = ListExpr::value(Vec::new(), ValueType::External(external_type.clone()));
3255 assert_eq!(
3256 ListReturn::expr(external.clone()),
3257 ListReturn::External {
3258 item_type: external_type,
3259 body: ExternalListReturn::expr(external.into_external().expect("external list"),),
3260 },
3261 );
3262
3263 let bool_ = ListExpr::value(
3264 vec![crate::plan::Expr::bool(BoolExpr::value(true))],
3265 ValueType::Bool,
3266 );
3267 assert_eq!(
3268 ListReturn::expr(bool_.clone()),
3269 ListReturn::Bool(BoolListReturn::expr(bool_.into_bool().expect("bool list"))),
3270 );
3271
3272 let nil = ListExpr::value(
3273 vec![crate::plan::Expr::nil(NilExpr::value())],
3274 ValueType::Nil,
3275 );
3276 assert_eq!(
3277 ListReturn::expr(nil.clone()),
3278 ListReturn::Nil(NilListReturn::expr(nil.into_nil().expect("nil list"))),
3279 );
3280
3281 let tuple = ListExpr::value(
3282 vec![crate::plan::Expr::tuple(TupleExpr::value(
3283 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3284 vec![ValueType::Int],
3285 ))],
3286 ValueType::Tuple(vec![ValueType::Int]),
3287 );
3288 assert_eq!(
3289 ListReturn::expr(tuple.clone()),
3290 ListReturn::Tuple {
3291 item_type: vec![ValueType::Int],
3292 body: TupleListReturn::expr(tuple.into_tuple().expect("tuple list")),
3293 },
3294 );
3295
3296 let nested = ListExpr::value(
3297 vec![crate::plan::Expr::list(ListExpr::value(
3298 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3299 ValueType::Int,
3300 ))],
3301 ValueType::List(Box::new(ValueType::Int)),
3302 );
3303 assert_eq!(
3304 ListReturn::expr(nested.clone()),
3305 ListReturn::List {
3306 item_shape: ValueStorageShape::Int,
3307 body: ListListReturn::expr(nested.into_list().expect("nested list")),
3308 },
3309 );
3310
3311 let parameter = TypeParameterId(0);
3312 let parameter_nested = ListExpr::value(
3313 Vec::new(),
3314 ValueType::List(Box::new(ValueType::Parameter(parameter))),
3315 );
3316 assert_eq!(
3317 ListReturn::expr(parameter_nested.clone()),
3318 ListReturn::ParameterList {
3319 item_parameter: parameter,
3320 body: ParameterListListReturn::expr(
3321 parameter_nested
3322 .into_parameter_list()
3323 .expect("parameter-list list"),
3324 ),
3325 },
3326 );
3327
3328 let function_type = FunctionType::new(Vec::new(), ValueType::Int);
3329 let function_instantiation = crate::plan::monomorphic_function_instantiation(
3330 0,
3331 crate::plan::FunctionShape::from_function_type(function_type.clone()),
3332 );
3333 let function = ListExpr::value(
3334 vec![crate::plan::Expr::function(
3335 crate::plan::FunctionExpr::reference(crate::plan::FunctionReference::new(
3336 function_instantiation,
3337 )),
3338 )],
3339 ValueType::Function(Box::new(function_type.clone())),
3340 );
3341 assert_eq!(
3342 ListReturn::expr(function.clone()),
3343 ListReturn::Function {
3344 item_type: function_type,
3345 body: FunctionListReturn::expr(function.into_function().expect("function list")),
3346 },
3347 );
3348 }
3349
3350 #[test]
3351 fn list_return_tail_call_preserves_item_family() {
3352 fn tail_call_function(item_type: ValueType) -> crate::plan::FunctionInstantiation {
3353 crate::plan::monomorphic_function_instantiation(
3354 0,
3355 crate::plan::FunctionShape::new(
3356 Vec::new(),
3357 ValueShape::List(Box::new(ValueShape::from_value_type(item_type))),
3358 ),
3359 )
3360 }
3361
3362 let parameter = crate::plan::TypeParameterId(0);
3363 let function = tail_call_function(ValueType::Parameter(parameter));
3364 assert_eq!(
3365 ListReturn::tail_call(
3366 function.clone(),
3367 ValueType::Parameter(parameter),
3368 Vec::new(),
3369 ),
3370 ListReturn::Generic {
3371 item_parameter: parameter,
3372 body: super::GenericListReturn::tail_call(function, Vec::new()),
3373 },
3374 );
3375
3376 let function = tail_call_function(ValueType::Int);
3377 assert_eq!(
3378 ListReturn::tail_call(function.clone(), ValueType::Int, Vec::new()),
3379 ListReturn::Int(IntListReturn::tail_call(function, Vec::new())),
3380 );
3381
3382 let function = tail_call_function(ValueType::Float);
3383 assert_eq!(
3384 ListReturn::tail_call(function.clone(), ValueType::Float, Vec::new()),
3385 ListReturn::Float(FloatListReturn::tail_call(function, Vec::new())),
3386 );
3387
3388 let function = tail_call_function(ValueType::String);
3389 assert_eq!(
3390 ListReturn::tail_call(function.clone(), ValueType::String, Vec::new()),
3391 ListReturn::String(StringListReturn::tail_call(function, Vec::new())),
3392 );
3393
3394 let function = tail_call_function(ValueType::BitArray);
3395 assert_eq!(
3396 ListReturn::tail_call(function.clone(), ValueType::BitArray, Vec::new()),
3397 ListReturn::BitArray(BitArrayListReturn::tail_call(function, Vec::new())),
3398 );
3399
3400 let function = tail_call_function(ValueType::UtfCodepoint);
3401 assert_eq!(
3402 ListReturn::tail_call(function.clone(), ValueType::UtfCodepoint, Vec::new()),
3403 ListReturn::UtfCodepoint(UtfCodepointListReturn::tail_call(function, Vec::new())),
3404 );
3405
3406 let custom_type = custom_type();
3407 let function = tail_call_function(ValueType::Custom(custom_type.clone()));
3408 assert_eq!(
3409 ListReturn::tail_call(
3410 function.clone(),
3411 ValueType::Custom(custom_type.clone()),
3412 Vec::new(),
3413 ),
3414 ListReturn::Custom {
3415 item_type: custom_type,
3416 body: CustomListReturn::tail_call(function, Vec::new()),
3417 },
3418 );
3419
3420 let external_type = external_type("Token");
3421 let function = tail_call_function(ValueType::External(external_type.clone()));
3422 assert_eq!(
3423 ListReturn::tail_call(
3424 function.clone(),
3425 ValueType::External(external_type.clone()),
3426 Vec::new(),
3427 ),
3428 ListReturn::External {
3429 item_type: external_type,
3430 body: ExternalListReturn::tail_call(function, Vec::new()),
3431 },
3432 );
3433
3434 let function = tail_call_function(ValueType::Bool);
3435 assert_eq!(
3436 ListReturn::tail_call(function.clone(), ValueType::Bool, Vec::new()),
3437 ListReturn::Bool(BoolListReturn::tail_call(function, Vec::new())),
3438 );
3439
3440 let function = tail_call_function(ValueType::Nil);
3441 assert_eq!(
3442 ListReturn::tail_call(function.clone(), ValueType::Nil, Vec::new()),
3443 ListReturn::Nil(NilListReturn::tail_call(function, Vec::new())),
3444 );
3445
3446 let tuple_type = vec![ValueType::Int];
3447 let function = tail_call_function(ValueType::Tuple(tuple_type.clone()));
3448 assert_eq!(
3449 ListReturn::tail_call(
3450 function.clone(),
3451 ValueType::Tuple(tuple_type.clone()),
3452 Vec::new(),
3453 ),
3454 ListReturn::Tuple {
3455 item_type: tuple_type,
3456 body: TupleListReturn::tail_call(function, Vec::new()),
3457 },
3458 );
3459
3460 let list_type = Box::new(ValueType::Int);
3461 let function = tail_call_function(ValueType::List(list_type.clone()));
3462 assert_eq!(
3463 ListReturn::tail_call(
3464 function.clone(),
3465 ValueType::List(list_type.clone()),
3466 Vec::new(),
3467 ),
3468 ListReturn::List {
3469 item_shape: ValueStorageShape::Int,
3470 body: ListListReturn::tail_call(function, Vec::new()),
3471 },
3472 );
3473
3474 let parameter = TypeParameterId(0);
3475 let parameter_list_type = Box::new(ValueType::Parameter(parameter));
3476 let function = tail_call_function(ValueType::List(parameter_list_type.clone()));
3477 assert_eq!(
3478 ListReturn::tail_call(
3479 function.clone(),
3480 ValueType::List(parameter_list_type),
3481 Vec::new(),
3482 ),
3483 ListReturn::ParameterList {
3484 item_parameter: parameter,
3485 body: ParameterListListReturn::tail_call(function, Vec::new()),
3486 },
3487 );
3488
3489 let function_type = FunctionType::new(Vec::new(), ValueType::Int);
3490 let function = tail_call_function(ValueType::Function(Box::new(function_type.clone())));
3491 assert_eq!(
3492 ListReturn::tail_call(
3493 function.clone(),
3494 ValueType::Function(Box::new(function_type.clone())),
3495 Vec::new(),
3496 ),
3497 ListReturn::Function {
3498 item_type: function_type,
3499 body: FunctionListReturn::tail_call(function, Vec::new()),
3500 },
3501 );
3502 }
3503
3504 #[test]
3505 fn list_return_cases_and_block_preserve_typed_body() {
3506 let true_ = IntListReturn::expr(
3507 ListExpr::value(
3508 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3509 ValueType::Int,
3510 )
3511 .into_int()
3512 .expect("int list"),
3513 );
3514 let false_ = IntListReturn::expr(
3515 ListExpr::value(
3516 vec![crate::plan::Expr::int(IntExpr::value(2.into()))],
3517 ValueType::Int,
3518 )
3519 .into_int()
3520 .expect("int list"),
3521 );
3522 assert_eq!(
3523 ListReturn::try_bool_case(
3524 BoolExpr::value(true),
3525 ListReturn::Int(true_.clone()),
3526 ListReturn::Int(false_.clone()),
3527 ),
3528 Some(ListReturn::Int(IntListReturn::bool_case(
3529 BoolExpr::value(true),
3530 true_,
3531 false_,
3532 ))),
3533 );
3534
3535 let fallback = StringListReturn::expr(
3536 ListExpr::value(
3537 vec![crate::plan::Expr::string(StringExpr::value(
3538 "fallback".into(),
3539 ))],
3540 ValueType::String,
3541 )
3542 .into_string()
3543 .expect("string list"),
3544 );
3545 let branch = StringListReturn::expr(
3546 ListExpr::value(
3547 vec![crate::plan::Expr::string(StringExpr::value(
3548 "branch".into(),
3549 ))],
3550 ValueType::String,
3551 )
3552 .into_string()
3553 .expect("string list"),
3554 );
3555 assert_eq!(
3556 ListReturn::try_int_case(
3557 IntExpr::value(1.into()),
3558 vec![(BigInt::from(1), ListReturn::String(branch.clone()))],
3559 ListReturn::String(fallback.clone()),
3560 ),
3561 Some(ListReturn::String(StringListReturn::int_case(
3562 IntExpr::value(1.into()),
3563 vec![(BigInt::from(1), branch)],
3564 fallback,
3565 ))),
3566 );
3567
3568 let fallback = FloatListReturn::expr(
3569 ListExpr::value(
3570 vec![crate::plan::Expr::float(FloatExpr::value(1.5))],
3571 ValueType::Float,
3572 )
3573 .into_float()
3574 .expect("float list"),
3575 );
3576 let branch = FloatListReturn::expr(
3577 ListExpr::value(
3578 vec![crate::plan::Expr::float(FloatExpr::value(2.5))],
3579 ValueType::Float,
3580 )
3581 .into_float()
3582 .expect("float list"),
3583 );
3584 assert_eq!(
3585 ListReturn::try_string_case(
3586 StringExpr::value("key".into()),
3587 vec![("key".into(), ListReturn::Float(branch.clone()))],
3588 ListReturn::Float(fallback.clone()),
3589 ),
3590 Some(ListReturn::Float(FloatListReturn::string_case(
3591 StringExpr::value("key".into()),
3592 vec![("key".into(), branch)],
3593 fallback,
3594 ))),
3595 );
3596
3597 let fallback = BoolListReturn::expr(
3598 ListExpr::value(
3599 vec![crate::plan::Expr::bool(BoolExpr::value(false))],
3600 ValueType::Bool,
3601 )
3602 .into_bool()
3603 .expect("bool list"),
3604 );
3605 let branch = BoolListReturn::expr(
3606 ListExpr::value(
3607 vec![crate::plan::Expr::bool(BoolExpr::value(true))],
3608 ValueType::Bool,
3609 )
3610 .into_bool()
3611 .expect("bool list"),
3612 );
3613 assert_eq!(
3614 ListReturn::try_float_case(
3615 FloatExpr::value(1.5),
3616 vec![(1.5, ListReturn::Bool(branch.clone()))],
3617 ListReturn::Bool(fallback.clone()),
3618 ),
3619 Some(ListReturn::Bool(BoolListReturn::float_case(
3620 FloatExpr::value(1.5),
3621 vec![(1.5, branch)],
3622 fallback,
3623 ))),
3624 );
3625
3626 let return_ = NilListReturn::expr(
3627 ListExpr::value(
3628 vec![crate::plan::Expr::nil(NilExpr::value())],
3629 ValueType::Nil,
3630 )
3631 .into_nil()
3632 .expect("nil list"),
3633 );
3634 assert_eq!(
3635 ListReturn::try_block(
3636 Vec::<crate::plan::Step>::new(),
3637 ListReturn::Nil(return_.clone()),
3638 ),
3639 ListReturn::Nil(NilListReturn::block(
3640 Vec::<crate::plan::Step>::new(),
3641 return_,
3642 )),
3643 );
3644 }
3645
3646 #[test]
3647 fn list_return_case_rejects_mismatched_item_families() {
3648 assert_eq!(
3649 ListReturn::try_bool_case(
3650 BoolExpr::value(true),
3651 ListReturn::expr(ListExpr::value(
3652 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3653 ValueType::Int,
3654 )),
3655 ListReturn::expr(ListExpr::value(
3656 vec![crate::plan::Expr::string(StringExpr::value("wrong".into()))],
3657 ValueType::String,
3658 )),
3659 ),
3660 None,
3661 );
3662 assert_eq!(
3663 ListReturn::try_int_case(
3664 IntExpr::value(1.into()),
3665 vec![(
3666 BigInt::from(1),
3667 ListReturn::expr(ListExpr::value(
3668 vec![crate::plan::Expr::string(StringExpr::value("wrong".into()))],
3669 ValueType::String,
3670 )),
3671 )],
3672 ListReturn::expr(ListExpr::value(
3673 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3674 ValueType::Int,
3675 )),
3676 ),
3677 None,
3678 );
3679 assert_eq!(
3680 ListReturn::try_int_case(
3681 IntExpr::value(1.into()),
3682 vec![(
3683 BigInt::from(1),
3684 ListReturn::expr(ListExpr::value(
3685 Vec::new(),
3686 ValueType::List(Box::new(ValueType::String)),
3687 )),
3688 )],
3689 ListReturn::expr(ListExpr::value(
3690 Vec::new(),
3691 ValueType::Tuple(vec![ValueType::Int])
3692 )),
3693 ),
3694 None,
3695 );
3696 assert_eq!(
3697 ListReturn::try_int_case(
3698 IntExpr::value(1.into()),
3699 vec![(
3700 BigInt::from(1),
3701 ListReturn::expr(ListExpr::value(
3702 Vec::new(),
3703 ValueType::Function(Box::new(FunctionType::new(
3704 Vec::new(),
3705 ValueType::Bool
3706 ))),
3707 )),
3708 )],
3709 ListReturn::expr(ListExpr::value(
3710 Vec::new(),
3711 ValueType::List(Box::new(ValueType::String)),
3712 )),
3713 ),
3714 None,
3715 );
3716 assert_eq!(
3717 ListReturn::try_int_case(
3718 IntExpr::value(1.into()),
3719 vec![(
3720 BigInt::from(1),
3721 ListReturn::expr(ListExpr::value(
3722 Vec::new(),
3723 ValueType::Tuple(vec![ValueType::Int])
3724 )),
3725 )],
3726 ListReturn::expr(ListExpr::value(
3727 Vec::new(),
3728 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::Bool))),
3729 )),
3730 ),
3731 None,
3732 );
3733 }
3734
3735 #[test]
3736 fn return_body_kind_accessor_exposes_exact_shape() {
3737 let expression = ListExpr::value(
3738 vec![crate::plan::Expr::int(IntExpr::value(1.into()))],
3739 ValueType::Int,
3740 )
3741 .into_int()
3742 .expect("int list");
3743 let body = IntListReturn::expr(expression.clone());
3744 assert_eq!(body.kind(), &ReturnBodyKind::Expr(expression));
3745 }
3746
3747 #[test]
3748 fn list_return_case_helpers_preserve_all_item_families() {
3749 let item_types = vec![
3750 ValueType::Parameter(crate::plan::TypeParameterId(0)),
3751 ValueType::Int,
3752 ValueType::Float,
3753 ValueType::String,
3754 ValueType::BitArray,
3755 ValueType::UtfCodepoint,
3756 ValueType::Custom(custom_type()),
3757 ValueType::External(external_type("Token")),
3758 ValueType::Bool,
3759 ValueType::Nil,
3760 ValueType::Tuple(vec![ValueType::Int]),
3761 ValueType::List(Box::new(ValueType::Parameter(TypeParameterId(1)))),
3762 ValueType::List(Box::new(ValueType::String)),
3763 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::Bool))),
3764 ];
3765
3766 for item_type in item_types {
3767 let true_ = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3768 let false_ = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3769 let bool_case = ListReturn::try_bool_case(BoolExpr::value(true), true_, false_);
3770 assert_eq!(
3771 bool_case.as_ref().map(list_return_item_type),
3772 Some(item_type.clone())
3773 );
3774
3775 let branch = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3776 let fallback = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3777 let int_case = ListReturn::try_int_case(
3778 IntExpr::value(1.into()),
3779 vec![(BigInt::from(1), branch)],
3780 fallback,
3781 );
3782 assert_eq!(
3783 int_case.as_ref().map(list_return_item_type),
3784 Some(item_type.clone())
3785 );
3786
3787 let branch = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3788 let fallback = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3789 let float_case =
3790 ListReturn::try_float_case(FloatExpr::value(1.5), vec![(1.5, branch)], fallback);
3791 assert_eq!(
3792 float_case.as_ref().map(list_return_item_type),
3793 Some(item_type.clone()),
3794 );
3795
3796 let branch = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3797 let fallback = ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone()));
3798 let string_case = ListReturn::try_string_case(
3799 StringExpr::value("one".into()),
3800 vec![("one".into(), branch)],
3801 fallback,
3802 );
3803 assert_eq!(
3804 string_case.as_ref().map(list_return_item_type),
3805 Some(item_type.clone()),
3806 );
3807
3808 let block = ListReturn::try_block(
3809 Vec::<crate::plan::Step>::new(),
3810 ListReturn::expr(ListExpr::value(Vec::new(), item_type.clone())),
3811 );
3812 assert_eq!(list_return_item_type(&block), item_type);
3813 }
3814 }
3815
3816 #[test]
3817 fn list_return_case_helpers_reject_clause_mismatch_for_all_item_families() {
3818 fn empty_return(item_type: ValueType) -> ListReturn {
3819 ListReturn::expr(ListExpr::value(Vec::new(), item_type))
3820 }
3821
3822 let item_types = vec![
3823 ValueType::Parameter(crate::plan::TypeParameterId(0)),
3824 ValueType::Int,
3825 ValueType::Float,
3826 ValueType::String,
3827 ValueType::BitArray,
3828 ValueType::UtfCodepoint,
3829 ValueType::Custom(custom_type()),
3830 ValueType::External(external_type("Token")),
3831 ValueType::Bool,
3832 ValueType::Nil,
3833 ValueType::Tuple(vec![ValueType::Int]),
3834 ValueType::List(Box::new(ValueType::Parameter(TypeParameterId(1)))),
3835 ValueType::List(Box::new(ValueType::String)),
3836 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::Bool))),
3837 ];
3838
3839 for item_type in item_types {
3840 let mismatched_type = if item_type == ValueType::Int {
3841 ValueType::String
3842 } else {
3843 ValueType::Int
3844 };
3845
3846 assert_eq!(
3847 ListReturn::try_int_case(
3848 IntExpr::value(1.into()),
3849 vec![(BigInt::from(1), empty_return(mismatched_type.clone()))],
3850 empty_return(item_type.clone()),
3851 ),
3852 None,
3853 );
3854 assert_eq!(
3855 ListReturn::try_float_case(
3856 FloatExpr::value(1.5),
3857 vec![(1.5, empty_return(mismatched_type.clone()))],
3858 empty_return(item_type.clone()),
3859 ),
3860 None,
3861 );
3862 assert_eq!(
3863 ListReturn::try_string_case(
3864 StringExpr::value("one".into()),
3865 vec![("one".into(), empty_return(mismatched_type))],
3866 empty_return(item_type),
3867 ),
3868 None,
3869 );
3870 }
3871 }
3872
3873 #[test]
3874 fn list_return_case_helpers_reject_nested_item_metadata_mismatch() {
3875 fn empty_return(item_type: ValueType) -> ListReturn {
3876 ListReturn::expr(ListExpr::value(Vec::new(), item_type))
3877 }
3878
3879 fn assert_case_helpers_reject(branch_type: ValueType, fallback_type: ValueType) {
3880 assert_eq!(
3881 ListReturn::try_bool_case(
3882 BoolExpr::value(true),
3883 empty_return(branch_type.clone()),
3884 empty_return(fallback_type.clone()),
3885 ),
3886 None,
3887 );
3888 assert_eq!(
3889 ListReturn::try_int_case(
3890 IntExpr::value(1.into()),
3891 vec![(BigInt::from(1), empty_return(branch_type.clone()))],
3892 empty_return(fallback_type.clone()),
3893 ),
3894 None,
3895 );
3896 assert_eq!(
3897 ListReturn::try_float_case(
3898 FloatExpr::value(1.5),
3899 vec![(1.5, empty_return(branch_type.clone()))],
3900 empty_return(fallback_type.clone()),
3901 ),
3902 None,
3903 );
3904 assert_eq!(
3905 ListReturn::try_string_case(
3906 StringExpr::value("one".into()),
3907 vec![("one".into(), empty_return(branch_type))],
3908 empty_return(fallback_type),
3909 ),
3910 None,
3911 );
3912 }
3913
3914 assert_case_helpers_reject(
3915 ValueType::Tuple(vec![ValueType::String]),
3916 ValueType::Tuple(vec![ValueType::Int]),
3917 );
3918 assert_case_helpers_reject(
3919 ValueType::List(Box::new(ValueType::String)),
3920 ValueType::List(Box::new(ValueType::Int)),
3921 );
3922 assert_case_helpers_reject(
3923 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::String))),
3924 ValueType::Function(Box::new(FunctionType::new(Vec::new(), ValueType::Int))),
3925 );
3926 assert_case_helpers_reject(
3927 ValueType::External(external_type("Left")),
3928 ValueType::External(external_type("Right")),
3929 );
3930 }
3931
3932 fn list_return_item_type(return_: &ListReturn) -> ValueType {
3933 match return_ {
3934 ListReturn::Generic { item_parameter, .. } => ValueType::Parameter(*item_parameter),
3935 ListReturn::Int(_) => ValueType::Int,
3936 ListReturn::Float(_) => ValueType::Float,
3937 ListReturn::String(_) => ValueType::String,
3938 ListReturn::BitArray(_) => ValueType::BitArray,
3939 ListReturn::UtfCodepoint(_) => ValueType::UtfCodepoint,
3940 ListReturn::Custom { item_type, .. } => ValueType::Custom(item_type.clone()),
3941 ListReturn::External { item_type, .. } => ValueType::External(item_type.clone()),
3942 ListReturn::Bool(_) => ValueType::Bool,
3943 ListReturn::Nil(_) => ValueType::Nil,
3944 ListReturn::Tuple { item_type, .. } => ValueType::Tuple(item_type.clone()),
3945 ListReturn::ParameterList { item_parameter, .. } => {
3946 ValueType::List(Box::new(ValueType::Parameter(*item_parameter)))
3947 }
3948 ListReturn::List { item_shape, .. } => {
3949 ValueType::List(Box::new(item_shape.value_type()))
3950 }
3951 ListReturn::Function { item_type, .. } => {
3952 ValueType::Function(Box::new(item_type.clone()))
3953 }
3954 }
3955 }
3956}