use crate::{core::TrapCode, index::*, *};
use ::core::{
num::{NonZeroI32, NonZeroI64, NonZeroU32, NonZeroU64},
slice,
};
use std::{boxed::Box, vec::Vec};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct InstrSequence {
instrs: Vec<Instruction>,
}
impl From<InstrSequence> for Vec<Instruction> {
fn from(sequence: InstrSequence) -> Self {
sequence.into_vec()
}
}
impl From<InstrSequence> for Box<[Instruction]> {
fn from(sequence: InstrSequence) -> Self {
sequence.into_boxed_slice()
}
}
impl InstrSequence {
pub fn into_vec(self) -> Vec<Instruction> {
self.instrs
}
pub fn into_boxed_slice(self) -> Box<[Instruction]> {
self.instrs.into_boxed_slice()
}
pub fn clear(&mut self) {
self.instrs.clear()
}
pub fn as_slice(&self) -> &[Instruction] {
&self.instrs[..]
}
pub fn as_slice_mut(&mut self) -> &mut [Instruction] {
&mut self.instrs[..]
}
#[inline]
pub fn len(&self) -> usize {
self.instrs.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn get(&self, instr: Instr) -> Option<Instruction> {
self.instrs.get(instr.into_usize()).copied()
}
#[inline]
pub fn get_mut(&mut self, instr: Instr) -> Option<&mut Instruction> {
self.instrs.get_mut(instr.into_usize())
}
pub fn iter(&self) -> InstrIter {
InstrIter::new(self)
}
pub fn iter_mut(&mut self) -> InstrIterMut {
InstrIterMut::new(self)
}
pub fn pop(&mut self) -> Option<Instruction> {
self.instrs.pop()
}
}
impl<'a> IntoIterator for &'a InstrSequence {
type Item = &'a Instruction;
type IntoIter = InstrIter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut InstrSequence {
type Item = &'a mut Instruction;
type IntoIter = InstrIterMut<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
macro_rules! define_builder {
(
$(
$( #[doc = $doc:literal] )*
#[snake_name($snake_name:ident)]
$name:ident
$(
{
$(
$( #[$field_docs:meta] )* $(@)?
$field_name:ident: $field_ty:ty
),*
$(,)?
}
)?
),* $(,)?
) => {
impl InstrSequence {
$(
#[doc = concat!("Pushes an [`Instruction::", stringify!($name), "`].")]
pub fn $snake_name(
&mut self,
$( $( $field_name: impl Into<$field_ty> ),* )?
) -> Instr {
let pos = Instr::from_usize(self.instrs.len());
self.instrs.push(Instruction::$name {
$( $( $field_name: $field_name.into() ),* )?
});
pos
}
)*
}
};
}
for_each_op!(define_builder);
#[derive(Debug)]
pub struct InstrIter<'a> {
instrs: slice::Iter<'a, Instruction>,
}
impl<'a> InstrIter<'a> {
fn new(builder: &'a InstrSequence) -> Self {
Self {
instrs: builder.instrs.iter(),
}
}
}
impl<'a> Iterator for InstrIter<'a> {
type Item = &'a Instruction;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.instrs.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.instrs.size_hint()
}
}
impl DoubleEndedIterator for InstrIter<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.instrs.next_back()
}
}
impl ExactSizeIterator for InstrIter<'_> {}
#[derive(Debug)]
pub struct InstrIterMut<'a> {
instrs: slice::IterMut<'a, Instruction>,
}
impl<'a> InstrIterMut<'a> {
fn new(builder: &'a mut InstrSequence) -> Self {
Self {
instrs: builder.instrs.iter_mut(),
}
}
}
impl<'a> Iterator for InstrIterMut<'a> {
type Item = &'a mut Instruction;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.instrs.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.instrs.size_hint()
}
}
impl DoubleEndedIterator for InstrIterMut<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.instrs.next_back()
}
}
impl ExactSizeIterator for InstrIterMut<'_> {}