1use core::{
2 fmt,
3 ops::{Index, IndexMut},
4};
5
6use miden_core::{Felt, FieldElement};
7use midenc_hir::{AttributeValue, Immediate, Type, ValueRef};
8use smallvec::{smallvec, SmallVec};
9
10#[derive(Debug, Copy, Clone)]
14pub enum Constraint {
15 Move,
19 Copy,
22}
23
24pub enum OperandType {
26 Const(Box<dyn AttributeValue>),
28 Value(ValueRef),
30 Type(Type),
33}
34impl Clone for OperandType {
35 fn clone(&self) -> Self {
36 match self {
37 Self::Const(value) => Self::Const(value.clone_value()),
38 Self::Value(value) => Self::Value(*value),
39 Self::Type(ty) => Self::Type(ty.clone()),
40 }
41 }
42}
43impl OperandType {
44 pub fn ty(&self) -> Type {
46 match self {
47 Self::Const(imm) => {
48 imm.downcast_ref::<Immediate>().expect("unexpected constant value type").ty()
49 }
50 Self::Value(value) => value.borrow().ty().clone(),
51 Self::Type(ref ty) => ty.clone(),
52 }
53 }
54}
55impl fmt::Debug for OperandType {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 match self {
58 Self::Const(value) => write!(f, "Const({value:?})"),
59 Self::Value(value) => write!(f, "Value({value})"),
60 Self::Type(ty) => write!(f, "Type({ty})"),
61 }
62 }
63}
64impl Eq for OperandType {}
65impl PartialEq for OperandType {
66 fn eq(&self, other: &Self) -> bool {
67 match (self, other) {
68 (Self::Value(a), Self::Value(b)) => a == b,
69 (Self::Value(_), _) | (_, Self::Value(_)) => false,
70 (Self::Const(ref a), Self::Const(ref b)) => a == b,
71 (Self::Const(_), _) | (_, Self::Const(_)) => false,
72 (Self::Type(ref a), Self::Type(ref b)) => a == b,
73 }
74 }
75}
76impl PartialEq<Type> for OperandType {
77 fn eq(&self, other: &Type) -> bool {
78 match self {
79 Self::Type(a) => a == other,
80 _ => false,
81 }
82 }
83}
84impl PartialEq<Immediate> for OperandType {
85 fn eq(&self, other: &Immediate) -> bool {
86 match self {
87 Self::Const(a) => a.downcast_ref::<Immediate>().is_some_and(|a| a == other),
88 _ => false,
89 }
90 }
91}
92impl PartialEq<dyn AttributeValue> for OperandType {
93 fn eq(&self, other: &dyn AttributeValue) -> bool {
94 match self {
95 Self::Const(a) => a.as_ref() == other,
96 _ => false,
97 }
98 }
99}
100impl PartialEq<ValueRef> for OperandType {
101 fn eq(&self, other: &ValueRef) -> bool {
102 match self {
103 Self::Value(this) => this == other,
104 _ => false,
105 }
106 }
107}
108impl From<ValueRef> for OperandType {
109 fn from(value: ValueRef) -> Self {
110 Self::Value(value)
111 }
112}
113impl From<Type> for OperandType {
114 fn from(ty: Type) -> Self {
115 Self::Type(ty)
116 }
117}
118impl From<Immediate> for OperandType {
119 fn from(value: Immediate) -> Self {
120 Self::Const(Box::new(value))
121 }
122}
123impl From<Box<dyn AttributeValue>> for OperandType {
124 fn from(value: Box<dyn AttributeValue>) -> Self {
125 Self::Const(value)
126 }
127}
128
129#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct Operand {
138 word: SmallVec<[Type; 4]>,
148 operand: OperandType,
155}
156impl Default for Operand {
157 fn default() -> Self {
158 Self {
159 word: smallvec![Type::Felt],
160 operand: OperandType::Const(Box::new(Immediate::Felt(Felt::ZERO))),
161 }
162 }
163}
164impl PartialEq<ValueRef> for Operand {
165 #[inline(always)]
166 fn eq(&self, other: &ValueRef) -> bool {
167 self.operand.eq(other)
168 }
169}
170impl PartialEq<dyn AttributeValue> for Operand {
171 #[inline(always)]
172 fn eq(&self, other: &dyn AttributeValue) -> bool {
173 self.operand.eq(other)
174 }
175}
176impl PartialEq<Immediate> for Operand {
177 #[inline(always)]
178 fn eq(&self, other: &Immediate) -> bool {
179 self.operand.eq(other)
180 }
181}
182impl PartialEq<Immediate> for &Operand {
183 #[inline(always)]
184 fn eq(&self, other: &Immediate) -> bool {
185 self.operand.eq(other)
186 }
187}
188impl PartialEq<Type> for Operand {
189 #[inline(always)]
190 fn eq(&self, other: &Type) -> bool {
191 self.operand.eq(other)
192 }
193}
194impl PartialEq<Type> for &Operand {
195 #[inline(always)]
196 fn eq(&self, other: &Type) -> bool {
197 self.operand.eq(other)
198 }
199}
200impl From<Immediate> for Operand {
201 #[inline]
202 fn from(imm: Immediate) -> Self {
203 Self::new(imm.into())
204 }
205}
206impl From<u32> for Operand {
207 #[inline]
208 fn from(imm: u32) -> Self {
209 Self::new(Immediate::U32(imm).into())
210 }
211}
212impl TryFrom<&Operand> for ValueRef {
213 type Error = ();
214
215 fn try_from(operand: &Operand) -> Result<Self, Self::Error> {
216 match operand.operand {
217 OperandType::Value(value) => Ok(value),
218 _ => Err(()),
219 }
220 }
221}
222#[cfg(test)]
223impl TryFrom<&Operand> for Immediate {
224 type Error = ();
225
226 fn try_from(operand: &Operand) -> Result<Self, Self::Error> {
227 match &operand.operand {
228 OperandType::Const(value) => value.downcast_ref::<Immediate>().copied().ok_or(()),
229 _ => Err(()),
230 }
231 }
232}
233#[cfg(test)]
234impl TryFrom<&Operand> for Type {
235 type Error = ();
236
237 fn try_from(operand: &Operand) -> Result<Self, Self::Error> {
238 match operand.operand {
239 OperandType::Type(ref ty) => Ok(ty.clone()),
240 _ => Err(()),
241 }
242 }
243}
244#[cfg(test)]
245impl TryFrom<Operand> for Type {
246 type Error = ();
247
248 fn try_from(operand: Operand) -> Result<Self, Self::Error> {
249 match operand.operand {
250 OperandType::Type(ty) => Ok(ty),
251 _ => Err(()),
252 }
253 }
254}
255impl From<Type> for Operand {
256 #[inline]
257 fn from(ty: Type) -> Self {
258 Self::new(OperandType::Type(ty))
259 }
260}
261impl From<ValueRef> for Operand {
262 #[inline]
263 fn from(value: ValueRef) -> Self {
264 Self::new(OperandType::Value(value))
265 }
266}
267impl Operand {
268 pub fn new(operand: OperandType) -> Self {
269 let ty = operand.ty();
270 let mut word = ty.to_raw_parts().expect("invalid operand type");
271 assert!(!word.is_empty(), "invalid operand: must be a sized type");
272 assert!(word.len() <= 4, "invalid operand: must be smaller than or equal to a word");
273 if word.len() > 1 {
274 word.reverse();
275 }
276 Self { word, operand }
277 }
278
279 pub fn size(&self) -> usize {
281 self.word.len()
282 }
283
284 #[inline(always)]
286 pub fn value(&self) -> &OperandType {
287 &self.operand
288 }
289
290 #[inline]
292 pub fn as_value(&self) -> Option<ValueRef> {
293 self.try_into().ok()
294 }
295
296 #[inline]
298 pub fn ty(&self) -> Type {
299 self.operand.ty()
300 }
301}
302
303#[derive(Clone, PartialEq, Eq)]
316pub struct OperandStack {
317 stack: Vec<Operand>,
318}
319impl Default for OperandStack {
320 fn default() -> Self {
321 Self {
322 stack: Vec::with_capacity(16),
323 }
324 }
325}
326impl OperandStack {
327 pub fn rename(&mut self, n: usize, value: ValueRef) {
331 match &mut self[n].operand {
332 OperandType::Value(ref mut prev_value) => {
333 *prev_value = value;
334 }
335 prev => {
336 *prev = OperandType::Value(value);
337 }
338 }
339 }
340
341 pub fn find(&self, value: &ValueRef) -> Option<usize> {
345 self.stack.iter().rev().position(|v| v == value)
346 }
347
348 #[allow(unused)]
350 #[inline(always)]
351 pub fn is_empty(&self) -> bool {
352 self.stack.is_empty()
353 }
354
355 #[inline]
357 pub fn raw_len(&self) -> usize {
358 self.stack.iter().map(|operand| operand.size()).sum()
359 }
360
361 #[track_caller]
364 pub fn effective_index(&self, index: usize) -> usize {
365 assert!(
366 index < self.stack.len(),
367 "expected {} to be less than {}",
368 index,
369 self.stack.len()
370 );
371
372 self.stack.iter().rev().take(index).map(|o| o.size()).sum()
373 }
374
375 #[track_caller]
378 pub fn effective_index_inclusive(&self, index: usize) -> usize {
379 assert!(index < self.stack.len());
380
381 self.stack.iter().rev().take(index + 1).map(|o| o.size()).sum::<usize>() - 1
382 }
383
384 #[inline]
386 pub fn len(&self) -> usize {
387 self.stack.len()
388 }
389
390 #[inline]
392 pub fn peek(&self) -> Option<&Operand> {
393 self.stack.last()
394 }
395
396 #[inline]
398 pub fn push<V: Into<Operand>>(&mut self, value: V) {
399 self.stack.push(value.into());
400 }
401
402 #[inline]
404 #[track_caller]
405 pub fn pop(&mut self) -> Option<Operand> {
406 self.stack.pop()
407 }
408
409 #[allow(clippy::should_implement_trait)]
411 #[track_caller]
412 pub fn drop(&mut self) {
413 self.stack.pop().expect("operand stack is empty");
414 }
415
416 #[inline]
418 #[track_caller]
419 pub fn dropn(&mut self, n: usize) {
420 let len = self.stack.len();
421 assert!(n <= len, "unable to drop {} operands, operand stack only has {}", n, len);
422 self.stack.truncate(len - n);
423 }
424
425 #[track_caller]
429 pub fn dup(&mut self, n: usize) {
430 let operand = self[n].clone();
431 self.stack.push(operand);
432 }
433
434 #[track_caller]
440 pub fn swap(&mut self, n: usize) {
441 assert_ne!(n, 0, "invalid swap, index must be in the range 1..=15");
442 let len = self.stack.len();
443 assert!(
444 n < len,
445 "invalid operand stack index ({}), only {} operands are available",
446 n,
447 len
448 );
449 let a = len - 1;
450 let b = a - n;
451 self.stack.swap(a, b);
452 }
453
454 pub fn movup(&mut self, n: usize) {
460 assert_ne!(n, 0, "invalid move, index must be in the range 1..=15");
461 let len = self.stack.len();
462 assert!(
463 n < len,
464 "invalid operand stack index ({}), only {} operands are available",
465 n,
466 len
467 );
468 let mid = len - (n + 1);
470 let (_, r) = self.stack.split_at_mut(mid);
473 r.rotate_left(1);
474 }
475
476 pub fn movdn(&mut self, n: usize) {
482 assert_ne!(n, 0, "invalid move, index must be in the range 1..=15");
483 let len = self.stack.len();
484 assert!(
485 n < len,
486 "invalid operand stack index ({}), only {} operands are available",
487 n,
488 len
489 );
490 let mid = len - (n + 1);
492 let (_, r) = self.stack.split_at_mut(mid);
493 r.rotate_right(1);
496 }
497
498 #[allow(unused)]
499 #[inline(always)]
500 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Operand> {
501 self.stack.iter()
502 }
503}
504impl Index<usize> for OperandStack {
505 type Output = Operand;
506
507 #[track_caller]
508 fn index(&self, index: usize) -> &Self::Output {
509 let len = self.stack.len();
510 assert!(
511 index < len,
512 "invalid operand stack index ({}): only {} operands are available",
513 index,
514 len
515 );
516 let effective_len: usize = self.stack.iter().rev().take(index + 1).map(|o| o.size()).sum();
517 assert!(
518 effective_len <= 16,
519 "invalid operand stack index ({}): requires access to more than 16 elements, which is \
520 not supported in Miden",
521 index
522 );
523 &self.stack[len - index - 1]
524 }
525}
526impl IndexMut<usize> for OperandStack {
527 #[track_caller]
528 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
529 let len = self.stack.len();
530 assert!(
531 index < len,
532 "invalid operand stack index ({}): only {} elements are available",
533 index,
534 len
535 );
536 let effective_len: usize = self.stack.iter().rev().take(index + 1).map(|o| o.size()).sum();
537 assert!(
538 effective_len <= 16,
539 "invalid operand stack index ({}): requires access to more than 16 elements, which is \
540 not supported in Miden",
541 index
542 );
543 &mut self.stack[len - index - 1]
544 }
545}
546
547impl fmt::Debug for OperandStack {
548 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549 let mut builder = f.debug_list();
550 for (index, value) in self.stack.iter().rev().enumerate() {
551 builder.entry_with(|f| write!(f, "{index} => {value:?}"));
552 }
553 builder.finish()
554 }
555}
556
557#[cfg(test)]
558mod tests {
559 use alloc::rc::Rc;
560
561 use midenc_hir::{ArrayType, BuilderExt, Context, PointerType, StructType};
562
563 use super::*;
564
565 #[test]
566 fn operand_stack_homogenous_operand_sizes_test() {
567 let mut stack = OperandStack::default();
568
569 let zero = Immediate::U32(0);
570 let one = Immediate::U32(1);
571 let two = Immediate::U32(2);
572 let three = Immediate::U32(3);
573
574 #[inline]
575 #[allow(unused)]
576 fn as_imms(word: [Operand; 4]) -> [Immediate; 4] {
577 [
578 (&word[0]).try_into().unwrap(),
579 (&word[1]).try_into().unwrap(),
580 (&word[2]).try_into().unwrap(),
581 (&word[3]).try_into().unwrap(),
582 ]
583 }
584
585 #[inline]
586 fn as_imm(operand: Operand) -> Immediate {
587 (&operand).try_into().unwrap()
588 }
589
590 stack.push(zero);
592 stack.push(one);
593 stack.push(two);
594 stack.push(three);
595 assert_eq!(stack.len(), 4);
596 assert_eq!(stack[0], three);
597 assert_eq!(stack[1], two);
598 assert_eq!(stack[2], one);
599 assert_eq!(stack[3], zero);
600
601 assert_eq!(stack.peek().unwrap(), three);
603
604 stack.dup(0);
606 assert_eq!(stack.len(), 5);
607 assert_eq!(stack[0], three);
608 assert_eq!(stack[1], three);
609 assert_eq!(stack[2], two);
610 assert_eq!(stack[3], one);
611 assert_eq!(stack[4], zero);
612
613 stack.dup(3);
614 assert_eq!(stack.len(), 6);
615 assert_eq!(stack[0], one);
616 assert_eq!(stack[1], three);
617 assert_eq!(stack[2], three);
618 assert_eq!(stack[3], two);
619 assert_eq!(stack[4], one);
620 assert_eq!(stack[5], zero);
621
622 stack.drop();
624 assert_eq!(stack.len(), 5);
625 assert_eq!(stack[0], three);
626 assert_eq!(stack[1], three);
627 assert_eq!(stack[2], two);
628 assert_eq!(stack[3], one);
629 assert_eq!(stack[4], zero);
630
631 stack.swap(2);
633 assert_eq!(stack.len(), 5);
634 assert_eq!(stack[0], two);
635 assert_eq!(stack[1], three);
636 assert_eq!(stack[2], three);
637 assert_eq!(stack[3], one);
638 assert_eq!(stack[4], zero);
639
640 stack.swap(1);
641 assert_eq!(stack.len(), 5);
642 assert_eq!(stack[0], three);
643 assert_eq!(stack[1], two);
644 assert_eq!(stack[2], three);
645 assert_eq!(stack[3], one);
646 assert_eq!(stack[4], zero);
647
648 stack.movup(2);
650 assert_eq!(stack.len(), 5);
651 assert_eq!(stack[0], three);
652 assert_eq!(stack[1], three);
653 assert_eq!(stack[2], two);
654 assert_eq!(stack[3], one);
655 assert_eq!(stack[4], zero);
656
657 stack.movdn(3);
659 assert_eq!(stack.len(), 5);
660 assert_eq!(stack[0], three);
661 assert_eq!(stack[1], two);
662 assert_eq!(stack[2], one);
663 assert_eq!(stack[3], three);
664 assert_eq!(stack[4], zero);
665
666 assert_eq!(stack.pop().map(as_imm), Some(three));
668 assert_eq!(stack.len(), 4);
669 assert_eq!(stack[0], two);
670 assert_eq!(stack[1], one);
671 assert_eq!(stack[2], three);
672 assert_eq!(stack[3], zero);
673
674 stack.dropn(2);
676 assert_eq!(stack.len(), 2);
677 assert_eq!(stack[0], three);
678 assert_eq!(stack[1], zero);
679 }
680
681 #[test]
682 fn operand_stack_values_test() {
683 use midenc_dialect_hir::Load;
684
685 let mut stack = OperandStack::default();
686 let context = Rc::new(Context::default());
687
688 let ptr_u8 = Type::from(PointerType::new(Type::U8));
689 let array_u8 = Type::from(ArrayType::new(Type::U8, 4));
690 let struct_ty = Type::from(StructType::new([Type::U64, Type::U8]));
691 let block = context.create_block_with_params([ptr_u8, array_u8, Type::U32, struct_ty]);
692 let block = block.borrow();
693 let values = block.arguments();
694
695 let zero = values[0] as ValueRef;
696 let one = values[1] as ValueRef;
697 let two = values[2] as ValueRef;
698 let three = values[3] as ValueRef;
699
700 drop(block);
701
702 stack.push(zero);
704 stack.push(one);
705 stack.push(two);
706 stack.push(three);
707 assert_eq!(stack.len(), 4);
708 assert_eq!(stack.raw_len(), 6);
709
710 assert_eq!(stack.find(&zero), Some(3));
711 assert_eq!(stack.find(&one), Some(2));
712 assert_eq!(stack.find(&two), Some(1));
713 assert_eq!(stack.find(&three), Some(0));
714
715 stack.dup(0);
717 assert_eq!(stack.find(&three), Some(0));
718
719 stack.dup(3);
720 assert_eq!(stack.find(&one), Some(0));
721
722 stack.drop();
724 assert_eq!(stack.find(&one), Some(3));
725 assert_eq!(stack.find(&three), Some(0));
726 assert_eq!(stack[1], three);
727
728 stack.push(Immediate::Felt(Felt::ZERO));
730 stack.push(Immediate::Felt(Felt::ZERO));
731 stack.push(Immediate::Felt(Felt::ZERO));
732 stack.push(Immediate::Felt(Felt::ZERO));
733 assert_eq!(stack.find(&one), Some(7));
734 assert_eq!(stack.find(&three), Some(4));
735
736 let four = {
738 let mut builder = midenc_hir::OpBuilder::new(context.clone());
739 let load_builder = builder.create::<Load, _>(Default::default());
740 let load = load_builder(zero).unwrap();
741 load.borrow().result().as_value_ref()
742 };
743 stack.rename(1, four);
744 assert_eq!(stack.find(&four), Some(1));
745 assert_eq!(stack.find(&three), Some(4));
746
747 let top = stack.pop().unwrap();
749 assert_eq!((&top).try_into(), Ok(Immediate::Felt(Felt::ZERO)));
750 assert_eq!(stack.find(&four), Some(0));
751 assert_eq!(stack[1], Immediate::Felt(Felt::ZERO));
752 assert_eq!(stack[2], Immediate::Felt(Felt::ZERO));
753 assert_eq!(stack.find(&three), Some(3));
754
755 stack.dropn(3);
757 assert_eq!(stack.find(&four), None);
758 assert_eq!(stack.find(&three), Some(0));
759 assert_eq!(stack[1], three);
760 assert_eq!(stack.find(&two), Some(2));
761 assert_eq!(stack.find(&one), Some(3));
762 assert_eq!(stack.find(&zero), Some(4));
763
764 stack.swap(3);
766 assert_eq!(stack.find(&one), Some(0));
767 assert_eq!(stack.find(&three), Some(1));
768 assert_eq!(stack.find(&two), Some(2));
769 assert_eq!(stack[3], three);
770
771 stack.swap(1);
772 assert_eq!(stack.find(&three), Some(0));
773 assert_eq!(stack.find(&one), Some(1));
774 assert_eq!(stack.find(&two), Some(2));
775 assert_eq!(stack.find(&zero), Some(4));
776
777 stack.movup(2);
779 assert_eq!(stack.find(&two), Some(0));
780 assert_eq!(stack.find(&three), Some(1));
781 assert_eq!(stack.find(&one), Some(2));
782 assert_eq!(stack.find(&zero), Some(4));
783
784 stack.movdn(3);
786 assert_eq!(stack.find(&three), Some(0));
787 assert_eq!(stack.find(&one), Some(1));
788 assert_eq!(stack[2], three);
789 assert_eq!(stack.find(&two), Some(3));
790 assert_eq!(stack.find(&zero), Some(4));
791 }
792
793 #[test]
794 fn operand_stack_heterogenous_operand_sizes_test() {
795 let mut stack = OperandStack::default();
796
797 let zero = Immediate::U32(0);
798 let one = Immediate::U32(1);
799 let two = Type::U64;
800 let three = Type::U64;
801 let struct_a = Type::from(StructType::new([
802 Type::from(PointerType::new(Type::U8)),
803 Type::U16,
804 Type::U32,
805 ]));
806
807 stack.push(zero);
809 stack.push(one);
810 stack.push(two.clone());
811 stack.push(three.clone());
812 stack.push(struct_a.clone());
813 assert_eq!(stack.len(), 5);
814 assert_eq!(stack.raw_len(), 9);
815 assert_eq!(stack[0], struct_a);
816 assert_eq!(stack[1], three);
817 assert_eq!(stack[2], two);
818 assert_eq!(stack[3], one);
819 assert_eq!(stack[4], zero);
820
821 assert_eq!(stack.peek().unwrap(), struct_a);
823
824 stack.dup(0);
826 assert_eq!(stack.len(), 6);
827 assert_eq!(stack.raw_len(), 12);
828 assert_eq!(stack[0], struct_a);
829 assert_eq!(stack[1], struct_a);
830 assert_eq!(stack[2], three);
831 assert_eq!(stack[3], two);
832 assert_eq!(stack[4], one);
833 assert_eq!(stack[5], zero);
834 assert_eq!(stack.effective_index(3), 8);
835
836 stack.dup(3);
837 assert_eq!(stack.len(), 7);
838 assert_eq!(stack.raw_len(), 14);
839 assert_eq!(stack[0], two);
840 assert_eq!(stack[1], struct_a);
841 assert_eq!(stack[2], struct_a);
842
843 stack.drop();
845 assert_eq!(stack.len(), 6);
846 assert_eq!(stack.raw_len(), 12);
847 assert_eq!(stack[0], struct_a);
848 assert_eq!(stack[1], struct_a);
849 assert_eq!(stack[2], three);
850 assert_eq!(stack[3], two);
851 assert_eq!(stack[4], one);
852 assert_eq!(stack[5], zero);
853
854 stack.swap(2);
856 assert_eq!(stack.len(), 6);
857 assert_eq!(stack.raw_len(), 12);
858 assert_eq!(stack[0], three);
859 assert_eq!(stack[1], struct_a);
860 assert_eq!(stack[2], struct_a);
861 assert_eq!(stack[3], two);
862 assert_eq!(stack[4], one);
863
864 stack.swap(1);
865 assert_eq!(stack.len(), 6);
866 assert_eq!(stack.raw_len(), 12);
867 assert_eq!(stack[0], struct_a);
868 assert_eq!(stack[1], three);
869 assert_eq!(stack[2], struct_a);
870 assert_eq!(stack[3], two);
871 assert_eq!(stack[4], one);
872 assert_eq!(stack[5], zero);
873
874 stack.movup(4);
876 assert_eq!(stack.len(), 6);
877 assert_eq!(stack.raw_len(), 12);
878 assert_eq!(stack[0], one);
879 assert_eq!(stack[1], struct_a);
880 assert_eq!(stack[2], three);
881 assert_eq!(stack[3], struct_a);
882 assert_eq!(stack[4], two);
883 assert_eq!(stack[5], zero);
884
885 stack.movdn(3);
887 assert_eq!(stack.len(), 6);
888 assert_eq!(stack.raw_len(), 12);
889 assert_eq!(stack[0], struct_a);
890 assert_eq!(stack[1], three);
891 assert_eq!(stack[2], struct_a);
892 assert_eq!(stack[3], one);
893 assert_eq!(stack[4], two);
894
895 let operand: Type = stack.pop().unwrap().try_into().unwrap();
897 assert_eq!(operand, struct_a);
898 assert_eq!(stack.len(), 5);
899 assert_eq!(stack.raw_len(), 9);
900 assert_eq!(stack[0], three);
901 assert_eq!(stack[1], struct_a);
902 assert_eq!(stack[2], one);
903 assert_eq!(stack[3], two);
904
905 stack.dropn(2);
907 assert_eq!(stack.len(), 3);
908 assert_eq!(stack.raw_len(), 4);
909 assert_eq!(stack[0], one);
910 assert_eq!(stack[1], two);
911 assert_eq!(stack[2], zero);
912 }
913}