1use super::expression::{
2 BitArrayExpr, BitArrayFunctionExpr, BoolExpr, BoolFunctionExpr, CustomExpr, CustomFunctionExpr,
3 CustomLocalExpr, Expr, ExternalExpr, ExternalFunctionExpr, FloatExpr, FloatFunctionExpr,
4 FunctionFunctionExpr, GenericExpr, GenericFunctionExpr, IntExpr, IntFunctionExpr,
5 ListFunctionExpr, ListLocalExpr, NilExpr, NilFunctionExpr, StringExpr, StringFunctionExpr,
6 TupleExpr, TupleFunctionExpr, TypedFunctionExpr, UtfCodepointExpr, UtfCodepointFunctionExpr,
7};
8use super::function::{ParamLocal, ParamSlot};
9use super::id::{
10 BitArrayFunctionLocalId, BitArrayLocalId, BoolFunctionLocalId, BoolLocalId,
11 CustomFunctionLocal, CustomFunctionLocalId, CustomLocal, CustomLocalId, ExternalFunctionLocal,
12 ExternalFunctionLocalId, ExternalLocal, FloatFunctionLocalId, FloatLocalId,
13 FunctionFunctionLocal, FunctionFunctionLocalId, GenericFunctionLocal, GenericLocal,
14 IntFunctionLocalId, IntLocalId, ListFunctionLocal, ListLocal, NilFunctionLocalId, NilLocalId,
15 StringFunctionLocalId, StringLocalId, TupleFunctionLocalId, TupleLocalId,
16 UtfCodepointFunctionLocalId, UtfCodepointLocalId,
17};
18use crate::plan::{BitArrayPattern, CustomBindingPattern};
19use crate::plan::{EchoSite, PanicSite, SourceSpan, ValueType};
20use ecow::EcoString;
21
22#[derive(Debug, Clone, PartialEq)]
23pub struct Step {
24 kind: StepKind,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub(crate) struct AssertBinding {
29 slot: ParamSlot,
30 name: EcoString,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub(crate) struct StringAssertBinding {
35 local: StringLocalId,
36 name: EcoString,
37}
38
39#[derive(Debug, Clone, PartialEq)]
40pub(crate) enum AssertPattern {
41 Bind(AssertBinding),
42 Discard,
43 Int(num_bigint::BigInt),
44 Float(f64),
45 String(EcoString),
46 Bool(bool),
47 Nil,
48 Tuple(Vec<AssertPattern>),
49 List(ListAssertPattern),
50 BitArray(BitArrayPattern),
51 Custom(crate::plan::CustomPattern),
52 StringPrefix {
53 prefix: EcoString,
54 left: Option<StringAssertBinding>,
55 right: Option<StringAssertBinding>,
56 },
57 Alias {
58 pattern: Box<AssertPattern>,
59 binding: AssertBinding,
60 },
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub(crate) enum AssertSubject {
65 Int(IntLocalId),
66 Float(FloatLocalId),
67 String(StringLocalId),
68 BitArray(BitArrayLocalId),
69 Custom(CustomLocal),
70 Bool(BoolLocalId),
71 Nil(NilLocalId),
72 Tuple(TupleLocalId),
73 List(ListLocal),
74}
75
76#[derive(Debug, Clone, PartialEq)]
77pub(crate) struct ListAssertPattern {
78 element_type: ValueType,
79 elements: Vec<AssertPattern>,
80 tail: Option<ListAssertTail>,
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub(crate) struct ListAssertTailBinding {
85 local: ListLocal,
86 name: EcoString,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub(crate) enum ListAssertTail {
91 Ignore,
92 Bind(ListAssertTailBinding),
93}
94
95#[derive(Debug, Clone, PartialEq)]
96pub(crate) enum StepKind {
97 LetGeneric {
98 local: GenericLocal,
99 name: EcoString,
100 value: GenericExpr,
101 },
102 LetInt {
103 local: IntLocalId,
104 name: EcoString,
105 value: IntExpr,
106 },
107 LetFloat {
108 local: FloatLocalId,
109 name: EcoString,
110 value: FloatExpr,
111 },
112 LetString {
113 local: StringLocalId,
114 name: EcoString,
115 value: StringExpr,
116 },
117 LetBitArray {
118 local: BitArrayLocalId,
119 name: EcoString,
120 value: BitArrayExpr,
121 },
122 LetUtfCodepoint {
123 local: UtfCodepointLocalId,
124 name: EcoString,
125 value: UtfCodepointExpr,
126 },
127 LetCustom {
128 binding: CustomLocalExpr,
129 name: EcoString,
130 },
131 LetExternal {
132 local: ExternalLocal,
133 name: EcoString,
134 value: ExternalExpr,
135 },
136 LetBool {
137 local: BoolLocalId,
138 name: EcoString,
139 value: BoolExpr,
140 },
141 LetNil {
142 local: NilLocalId,
143 name: EcoString,
144 value: NilExpr,
145 },
146 LetTuple {
147 local: TupleLocalId,
148 name: EcoString,
149 value: TupleExpr,
150 },
151 LetList {
152 name: EcoString,
153 value: ListLocalExpr,
154 },
155 LetIntFunction {
156 local: IntFunctionLocalId,
157 name: EcoString,
158 value: TypedFunctionExpr<IntFunctionExpr>,
159 },
160 LetFloatFunction {
161 local: FloatFunctionLocalId,
162 name: EcoString,
163 value: TypedFunctionExpr<FloatFunctionExpr>,
164 },
165 LetStringFunction {
166 local: StringFunctionLocalId,
167 name: EcoString,
168 value: TypedFunctionExpr<StringFunctionExpr>,
169 },
170 LetBitArrayFunction {
171 local: BitArrayFunctionLocalId,
172 name: EcoString,
173 value: TypedFunctionExpr<BitArrayFunctionExpr>,
174 },
175 LetUtfCodepointFunction {
176 local: UtfCodepointFunctionLocalId,
177 name: EcoString,
178 value: TypedFunctionExpr<UtfCodepointFunctionExpr>,
179 },
180 LetCustomFunction {
181 local: CustomFunctionLocal,
182 name: EcoString,
183 value: TypedFunctionExpr<CustomFunctionExpr>,
184 },
185 LetExternalFunction {
186 local: ExternalFunctionLocal,
187 name: EcoString,
188 value: TypedFunctionExpr<ExternalFunctionExpr>,
189 },
190 LetBoolFunction {
191 local: BoolFunctionLocalId,
192 name: EcoString,
193 value: TypedFunctionExpr<BoolFunctionExpr>,
194 },
195 LetNilFunction {
196 local: NilFunctionLocalId,
197 name: EcoString,
198 value: TypedFunctionExpr<NilFunctionExpr>,
199 },
200 LetTupleFunction {
201 local: TupleFunctionLocalId,
202 name: EcoString,
203 value: TypedFunctionExpr<TupleFunctionExpr>,
204 },
205 LetListFunction {
206 local: ListFunctionLocal,
207 name: EcoString,
208 value: TypedFunctionExpr<ListFunctionExpr>,
209 },
210 LetFunctionFunction {
211 local: FunctionFunctionLocal,
212 name: EcoString,
213 value: TypedFunctionExpr<FunctionFunctionExpr>,
214 },
215 LetGenericFunction {
216 local: GenericFunctionLocal,
217 name: EcoString,
218 value: TypedFunctionExpr<GenericFunctionExpr>,
219 },
220 Echo(Echo),
221 AssertPattern {
222 subject: AssertSubject,
223 pattern: AssertPattern,
224 message: Option<StringExpr>,
225 site: PanicSite,
226 pattern_span: SourceSpan,
227 },
228 BindCustomFields {
229 local: CustomLocal,
230 pattern: CustomBindingPattern,
231 },
232 AssertBool {
233 condition: BoolExpr,
234 message: Option<StringExpr>,
235 site: PanicSite,
236 },
237 Evaluate(Expr),
238}
239
240#[derive(Debug, Clone, PartialEq)]
241pub(crate) struct Echo {
242 subject: EchoSubject,
243 message: Option<StringExpr>,
244 site: EchoSite,
245}
246
247#[derive(Debug, Clone, PartialEq)]
248pub(crate) enum EchoSubject {
249 Generic {
250 local: GenericLocal,
251 value: GenericExpr,
252 },
253 Int {
254 local: IntLocalId,
255 value: IntExpr,
256 },
257 Float {
258 local: FloatLocalId,
259 value: FloatExpr,
260 },
261 String {
262 local: StringLocalId,
263 value: StringExpr,
264 },
265 BitArray {
266 local: BitArrayLocalId,
267 value: BitArrayExpr,
268 },
269 UtfCodepoint {
270 local: UtfCodepointLocalId,
271 value: UtfCodepointExpr,
272 },
273 Custom(CustomLocalExpr),
274 External {
275 local: ExternalLocal,
276 value: ExternalExpr,
277 },
278 Bool {
279 local: BoolLocalId,
280 value: BoolExpr,
281 },
282 Nil {
283 local: NilLocalId,
284 value: NilExpr,
285 },
286 Tuple {
287 local: TupleLocalId,
288 value: TupleExpr,
289 },
290 List(ListLocalExpr),
291 IntFunction {
292 local: IntFunctionLocalId,
293 value: TypedFunctionExpr<IntFunctionExpr>,
294 },
295 FloatFunction {
296 local: FloatFunctionLocalId,
297 value: TypedFunctionExpr<FloatFunctionExpr>,
298 },
299 StringFunction {
300 local: StringFunctionLocalId,
301 value: TypedFunctionExpr<StringFunctionExpr>,
302 },
303 BitArrayFunction {
304 local: BitArrayFunctionLocalId,
305 value: TypedFunctionExpr<BitArrayFunctionExpr>,
306 },
307 UtfCodepointFunction {
308 local: UtfCodepointFunctionLocalId,
309 value: TypedFunctionExpr<UtfCodepointFunctionExpr>,
310 },
311 CustomFunction {
312 local: CustomFunctionLocal,
313 value: TypedFunctionExpr<CustomFunctionExpr>,
314 },
315 ExternalFunction {
316 local: ExternalFunctionLocal,
317 value: TypedFunctionExpr<ExternalFunctionExpr>,
318 },
319 BoolFunction {
320 local: BoolFunctionLocalId,
321 value: TypedFunctionExpr<BoolFunctionExpr>,
322 },
323 NilFunction {
324 local: NilFunctionLocalId,
325 value: TypedFunctionExpr<NilFunctionExpr>,
326 },
327 TupleFunction {
328 local: TupleFunctionLocalId,
329 value: TypedFunctionExpr<TupleFunctionExpr>,
330 },
331 ListFunction {
332 local: ListFunctionLocal,
333 value: TypedFunctionExpr<ListFunctionExpr>,
334 },
335 FunctionFunction {
336 local: FunctionFunctionLocal,
337 value: TypedFunctionExpr<FunctionFunctionExpr>,
338 },
339 GenericFunction {
340 local: GenericFunctionLocal,
341 value: TypedFunctionExpr<GenericFunctionExpr>,
342 },
343}
344
345impl AssertBinding {
346 pub(crate) fn new(local: ParamLocal, name: EcoString, shape: crate::plan::ValueShape) -> Self {
347 Self {
348 slot: ParamSlot::new(local, shape),
349 name,
350 }
351 }
352
353 pub(crate) fn local(&self) -> &ParamLocal {
354 self.slot.local()
355 }
356
357 pub(crate) fn slot(&self) -> &ParamSlot {
358 &self.slot
359 }
360}
361
362impl StringAssertBinding {
363 pub(crate) fn new(local: StringLocalId, name: EcoString) -> Self {
364 Self { local, name }
365 }
366
367 pub(crate) fn local(&self) -> StringLocalId {
368 self.local
369 }
370}
371
372impl AssertPattern {
373 pub(crate) fn list(pattern: ListAssertPattern) -> Self {
374 Self::List(pattern)
375 }
376
377 pub(crate) fn bit_array(pattern: BitArrayPattern) -> Self {
378 Self::BitArray(pattern)
379 }
380
381 pub(crate) fn custom(pattern: crate::plan::CustomPattern) -> Self {
382 Self::Custom(pattern)
383 }
384
385 pub(crate) fn alias(pattern: AssertPattern, binding: AssertBinding) -> Self {
386 Self::Alias {
387 pattern: Box::new(pattern),
388 binding,
389 }
390 }
391}
392
393impl ListAssertPattern {
394 pub(crate) fn new(
395 element_type: ValueType,
396 elements: Vec<AssertPattern>,
397 tail: Option<ListAssertTail>,
398 ) -> Self {
399 Self {
400 element_type,
401 elements,
402 tail,
403 }
404 }
405
406 pub(crate) fn element_type(&self) -> &ValueType {
407 &self.element_type
408 }
409
410 pub(crate) fn elements(&self) -> &[AssertPattern] {
411 &self.elements
412 }
413
414 pub(crate) fn tail(&self) -> Option<&ListAssertTail> {
415 self.tail.as_ref()
416 }
417}
418
419impl ListAssertTail {
420 pub(crate) fn bind(local: ListLocal, name: EcoString) -> Self {
421 Self::Bind(ListAssertTailBinding { local, name })
422 }
423}
424
425impl ListAssertTailBinding {
426 pub(crate) fn local(&self) -> &ListLocal {
427 &self.local
428 }
429}
430
431impl Step {
432 pub(crate) fn let_generic(local: GenericLocal, name: EcoString, value: GenericExpr) -> Self {
433 Self {
434 kind: StepKind::LetGeneric { local, name, value },
435 }
436 }
437
438 pub(crate) fn let_int(local: IntLocalId, name: EcoString, value: IntExpr) -> Self {
439 Self {
440 kind: StepKind::LetInt { local, name, value },
441 }
442 }
443
444 pub(crate) fn let_float(local: FloatLocalId, name: EcoString, value: FloatExpr) -> Self {
445 Self {
446 kind: StepKind::LetFloat { local, name, value },
447 }
448 }
449
450 pub(crate) fn let_string(local: StringLocalId, name: EcoString, value: StringExpr) -> Self {
451 Self {
452 kind: StepKind::LetString { local, name, value },
453 }
454 }
455
456 pub(crate) fn let_bit_array(
457 local: BitArrayLocalId,
458 name: EcoString,
459 value: BitArrayExpr,
460 ) -> Self {
461 Self {
462 kind: StepKind::LetBitArray { local, name, value },
463 }
464 }
465
466 pub(crate) fn let_utf_codepoint(
467 local: UtfCodepointLocalId,
468 name: EcoString,
469 value: UtfCodepointExpr,
470 ) -> Self {
471 Self {
472 kind: StepKind::LetUtfCodepoint { local, name, value },
473 }
474 }
475
476 pub(crate) fn let_custom(local: CustomLocalId, name: EcoString, value: CustomExpr) -> Self {
477 Self {
478 kind: StepKind::LetCustom {
479 binding: CustomLocalExpr::from_value(local, value),
480 name,
481 },
482 }
483 }
484
485 pub(crate) fn let_external(local: ExternalLocal, name: EcoString, value: ExternalExpr) -> Self {
486 Self {
487 kind: StepKind::LetExternal { local, name, value },
488 }
489 }
490
491 pub(crate) fn let_bool(local: BoolLocalId, name: EcoString, value: BoolExpr) -> Self {
492 Self {
493 kind: StepKind::LetBool { local, name, value },
494 }
495 }
496
497 pub(crate) fn let_nil(local: NilLocalId, name: EcoString, value: NilExpr) -> Self {
498 Self {
499 kind: StepKind::LetNil { local, name, value },
500 }
501 }
502
503 pub(crate) fn let_tuple(local: TupleLocalId, name: EcoString, value: TupleExpr) -> Self {
504 Self {
505 kind: StepKind::LetTuple { local, name, value },
506 }
507 }
508
509 pub(crate) fn let_list_expr(name: EcoString, value: ListLocalExpr) -> Self {
510 Self {
511 kind: StepKind::LetList { name, value },
512 }
513 }
514
515 pub(crate) fn let_int_function_expr(
516 local: IntFunctionLocalId,
517 name: EcoString,
518 value: TypedFunctionExpr<IntFunctionExpr>,
519 ) -> Self {
520 Self {
521 kind: StepKind::LetIntFunction { local, name, value },
522 }
523 }
524
525 pub(crate) fn let_float_function_expr(
526 local: FloatFunctionLocalId,
527 name: EcoString,
528 value: TypedFunctionExpr<FloatFunctionExpr>,
529 ) -> Self {
530 Self {
531 kind: StepKind::LetFloatFunction { local, name, value },
532 }
533 }
534
535 pub(crate) fn let_string_function_expr(
536 local: StringFunctionLocalId,
537 name: EcoString,
538 value: TypedFunctionExpr<StringFunctionExpr>,
539 ) -> Self {
540 Self {
541 kind: StepKind::LetStringFunction { local, name, value },
542 }
543 }
544
545 pub(crate) fn let_bit_array_function_expr(
546 local: BitArrayFunctionLocalId,
547 name: EcoString,
548 value: TypedFunctionExpr<BitArrayFunctionExpr>,
549 ) -> Self {
550 Self {
551 kind: StepKind::LetBitArrayFunction { local, name, value },
552 }
553 }
554
555 pub(crate) fn let_utf_codepoint_function_expr(
556 local: UtfCodepointFunctionLocalId,
557 name: EcoString,
558 value: TypedFunctionExpr<UtfCodepointFunctionExpr>,
559 ) -> Self {
560 Self {
561 kind: StepKind::LetUtfCodepointFunction { local, name, value },
562 }
563 }
564
565 pub(crate) fn let_custom_function_expr(
566 local: CustomFunctionLocalId,
567 name: EcoString,
568 value: TypedFunctionExpr<CustomFunctionExpr>,
569 ) -> Self {
570 let local =
571 CustomFunctionLocal::new(local, value.expression().custom_function_type().clone());
572 Self {
573 kind: StepKind::LetCustomFunction { local, name, value },
574 }
575 }
576
577 pub(crate) fn let_external_function_expr(
578 local: ExternalFunctionLocalId,
579 name: EcoString,
580 value: TypedFunctionExpr<ExternalFunctionExpr>,
581 ) -> Self {
582 let local =
583 ExternalFunctionLocal::new(local, value.expression().external_function_type().clone());
584 Self {
585 kind: StepKind::LetExternalFunction { local, name, value },
586 }
587 }
588
589 pub(crate) fn let_bool_function_expr(
590 local: BoolFunctionLocalId,
591 name: EcoString,
592 value: TypedFunctionExpr<BoolFunctionExpr>,
593 ) -> Self {
594 Self {
595 kind: StepKind::LetBoolFunction { local, name, value },
596 }
597 }
598
599 pub(crate) fn let_nil_function_expr(
600 local: NilFunctionLocalId,
601 name: EcoString,
602 value: TypedFunctionExpr<NilFunctionExpr>,
603 ) -> Self {
604 Self {
605 kind: StepKind::LetNilFunction { local, name, value },
606 }
607 }
608
609 pub(crate) fn let_tuple_function_expr(
610 local: TupleFunctionLocalId,
611 name: EcoString,
612 value: TypedFunctionExpr<TupleFunctionExpr>,
613 ) -> Self {
614 Self {
615 kind: StepKind::LetTupleFunction { local, name, value },
616 }
617 }
618
619 pub(crate) fn let_list_function_expr(
620 local: ListFunctionLocal,
621 name: EcoString,
622 value: TypedFunctionExpr<ListFunctionExpr>,
623 ) -> Self {
624 Self {
625 kind: StepKind::LetListFunction { local, name, value },
626 }
627 }
628
629 pub(crate) fn let_function_function_expr(
630 local: FunctionFunctionLocalId,
631 name: EcoString,
632 value: TypedFunctionExpr<FunctionFunctionExpr>,
633 ) -> Self {
634 let local =
635 FunctionFunctionLocal::new(local, value.expression().function_function_type().clone());
636 Self {
637 kind: StepKind::LetFunctionFunction { local, name, value },
638 }
639 }
640
641 pub(crate) fn let_generic_function_expr(
642 local: GenericFunctionLocal,
643 name: EcoString,
644 value: TypedFunctionExpr<GenericFunctionExpr>,
645 ) -> Self {
646 Self {
647 kind: StepKind::LetGenericFunction { local, name, value },
648 }
649 }
650
651 pub(crate) fn echo(subject: EchoSubject, message: Option<StringExpr>, site: EchoSite) -> Self {
652 Self {
653 kind: StepKind::Echo(Echo {
654 subject,
655 message,
656 site,
657 }),
658 }
659 }
660
661 #[cfg(test)]
662 pub(crate) fn let_int_function(
663 local: IntFunctionLocalId,
664 name: EcoString,
665 value: IntFunctionExpr,
666 ) -> Self {
667 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
668 Self::let_int_function_expr(local, name, TypedFunctionExpr::new(shape, value))
669 }
670
671 #[cfg(test)]
672 pub(crate) fn let_float_function(
673 local: FloatFunctionLocalId,
674 name: EcoString,
675 value: FloatFunctionExpr,
676 ) -> Self {
677 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
678 Self::let_float_function_expr(local, name, TypedFunctionExpr::new(shape, value))
679 }
680
681 #[cfg(test)]
682 pub(crate) fn let_string_function(
683 local: StringFunctionLocalId,
684 name: EcoString,
685 value: StringFunctionExpr,
686 ) -> Self {
687 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
688 Self::let_string_function_expr(local, name, TypedFunctionExpr::new(shape, value))
689 }
690
691 #[cfg(test)]
692 pub(crate) fn let_bit_array_function(
693 local: BitArrayFunctionLocalId,
694 name: EcoString,
695 value: BitArrayFunctionExpr,
696 ) -> Self {
697 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
698 Self::let_bit_array_function_expr(local, name, TypedFunctionExpr::new(shape, value))
699 }
700
701 #[cfg(test)]
702 pub(crate) fn let_utf_codepoint_function(
703 local: UtfCodepointFunctionLocalId,
704 name: EcoString,
705 value: UtfCodepointFunctionExpr,
706 ) -> Self {
707 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
708 Self::let_utf_codepoint_function_expr(local, name, TypedFunctionExpr::new(shape, value))
709 }
710
711 #[cfg(test)]
712 pub(crate) fn let_custom_function(
713 local: CustomFunctionLocalId,
714 name: EcoString,
715 value: CustomFunctionExpr,
716 ) -> Self {
717 let shape = crate::plan::FunctionShape::new(
718 value.custom_function_type().argument_shapes().to_vec(),
719 crate::plan::ValueShape::Custom(value.custom_function_type().return_().clone()),
720 );
721 Self::let_custom_function_expr(local, name, TypedFunctionExpr::new(shape, value))
722 }
723
724 #[cfg(test)]
725 pub(crate) fn let_bool_function(
726 local: BoolFunctionLocalId,
727 name: EcoString,
728 value: BoolFunctionExpr,
729 ) -> Self {
730 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
731 Self::let_bool_function_expr(local, name, TypedFunctionExpr::new(shape, value))
732 }
733
734 #[cfg(test)]
735 pub(crate) fn let_nil_function(
736 local: NilFunctionLocalId,
737 name: EcoString,
738 value: NilFunctionExpr,
739 ) -> Self {
740 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
741 Self::let_nil_function_expr(local, name, TypedFunctionExpr::new(shape, value))
742 }
743
744 #[cfg(test)]
745 pub(crate) fn let_tuple_function(
746 local: TupleFunctionLocalId,
747 name: EcoString,
748 value: TupleFunctionExpr,
749 ) -> Self {
750 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
751 Self::let_tuple_function_expr(local, name, TypedFunctionExpr::new(shape, value))
752 }
753
754 #[cfg(test)]
755 pub(crate) fn let_list_function(
756 local: ListFunctionLocal,
757 name: EcoString,
758 value: ListFunctionExpr,
759 ) -> Self {
760 let shape = crate::plan::FunctionShape::from_function_type(value.type_().clone());
761 Self::let_list_function_expr(local, name, TypedFunctionExpr::new(shape, value))
762 }
763
764 #[cfg(test)]
765 pub(crate) fn let_function_function(
766 local: FunctionFunctionLocalId,
767 name: EcoString,
768 value: FunctionFunctionExpr,
769 ) -> Self {
770 let shape = crate::plan::FunctionShape::from_function_type(value.type_());
771 Self::let_function_function_expr(local, name, TypedFunctionExpr::new(shape, value))
772 }
773
774 pub(crate) fn assert_pattern_at(
775 subject: AssertSubject,
776 pattern: AssertPattern,
777 message: Option<StringExpr>,
778 site: PanicSite,
779 pattern_span: SourceSpan,
780 ) -> Self {
781 Self {
782 kind: StepKind::AssertPattern {
783 subject,
784 pattern,
785 message,
786 site,
787 pattern_span,
788 },
789 }
790 }
791
792 pub(crate) fn bind_custom_fields(local: CustomLocalId, pattern: CustomBindingPattern) -> Self {
793 let local = CustomLocal::from_shape(local, pattern.source_shape().clone());
794 Self {
795 kind: StepKind::BindCustomFields { local, pattern },
796 }
797 }
798
799 pub(crate) fn assert_bool_at(
800 condition: BoolExpr,
801 message: Option<StringExpr>,
802 site: PanicSite,
803 ) -> Self {
804 Self {
805 kind: StepKind::AssertBool {
806 condition,
807 message,
808 site,
809 },
810 }
811 }
812
813 pub(crate) fn evaluate(value: Expr) -> Self {
814 Self {
815 kind: StepKind::Evaluate(value),
816 }
817 }
818
819 pub(crate) fn kind(&self) -> &StepKind {
820 &self.kind
821 }
822}
823
824impl Echo {
825 pub(crate) fn subject(&self) -> &EchoSubject {
826 &self.subject
827 }
828
829 pub(crate) fn message(&self) -> Option<&StringExpr> {
830 self.message.as_ref()
831 }
832
833 pub(crate) fn site(&self) -> &EchoSite {
834 &self.site
835 }
836}
837
838#[cfg(test)]
839mod tests {
840 use super::{Step, StepKind};
841 use crate::plan::module::TypedFunctionExpr;
842 use crate::plan::{
843 AssertPattern, AssertSubject, BoolExpr, CustomFunctionExpr, CustomFunctionLocal,
844 CustomFunctionLocalId, CustomFunctionType, CustomType, CustomTypeName, Expr,
845 FunctionFunctionExpr, FunctionFunctionLocal, FunctionFunctionLocalId, FunctionFunctionType,
846 FunctionType, IntExpr, IntFunctionLocalId, IntFunctionReference, IntListLocalId,
847 IntLocalId, ListAssertPattern, ListAssertTail, ListLocal, PanicExpr, PanicSite, StringExpr,
848 ValueShape, ValueType,
849 };
850 use num_bigint::BigInt;
851
852 #[test]
853 fn step_kind_accessors() {
854 assert_eq!(
855 Step::let_int(IntLocalId(0), "x".into(), IntExpr::value(BigInt::from(1))).kind(),
856 &StepKind::LetInt {
857 local: IntLocalId(0),
858 name: "x".into(),
859 value: IntExpr::value(BigInt::from(1)),
860 },
861 );
862 assert_eq!(
863 Step::let_int_function(IntFunctionLocalId(0), "f".into(), function_expr()).kind(),
864 &StepKind::LetIntFunction {
865 local: IntFunctionLocalId(0),
866 name: "f".into(),
867 value: TypedFunctionExpr::new(
868 crate::plan::FunctionShape::from_function_type(function_expr().type_().clone()),
869 function_expr(),
870 ),
871 },
872 );
873 assert_eq!(
874 Step::evaluate(Expr::int(IntExpr::value(BigInt::from(1)))).kind(),
875 &StepKind::Evaluate(Expr::int(IntExpr::value(BigInt::from(1)))),
876 );
877 assert_eq!(
878 Step::assert_bool_at(
879 BoolExpr::value(false),
880 Some(StringExpr::value("nope".into())),
881 crate::plan::PanicSite::unknown(),
882 )
883 .kind(),
884 &StepKind::AssertBool {
885 condition: BoolExpr::value(false),
886 message: Some(StringExpr::value("nope".into())),
887 site: crate::plan::PanicSite::unknown(),
888 },
889 );
890 assert_eq!(
891 Step::assert_pattern_at(
892 AssertSubject::List(ListLocal::int(IntListLocalId(0))),
893 AssertPattern::list(ListAssertPattern::new(
894 ValueType::Int,
895 vec![AssertPattern::Discard],
896 Some(ListAssertTail::bind(
897 ListLocal::int(IntListLocalId(1)),
898 "tail".into()
899 )),
900 )),
901 None,
902 crate::plan::PanicSite::unknown(),
903 crate::plan::SourceSpan::new(0, 0),
904 )
905 .kind(),
906 &StepKind::AssertPattern {
907 subject: AssertSubject::List(ListLocal::int(IntListLocalId(0))),
908 pattern: AssertPattern::list(ListAssertPattern::new(
909 ValueType::Int,
910 vec![AssertPattern::Discard],
911 Some(ListAssertTail::bind(
912 ListLocal::int(IntListLocalId(1)),
913 "tail".into()
914 )),
915 )),
916 message: None,
917 site: crate::plan::PanicSite::unknown(),
918 pattern_span: crate::plan::SourceSpan::new(0, 0),
919 },
920 );
921 }
922
923 #[test]
924 fn callable_let_steps_derive_the_local_type_from_the_value() {
925 let custom_type = CustomType::new(
926 CustomTypeName::new("geam".into(), "main".into(), "Boxed".into()),
927 Vec::new(),
928 );
929 let custom_function_type =
930 CustomFunctionType::new(vec![ValueType::Int], custom_type.clone());
931 let custom_value = CustomFunctionExpr::panic(
932 PanicExpr::panic_at(None, PanicSite::unknown()),
933 custom_function_type.clone(),
934 );
935 assert_eq!(
936 Step::let_custom_function(
937 CustomFunctionLocalId(3),
938 "custom".into(),
939 custom_value.clone(),
940 )
941 .kind(),
942 &StepKind::LetCustomFunction {
943 local: CustomFunctionLocal::new(CustomFunctionLocalId(3), custom_function_type,),
944 name: "custom".into(),
945 value: TypedFunctionExpr::new(
946 crate::plan::FunctionShape::new(
947 custom_value
948 .custom_function_type()
949 .argument_shapes()
950 .to_vec(),
951 ValueShape::Custom(custom_value.custom_function_type().return_().clone(),),
952 ),
953 custom_value,
954 ),
955 },
956 );
957
958 let function_function_type = FunctionFunctionType::new(
959 vec![ValueType::String],
960 FunctionType::new(vec![ValueType::Bool], ValueType::Int),
961 );
962 let function_value = FunctionFunctionExpr::panic(
963 PanicExpr::panic_at(None, PanicSite::unknown()),
964 function_function_type.clone(),
965 );
966 assert_eq!(
967 Step::let_function_function(
968 FunctionFunctionLocalId(4),
969 "function".into(),
970 function_value.clone(),
971 )
972 .kind(),
973 &StepKind::LetFunctionFunction {
974 local: FunctionFunctionLocal::new(
975 FunctionFunctionLocalId(4),
976 function_function_type,
977 ),
978 name: "function".into(),
979 value: TypedFunctionExpr::new(
980 crate::plan::FunctionShape::from_function_type(function_value.type_()),
981 function_value,
982 ),
983 },
984 );
985 }
986
987 fn function_expr() -> crate::plan::IntFunctionExpr {
988 crate::plan::IntFunctionExpr::reference(IntFunctionReference::new(
989 crate::plan::monomorphic_function_instantiation(
990 0,
991 crate::plan::FunctionShape::new(
992 vec![crate::plan::ValueShape::Int],
993 crate::plan::ValueShape::Int,
994 ),
995 ),
996 ))
997 }
998}