1use crate::limits::{MAX_WASM_CATCHES, MAX_WASM_HANDLERS};
17use crate::prelude::*;
18use crate::{BinaryReader, BinaryReaderError, FromReader, Result, ValType};
19use core::{fmt, mem};
20
21#[derive(Debug, Copy, Clone, PartialEq, Eq)]
23pub enum BlockType {
24 Empty,
26 Type(ValType),
28 FuncType(u32),
32}
33
34#[derive(Copy, Clone, Debug, PartialEq, Eq)]
36pub enum FrameKind {
37 Block,
39 If,
41 Else,
43 Loop,
45 TryTable,
51 LegacyTry,
57 LegacyCatch,
63 LegacyCatchAll,
69}
70
71#[derive(Debug, Copy, Clone, Eq, PartialEq)]
73pub struct MemArg {
74 pub align: u8,
76 pub max_align: u8,
82 pub offset: u64,
89 pub memory: u32,
95}
96
97#[derive(Clone)]
99pub struct BrTable<'a> {
100 pub(crate) reader: crate::BinaryReader<'a>,
101 pub(crate) cnt: u32,
102 pub(crate) default: u32,
103}
104
105impl PartialEq<Self> for BrTable<'_> {
106 fn eq(&self, other: &Self) -> bool {
107 self.cnt == other.cnt
108 && self.default == other.default
109 && self.reader.remaining_buffer() == other.reader.remaining_buffer()
110 }
111}
112
113impl Eq for BrTable<'_> {}
114
115impl<'a> BrTable<'a> {
116 pub fn len(&self) -> u32 {
119 self.cnt
120 }
121
122 pub fn is_empty(&self) -> bool {
124 self.len() == 0
125 }
126
127 pub fn default(&self) -> u32 {
129 self.default
130 }
131
132 pub fn targets(&self) -> BrTableTargets<'_> {
153 BrTableTargets {
154 reader: self.reader.clone(),
155 remaining: self.cnt,
156 }
157 }
158}
159
160pub struct BrTableTargets<'a> {
168 reader: crate::BinaryReader<'a>,
169 remaining: u32,
170}
171
172impl<'a> Iterator for BrTableTargets<'a> {
173 type Item = Result<u32>;
174
175 fn size_hint(&self) -> (usize, Option<usize>) {
176 let remaining = usize::try_from(self.remaining).unwrap_or_else(|error| {
177 panic!("could not convert remaining `u32` into `usize`: {error}")
178 });
179 (remaining, Some(remaining))
180 }
181
182 fn next(&mut self) -> Option<Self::Item> {
183 if self.remaining == 0 {
184 if !self.reader.eof() {
185 return Some(Err(BinaryReaderError::new(
186 "trailing data in br_table",
187 self.reader.original_position(),
188 )));
189 }
190 return None;
191 }
192 self.remaining -= 1;
193 Some(self.reader.read_var_u32())
194 }
195}
196
197impl fmt::Debug for BrTable<'_> {
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 let mut f = f.debug_struct("BrTable");
200 f.field("count", &self.cnt);
201 f.field("default", &self.default);
202 match self.targets().collect::<Result<Vec<_>>>() {
203 Ok(targets) => {
204 f.field("targets", &targets);
205 }
206 Err(_) => {
207 f.field("reader", &self.reader);
208 }
209 }
210 f.finish()
211 }
212}
213
214#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
219pub struct Ieee32(pub(crate) u32);
220
221impl Ieee32 {
222 pub fn bits(self) -> u32 {
224 self.0
225 }
226}
227
228impl From<f32> for Ieee32 {
229 fn from(value: f32) -> Self {
230 Ieee32 {
231 0: u32::from_le_bytes(value.to_le_bytes()),
232 }
233 }
234}
235
236impl From<Ieee32> for f32 {
237 fn from(bits: Ieee32) -> f32 {
238 f32::from_bits(bits.bits())
239 }
240}
241
242#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
247pub struct Ieee64(pub(crate) u64);
248
249impl Ieee64 {
250 pub fn bits(self) -> u64 {
252 self.0
253 }
254}
255
256impl From<f64> for Ieee64 {
257 fn from(value: f64) -> Self {
258 Ieee64 {
259 0: u64::from_le_bytes(value.to_le_bytes()),
260 }
261 }
262}
263
264impl From<Ieee64> for f64 {
265 fn from(bits: Ieee64) -> f64 {
266 f64::from_bits(bits.bits())
267 }
268}
269
270#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
272pub struct V128(pub(crate) [u8; 16]);
273
274impl V128 {
275 pub fn bytes(&self) -> &[u8; 16] {
277 &self.0
278 }
279
280 pub fn i128(&self) -> i128 {
282 i128::from_le_bytes(self.0)
283 }
284}
285
286impl From<V128> for i128 {
287 fn from(bits: V128) -> i128 {
288 bits.i128()
289 }
290}
291
292impl From<V128> for u128 {
293 fn from(bits: V128) -> u128 {
294 u128::from_le_bytes(bits.0)
295 }
296}
297
298impl From<i128> for V128 {
299 fn from(value: i128) -> Self {
300 V128(i128::to_le_bytes(value))
301 }
302}
303
304impl From<u128> for V128 {
305 fn from(value: u128) -> Self {
306 V128(u128::to_le_bytes(value))
307 }
308}
309
310#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
318pub enum Ordering {
319 AcqRel,
323 SeqCst,
326}
327
328macro_rules! define_operator {
329 ($(@$proposal:ident $op:ident $({ $($payload:tt)* })? => $visit:ident ($($ann:tt)*))*) => {
330 #[derive(Debug, Clone, Eq, PartialEq)]
334 #[allow(missing_docs)]
335 #[non_exhaustive]
336 pub enum Operator<'a> {
337 $(
338 $op $({ $($payload)* })?,
339 )*
340 }
341 }
342}
343crate::for_each_operator!(define_operator);
344
345pub trait FrameStack {
352 fn current_frame(&self) -> Option<FrameKind>;
354}
355
356#[derive(Debug, Default, Clone)]
358pub struct ControlStack {
359 frames: Vec<FrameKind>,
361 top: Option<FrameKind>,
363}
364
365impl ControlStack {
366 pub fn clear(&mut self) {
368 self.frames.clear();
369 self.top = None;
370 }
371
372 #[inline]
374 pub fn is_empty(&self) -> bool {
375 self.top.is_none()
376 }
377
378 #[inline]
380 pub fn push(&mut self, frame: FrameKind) {
381 if let Some(old_top) = self.top.replace(frame) {
382 self.frames.push(old_top);
383 }
384 }
385
386 pub fn pop(&mut self) -> Option<FrameKind> {
388 mem::replace(&mut self.top, self.frames.pop())
389 }
390
391 #[inline]
393 pub fn last(&self) -> Option<FrameKind> {
394 self.top
395 }
396}
397
398struct FrameStackAdapter<'a, T> {
400 stack: &'a mut ControlStack,
401 visitor: &'a mut T,
402}
403
404impl<T> FrameStack for FrameStackAdapter<'_, T> {
405 fn current_frame(&self) -> Option<FrameKind> {
406 self.stack.last()
407 }
408}
409
410struct SingleFrameAdapter<'a, T> {
411 current_frame: FrameKind,
412 visitor: &'a mut T,
413}
414
415impl<T> FrameStack for SingleFrameAdapter<'_, T> {
416 fn current_frame(&self) -> Option<FrameKind> {
417 Some(self.current_frame)
418 }
419}
420
421#[derive(Clone)]
426pub struct OperatorsReader<'a> {
427 reader: BinaryReader<'a>,
428 stack: ControlStack,
429}
430
431#[derive(Default)]
438pub struct OperatorsReaderAllocations(ControlStack);
439
440impl<'a> OperatorsReader<'a> {
441 pub fn new(reader: BinaryReader<'a>) -> Self {
449 Self::new_with_allocs(reader, Default::default())
450 }
451
452 pub fn new_with_allocs(
456 reader: BinaryReader<'a>,
457 mut allocs: OperatorsReaderAllocations,
458 ) -> Self {
459 allocs.0.clear();
460 allocs.0.push(FrameKind::Block);
461 Self {
462 reader,
463 stack: allocs.0,
464 }
465 }
466
467 pub fn get_binary_reader(&self) -> BinaryReader<'a> {
469 self.reader.clone()
470 }
471
472 pub fn eof(&self) -> bool {
474 self.reader.eof()
475 }
476
477 pub fn original_position(&self) -> usize {
479 self.reader.original_position()
480 }
481
482 pub fn is_end_then_eof(&self) -> bool {
485 self.reader.is_end_then_eof()
486 }
487
488 pub fn into_allocations(self) -> OperatorsReaderAllocations {
495 OperatorsReaderAllocations(self.stack)
496 }
497
498 pub fn read(&mut self) -> Result<Operator<'a>> {
505 self.visit_operator(&mut OperatorFactory)
506 }
507
508 pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
555 where
556 T: VisitOperator<'a>,
557 {
558 self.reader.visit_operator(&mut FrameStackAdapter {
559 stack: &mut self.stack,
560 visitor,
561 })
562 }
563
564 pub fn read_with_offset(&mut self) -> Result<(Operator<'a>, usize)> {
566 let pos = self.reader.original_position();
567 Ok((self.read()?, pos))
568 }
569
570 pub fn into_iter_with_offsets(self) -> OperatorsIteratorWithOffsets<'a> {
572 OperatorsIteratorWithOffsets {
573 reader: self,
574 err: false,
575 }
576 }
577
578 pub(crate) fn skip_const_expr(&mut self) -> Result<()> {
579 loop {
581 if let Operator::End = self.read()? {
582 if self.current_frame().is_some() {
583 bail!(
584 self.original_position(),
585 "control frames remain at end of expression"
586 );
587 }
588 return Ok(());
589 }
590 }
591 }
592
593 pub fn finish(&self) -> Result<()> {
599 self.reader.finish_expression(self)
600 }
601}
602
603impl<'a> FrameStack for OperatorsReader<'a> {
604 fn current_frame(&self) -> Option<FrameKind> {
605 self.stack.last()
606 }
607}
608
609impl<'a> IntoIterator for OperatorsReader<'a> {
610 type Item = Result<Operator<'a>>;
611 type IntoIter = OperatorsIterator<'a>;
612
613 fn into_iter(self) -> Self::IntoIter {
634 OperatorsIterator {
635 reader: self,
636 err: false,
637 }
638 }
639}
640
641pub struct OperatorsIterator<'a> {
643 reader: OperatorsReader<'a>,
644 err: bool,
645}
646
647impl<'a> OperatorsIterator<'a> {
648 pub fn into_allocations(self) -> OperatorsReaderAllocations {
651 self.reader.into_allocations()
652 }
653}
654
655impl<'a> Iterator for OperatorsIterator<'a> {
656 type Item = Result<Operator<'a>>;
657
658 fn next(&mut self) -> Option<Self::Item> {
659 if self.err || self.reader.eof() {
660 return None;
661 }
662 let result = self.reader.read();
663 self.err = result.is_err();
664 Some(result)
665 }
666}
667
668pub struct OperatorsIteratorWithOffsets<'a> {
670 reader: OperatorsReader<'a>,
671 err: bool,
672}
673
674impl<'a> OperatorsIteratorWithOffsets<'a> {
675 pub fn into_allocations(self) -> OperatorsReaderAllocations {
678 self.reader.into_allocations()
679 }
680}
681
682impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> {
683 type Item = Result<(Operator<'a>, usize)>;
684
685 fn next(&mut self) -> Option<Self::Item> {
706 if self.err || self.reader.eof() {
707 return None;
708 }
709 let result = self.reader.read_with_offset();
710 self.err = result.is_err();
711 Some(result)
712 }
713}
714
715macro_rules! define_visit_operator {
716 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
717 $(
718 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output;
719 )*
720 }
721}
722
723#[allow(missing_docs)]
725pub trait VisitOperator<'a> {
726 type Output: 'a;
728
729 fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
738 macro_rules! visit_operator {
739 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {{
740 match op {
741 $( Operator::$op $({ $($arg),* })? => self.$visit($($($arg.clone()),*)?), )*
742 #[cfg(feature = "simd")]
743 other => visit_simd_operator(self, other),
744 }
745 }};
746 }
747 crate::for_each_visit_operator!(visit_operator)
748 }
749
750 #[cfg(feature = "simd")]
786 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
787 None
788 }
789
790 crate::for_each_visit_operator!(define_visit_operator);
791}
792
793#[cfg(feature = "simd")]
795fn visit_simd_operator<'a, V>(visitor: &mut V, op: &Operator<'a>) -> V::Output
796where
797 V: VisitOperator<'a> + ?Sized,
798{
799 let Some(simd_visitor) = visitor.simd_visitor() else {
800 panic!("missing SIMD visitor to visit operator: {op:?}")
801 };
802 macro_rules! visit_simd_operator {
803 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {{
804 match op {
805 $( Operator::$op $({ $($arg),* })? => simd_visitor.$visit($($($arg.clone()),*)?), )*
806 unexpected => unreachable!("unexpected non-SIMD operator: {unexpected:?}"),
807 }
808 }};
809 }
810 crate::for_each_visit_simd_operator!(visit_simd_operator)
811}
812
813#[cfg(feature = "simd")]
815#[allow(missing_docs)]
816pub trait VisitSimdOperator<'a>: VisitOperator<'a> {
817 crate::for_each_visit_simd_operator!(define_visit_operator);
818}
819
820macro_rules! define_visit_operator_delegate {
821 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
822 $(
823 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
824 V::$visit(&mut *self, $($($arg),*)?)
825 }
826 )*
827 }
828}
829
830impl<'a, 'b, V: VisitOperator<'a> + ?Sized> VisitOperator<'a> for &'b mut V {
831 type Output = V::Output;
832 fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
833 V::visit_operator(*self, op)
834 }
835 #[cfg(feature = "simd")]
836 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = V::Output>> {
837 V::simd_visitor(*self)
838 }
839 crate::for_each_visit_operator!(define_visit_operator_delegate);
840}
841
842#[cfg(feature = "simd")]
843impl<'a, 'b, V: VisitSimdOperator<'a> + ?Sized> VisitSimdOperator<'a> for &'b mut V {
844 crate::for_each_visit_simd_operator!(define_visit_operator_delegate);
845}
846
847impl<'a, V: VisitOperator<'a> + ?Sized> VisitOperator<'a> for Box<V> {
848 type Output = V::Output;
849 fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
850 V::visit_operator(&mut *self, op)
851 }
852 #[cfg(feature = "simd")]
853 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = V::Output>> {
854 V::simd_visitor(&mut *self)
855 }
856 crate::for_each_visit_operator!(define_visit_operator_delegate);
857}
858
859#[cfg(feature = "simd")]
860impl<'a, V: VisitSimdOperator<'a> + ?Sized> VisitSimdOperator<'a> for Box<V> {
861 crate::for_each_visit_simd_operator!(define_visit_operator_delegate);
862}
863
864#[derive(Clone, Debug, Eq, PartialEq)]
866pub struct TryTable {
867 pub ty: BlockType,
869 pub catches: Vec<Catch>,
871}
872
873#[derive(Copy, Clone, Debug, Eq, PartialEq)]
875#[allow(missing_docs)]
876pub enum Catch {
877 One { tag: u32, label: u32 },
879 OneRef { tag: u32, label: u32 },
881 All { label: u32 },
883 AllRef { label: u32 },
885}
886
887impl<'a> FromReader<'a> for TryTable {
888 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
889 let ty = reader.read_block_type()?;
890 let catches = reader
891 .read_iter(MAX_WASM_CATCHES, "catches")?
892 .collect::<Result<_>>()?;
893 Ok(TryTable { ty, catches })
894 }
895}
896
897impl<'a> FromReader<'a> for Catch {
898 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
899 Ok(match reader.read_u8()? {
900 0x00 => Catch::One {
901 tag: reader.read_var_u32()?,
902 label: reader.read_var_u32()?,
903 },
904 0x01 => Catch::OneRef {
905 tag: reader.read_var_u32()?,
906 label: reader.read_var_u32()?,
907 },
908 0x02 => Catch::All {
909 label: reader.read_var_u32()?,
910 },
911 0x03 => Catch::AllRef {
912 label: reader.read_var_u32()?,
913 },
914
915 x => return reader.invalid_leading_byte(x, "catch"),
916 })
917 }
918}
919
920#[derive(Clone, Debug, Eq, PartialEq)]
923pub struct ResumeTable {
924 pub handlers: Vec<Handle>,
927}
928
929#[derive(Copy, Clone, Debug, Eq, PartialEq)]
931#[allow(missing_docs)]
932pub enum Handle {
933 OnLabel { tag: u32, label: u32 },
935 OnSwitch { tag: u32 },
937}
938
939impl ResumeTable {
940 pub fn len(&self) -> usize {
942 self.handlers.len()
943 }
944}
945
946impl<'a> FromReader<'a> for ResumeTable {
947 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
948 let handlers = reader
949 .read_iter(MAX_WASM_HANDLERS, "resume table")?
950 .collect::<Result<_>>()?;
951 let table = ResumeTable { handlers };
952 Ok(table)
953 }
954}
955
956impl<'a> FromReader<'a> for Handle {
957 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
958 Ok(match reader.read_u8()? {
959 0x00 => Handle::OnLabel {
960 tag: reader.read_var_u32()?,
961 label: reader.read_var_u32()?,
962 },
963 0x01 => Handle::OnSwitch {
964 tag: reader.read_var_u32()?,
965 },
966 x => return reader.invalid_leading_byte(x, "on clause"),
967 })
968 }
969}
970
971struct OperatorFactory;
973
974macro_rules! define_visit_operator {
975 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
976 $(
977 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Operator<'a> {
978 Operator::$op $({ $($arg),* })?
979 }
980 )*
981 }
982}
983
984impl<'a> VisitOperator<'a> for OperatorFactory {
985 type Output = Operator<'a>;
986
987 #[cfg(feature = "simd")]
988 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
989 Some(self)
990 }
991
992 crate::for_each_visit_operator!(define_visit_operator);
993}
994
995#[cfg(feature = "simd")]
996impl<'a> VisitSimdOperator<'a> for OperatorFactory {
997 crate::for_each_visit_simd_operator!(define_visit_operator);
998}
999
1000macro_rules! define_visit_operator_stack_adapter {
1001 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1002 $(
1003 fn $visit(&mut self $($(,$arg: $argty)*)?) -> T::Output {
1004 define_visit_operator_stack_adapter!(@visit self $visit $($($arg,)*)?)
1005 }
1006 )*
1007 };
1008
1009 (@visit $self:ident visit_block $($rest:tt)*) => {{
1010 $self.stack.push(FrameKind::Block);
1011 $self.visitor.visit_block( $($rest)* )
1012 }};
1013
1014 (@visit $self:ident visit_loop $($rest:tt)*) => {{
1015 $self.stack.push(FrameKind::Loop);
1016 $self.visitor.visit_loop( $($rest)* )
1017 }};
1018
1019 (@visit $self:ident visit_if $($rest:tt)*) => {{
1020 $self.stack.push(FrameKind::If);
1021 $self.visitor.visit_if( $($rest)* )
1022 }};
1023
1024 (@visit $self:ident visit_else $($rest:tt)*) => {{
1025 $self.stack.pop();
1026 $self.stack.push(FrameKind::Else);
1027 $self.visitor.visit_else( $($rest)* )
1028 }};
1029
1030 (@visit $self:ident visit_try $($rest:tt)*) => {{
1031 $self.stack.push(FrameKind::LegacyTry);
1032 $self.visitor.visit_try( $($rest)* )
1033 }};
1034
1035 (@visit $self:ident visit_catch $($rest:tt)*) => {{
1036 $self.stack.pop();
1037 $self.stack.push(FrameKind::LegacyCatch);
1038 $self.visitor.visit_catch( $($rest)* )
1039 }};
1040
1041 (@visit $self:ident visit_catch_all $($rest:tt)*) => {{
1042 $self.stack.pop();
1043 $self.stack.push(FrameKind::LegacyCatchAll);
1044 $self.visitor.visit_catch_all( $($rest)* )
1045 }};
1046
1047 (@visit $self:ident visit_try_table $($rest:tt)*) => {{
1048 $self.stack.push(FrameKind::TryTable);
1049 $self.visitor.visit_try_table( $($rest)* )
1050 }};
1051
1052 (@visit $self:ident visit_delegate $($rest:tt)*) => {{
1053 $self.stack.pop();
1054 $self.visitor.visit_delegate( $($rest)* )
1055 }};
1056
1057 (@visit $self:ident visit_end $($rest:tt)*) => {{
1058 $self.stack.pop();
1059 $self.visitor.visit_end( $($rest)* )
1060 }};
1061
1062 (@visit $self:ident $visit:ident $($rest:tt)*) => {
1063 $self.visitor.$visit( $($rest)* )
1064 };
1065}
1066
1067impl<'a, T: VisitOperator<'a>> VisitOperator<'a> for FrameStackAdapter<'_, T> {
1068 type Output = T::Output;
1069
1070 #[cfg(feature = "simd")]
1071 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
1072 self.visitor.simd_visitor()
1073 }
1074
1075 crate::for_each_visit_operator!(define_visit_operator_stack_adapter);
1076}
1077
1078macro_rules! define_passthrough_visit_operator {
1079 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1080 $(
1081 fn $visit(&mut self $($(,$arg: $argty)*)?) -> T::Output {
1082 self.visitor.$visit( $($($arg,)*)? )
1083 }
1084 )*
1085 };
1086}
1087
1088impl<'a, T: VisitOperator<'a>> VisitOperator<'a> for SingleFrameAdapter<'_, T> {
1089 type Output = T::Output;
1090
1091 #[cfg(feature = "simd")]
1092 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
1093 self.visitor.simd_visitor()
1094 }
1095
1096 crate::for_each_visit_operator!(define_passthrough_visit_operator);
1097}
1098
1099impl<'a> BinaryReader<'a> {
1100 pub fn peek_operator<T: FrameStack>(&self, stack: &T) -> Result<Operator<'a>> {
1107 self.clone().visit_operator(&mut SingleFrameAdapter {
1108 current_frame: stack.current_frame().ok_or_else(|| {
1109 format_err!(
1110 self.original_position(),
1111 "operators remaining after end of function body or expression"
1112 )
1113 })?,
1114 visitor: &mut OperatorFactory,
1115 })
1116 }
1117}