use std::borrow::{Borrow, BorrowMut};
use std::mem;
use std::ops::{Deref, DerefMut, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
use log::warn;
pub use crate::errors::StackError as Error;
use crate::value::Value;
#[derive(Debug, Clone)]
pub enum StackSlot {
Value(Value),
PopMarker,
}
impl StackSlot {
#[inline]
fn is_value(&self) -> bool { matches!(self, Self::Value(_)) }
#[inline]
fn is_pop_marker(&self) -> bool { matches!(self, Self::PopMarker) }
#[inline]
fn into_value(self) -> Value {
if let Self::Value(value) = self {
value
} else {
panic!("Cannot get '{self:?}' as a Value");
}
}
#[inline]
fn as_value(&self) -> &Value {
if let Self::Value(value) = self {
value
} else {
panic!("Cannot get '{self:?}' as a Value");
}
}
#[inline]
fn as_value_mut(&mut self) -> &mut Value {
if let Self::Value(value) = self {
value
} else {
panic!("Cannot get '{self:?}' as a Value");
}
}
}
impl From<&Value> for StackSlot {
#[inline]
fn from(value: &Value) -> Self { Self::from(value.clone()) }
}
impl From<Value> for StackSlot {
#[inline]
fn from(value: Value) -> Self { Self::Value(value) }
}
#[derive(Debug)]
pub struct StackSlice {
slots: [StackSlot],
}
impl StackSlice {
#[inline]
unsafe fn from_slots_unchecked(slots: &[StackSlot]) -> &Self { mem::transmute(slots) }
#[inline]
unsafe fn from_slots_unchecked_mut(slots: &mut [StackSlot]) -> &mut Self { mem::transmute(slots) }
pub fn peek(&self) -> Option<&Value> {
for v in self.slots.iter().rev() {
if let StackSlot::Value(v) = v {
return Some(v);
}
}
None
}
#[inline]
pub fn len(&self) -> usize { self.slots.len() }
#[inline]
pub fn is_empty(&self) -> bool { self.len() == 0 }
#[inline]
pub fn iter(&mut self) -> impl Iterator<Item = &Value> {
self.slots.iter().filter_map(|s: &StackSlot| if s.is_value() { Some(s.as_value()) } else { None })
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Value> {
self.slots.iter_mut().filter_map(|s: &mut StackSlot| if s.is_value() { Some(s.as_value_mut()) } else { None })
}
}
impl Index<usize> for StackSlice {
type Output = Value;
#[inline]
fn index(&self, index: usize) -> &Self::Output { self.slots[index].as_value() }
}
impl Index<Range<usize>> for StackSlice {
type Output = StackSlice;
fn index(&self, index: Range<usize>) -> &Self::Output {
if index.start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked(&[]) };
}
let end: usize = if index.end <= self.slots.len() { index.end } else { self.slots.len() };
unsafe { Self::from_slots_unchecked(&self.slots[index.start..end]) }
}
}
impl Index<RangeTo<usize>> for StackSlice {
type Output = Self;
fn index(&self, index: RangeTo<usize>) -> &Self::Output {
if self.slots.is_empty() {
return unsafe { Self::from_slots_unchecked(&[]) };
}
let end: usize = if index.end <= self.slots.len() { index.end } else { self.slots.len() };
unsafe { Self::from_slots_unchecked(&self.slots[..end]) }
}
}
impl Index<RangeFrom<usize>> for StackSlice {
type Output = Self;
fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
if index.start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked(&[]) };
}
unsafe { Self::from_slots_unchecked(&self.slots[index.start..]) }
}
}
impl Index<RangeFull> for StackSlice {
type Output = Self;
#[inline]
fn index(&self, _index: RangeFull) -> &Self::Output { self }
}
impl Index<RangeInclusive<usize>> for StackSlice {
type Output = Self;
fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
let start: usize = *index.start();
let end: usize = *index.end();
if start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked(&[]) };
}
let end: usize = if end < self.slots.len() { end + 1 } else { self.slots.len() };
unsafe { Self::from_slots_unchecked(&self.slots[start..end]) }
}
}
impl Index<RangeToInclusive<usize>> for StackSlice {
type Output = Self;
fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
if self.slots.is_empty() {
return unsafe { Self::from_slots_unchecked(&[]) };
}
let end: usize = if index.end < self.slots.len() { index.end + 1 } else { self.slots.len() };
unsafe { Self::from_slots_unchecked(&self.slots[..end]) }
}
}
impl IndexMut<usize> for StackSlice {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.slots[index].as_value_mut() }
}
impl IndexMut<Range<usize>> for StackSlice {
fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
if index.start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked_mut(&mut []) };
}
let end: usize = if index.end <= self.slots.len() { index.end } else { self.slots.len() };
unsafe { Self::from_slots_unchecked_mut(&mut self.slots[index.start..end]) }
}
}
impl IndexMut<RangeTo<usize>> for StackSlice {
fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
if self.slots.is_empty() {
return unsafe { Self::from_slots_unchecked_mut(&mut []) };
}
let end: usize = if index.end <= self.slots.len() { index.end } else { self.slots.len() };
unsafe { Self::from_slots_unchecked_mut(&mut self.slots[..end]) }
}
}
impl IndexMut<RangeFrom<usize>> for StackSlice {
fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
if index.start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked_mut(&mut []) };
}
unsafe { Self::from_slots_unchecked_mut(&mut self.slots[index.start..]) }
}
}
impl IndexMut<RangeFull> for StackSlice {
#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output { self }
}
impl IndexMut<RangeInclusive<usize>> for StackSlice {
fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
let start: usize = *index.start();
let end: usize = *index.end();
if start >= self.slots.len() {
return unsafe { Self::from_slots_unchecked_mut(&mut []) };
}
let end: usize = if end < self.slots.len() { end + 1 } else { self.slots.len() };
unsafe { Self::from_slots_unchecked_mut(&mut self.slots[start..end]) }
}
}
impl IndexMut<RangeToInclusive<usize>> for StackSlice {
fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
if self.slots.is_empty() {
return unsafe { Self::from_slots_unchecked_mut(&mut []) };
}
let end: usize = if index.end < self.slots.len() { index.end + 1 } else { self.slots.len() };
unsafe { Self::from_slots_unchecked_mut(&mut self.slots[..end]) }
}
}
impl ToOwned for StackSlice {
type Owned = Stack;
#[inline]
fn to_owned(&self) -> Stack { Stack::from_slice(&self.slots) }
}
impl<'a> IntoIterator for &'a StackSlice {
type IntoIter = std::iter::FilterMap<std::slice::Iter<'a, StackSlot>, fn(&'a StackSlot) -> Option<&'a Value>>;
type Item = &'a Value;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.slots.iter().filter_map(|s: &StackSlot| if s.is_value() { Some(s.as_value()) } else { None }) }
}
impl<'a> IntoIterator for &'a mut StackSlice {
type IntoIter = std::iter::FilterMap<std::slice::IterMut<'a, StackSlot>, fn(&'a mut StackSlot) -> Option<&'a mut Value>>;
type Item = &'a mut Value;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.slots.iter_mut().filter_map(|s: &mut StackSlot| if s.is_value() { Some(s.as_value_mut()) } else { None })
}
}
#[derive(Clone, Debug)]
pub struct Stack {
slots: Vec<StackSlot>,
}
impl Stack {
#[inline]
pub fn new(size: usize) -> Self { Self { slots: Vec::with_capacity(size) } }
#[inline]
fn from_slice(slice: &[StackSlot]) -> Self { Self { slots: slice.to_vec() } }
pub fn pop(&mut self) -> Option<Value> {
while let Some(v) = self.slots.pop() {
if v.is_value() {
return Some(v.into_value());
}
warn!("Popping {:?} in a non-dynamic pop situation", v);
}
None
}
pub fn dpop(&mut self) -> Vec<Value> {
let mut res: Vec<Value> = vec![];
while let Some(v) = self.slots.pop() {
if v.is_value() {
res.push(v.into_value());
continue;
}
if v.is_pop_marker() {
break;
}
}
res
}
pub fn push<V: Into<Value>>(&mut self, value: V) -> Result<(), Error> {
if self.slots.len() == self.slots.capacity() {
return Err(Error::StackOverflowError { size: self.slots.capacity() });
}
self.slots.push(StackSlot::from(value.into()));
Ok(())
}
pub fn push_pop_marker(&mut self) -> Result<(), Error> {
if self.slots.len() == self.slots.capacity() {
return Err(Error::StackOverflowError { size: self.slots.capacity() });
}
self.slots.push(StackSlot::PopMarker);
Ok(())
}
pub fn insert<V: Into<Value>>(&mut self, index: usize, value: V) -> Result<(), Error> {
if self.slots.len() == self.slots.capacity() {
return Err(Error::StackOverflowError { size: self.slots.capacity() });
}
self.slots.insert(index, StackSlot::from(value.into()));
Ok(())
}
}
impl Index<usize> for Stack {
type Output = Value;
#[inline]
fn index(&self, index: usize) -> &Self::Output { self.slots[index].as_value() }
}
impl Index<Range<usize>> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, index: Range<usize>) -> &Self::Output { &self[..][index] }
}
impl Index<RangeTo<usize>> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, index: RangeTo<usize>) -> &Self::Output { &self[..][index] }
}
impl Index<RangeFrom<usize>> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, index: RangeFrom<usize>) -> &Self::Output { &self[..][index] }
}
impl Index<RangeFull> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, _index: RangeFull) -> &Self::Output { unsafe { StackSlice::from_slots_unchecked(&self.slots) } }
}
impl Index<RangeInclusive<usize>> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, index: RangeInclusive<usize>) -> &Self::Output { Index::index(&**self, index) }
}
impl Index<RangeToInclusive<usize>> for Stack {
type Output = StackSlice;
#[inline]
fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output { Index::index(&**self, index) }
}
impl IndexMut<usize> for Stack {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.slots[index].as_value_mut() }
}
impl IndexMut<Range<usize>> for Stack {
#[inline]
fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output { unsafe { StackSlice::from_slots_unchecked_mut(&mut self.slots[index]) } }
}
impl IndexMut<RangeTo<usize>> for Stack {
#[inline]
fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output { &mut self[..][index] }
}
impl IndexMut<RangeFrom<usize>> for Stack {
#[inline]
fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output { &mut self[..][index] }
}
impl IndexMut<RangeFull> for Stack {
#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output { unsafe { StackSlice::from_slots_unchecked_mut(&mut self.slots) } }
}
impl IndexMut<RangeInclusive<usize>> for Stack {
#[inline]
fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output { IndexMut::index_mut(&mut **self, index) }
}
impl IndexMut<RangeToInclusive<usize>> for Stack {
#[inline]
fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output { IndexMut::index_mut(&mut **self, index) }
}
impl IntoIterator for Stack {
type IntoIter = std::iter::FilterMap<std::vec::IntoIter<StackSlot>, fn(StackSlot) -> Option<Value>>;
type Item = Value;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.slots.into_iter().filter_map(|s: StackSlot| if s.is_value() { Some(s.into_value()) } else { None }) }
}
impl<'a> IntoIterator for &'a Stack {
type IntoIter = std::iter::FilterMap<std::slice::Iter<'a, StackSlot>, fn(&'a StackSlot) -> Option<&'a Value>>;
type Item = &'a Value;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.slots.iter().filter_map(|s: &StackSlot| if s.is_value() { Some(s.as_value()) } else { None }) }
}
impl<'a> IntoIterator for &'a mut Stack {
type IntoIter = std::iter::FilterMap<std::slice::IterMut<'a, StackSlot>, fn(&'a mut StackSlot) -> Option<&'a mut Value>>;
type Item = &'a mut Value;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.slots.iter_mut().filter_map(|s: &mut StackSlot| if s.is_value() { Some(s.as_value_mut()) } else { None })
}
}
impl Borrow<StackSlice> for Stack {
#[inline]
fn borrow(&self) -> &StackSlice { &self[..] }
}
impl BorrowMut<StackSlice> for Stack {
#[inline]
fn borrow_mut(&mut self) -> &mut StackSlice { &mut self[..] }
}
impl Deref for Stack {
type Target = StackSlice;
#[inline]
fn deref(&self) -> &Self::Target { &self[..] }
}
impl DerefMut for Stack {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { &mut self[..] }
}