use std::borrow::Borrow;
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::ops::Deref;
use std::ops::Range;
use std::sync::Arc;
use crate::eval::escaping;
use crate::eval::value::DebugInfo;
use crate::eval::value::Value;
pub type Str<'i> = ArcSlice<'i, str>;
pub type List<'i> = ArcSlice<'i, [Value<'i>]>;
#[allow(clippy::len_without_is_empty)]
pub trait Seq {
fn slice(&self, range: Range<usize>) -> Option<&Self>;
fn len(&self) -> usize;
fn empty<'a>() -> &'a Self;
fn ptr_value(&self) -> usize;
}
impl<T> Seq for [T] {
#[inline]
fn slice(&self, range: Range<usize>) -> Option<&Self> {
self.get(range)
}
#[inline]
fn len(&self) -> usize {
<[T]>::len(self)
}
#[inline]
fn empty<'a>() -> &'a Self {
&[]
}
#[inline]
fn ptr_value(&self) -> usize {
self.as_ptr() as usize
}
}
impl Seq for str {
#[inline]
fn slice(&self, range: Range<usize>) -> Option<&Self> {
self.get(range)
}
#[inline]
fn len(&self) -> usize {
str::len(self)
}
#[inline]
fn empty<'a>() -> &'a Self {
""
}
#[inline]
fn ptr_value(&self) -> usize {
self.as_ptr() as usize
}
}
#[derive(Debug)]
pub struct ArcSlice<'i, S: ?Sized> {
inner: Inner<'i, S>,
start: usize,
end: usize,
}
#[derive(Debug)]
enum Inner<'i, S: ?Sized> {
Empty,
Static(&'i S),
Dynamic(Arc<S>),
}
impl<'i, S: Seq + ?Sized> Inner<'i, S> {
fn as_ref(&self) -> &S {
match self {
Inner::Empty => S::empty(),
Inner::Static(s) => s,
Inner::Dynamic(s) => s.as_ref(),
}
}
}
#[derive(Eq, PartialEq, Copy, Clone, Hash, Debug)]
pub enum AllocType {
Empty,
Static,
Dynamic(usize),
}
impl fmt::Display for AllocType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AllocType::Empty => write!(f, "empty"),
AllocType::Static => write!(f, "static"),
AllocType::Dynamic(count) => write!(f, "arc = {}", count),
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct DebugInfoSeq {
pub addr: usize,
pub alloc_ty: AllocType,
pub start: usize,
pub end: usize,
}
impl fmt::Display for DebugInfoSeq {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"<{:#x}[{}..{}], {}>",
self.addr, self.start, self.end, self.alloc_ty
)
}
}
impl<S: Seq + ?Sized> DebugInfo for ArcSlice<'_, S> {
type Info = DebugInfoSeq;
fn debug_info(&self) -> Self::Info {
DebugInfoSeq {
addr: self.inner.as_ref().ptr_value(),
alloc_ty: match &self.inner {
Inner::Empty => AllocType::Empty,
Inner::Static(..) => AllocType::Static,
Inner::Dynamic(arc) => AllocType::Dynamic(Arc::strong_count(arc)),
},
start: self.start,
end: self.end,
}
}
}
impl<'i, S: Seq + ?Sized> ArcSlice<'i, S> {
pub fn new(values: impl Into<Arc<S>>) -> Self {
let values = values.into();
let len = values.len();
if len == 0 {
return Self::empty();
}
Self {
inner: Inner::Dynamic(values),
start: 0,
end: len,
}
}
pub fn empty() -> Self {
Self {
inner: Inner::Empty,
start: 0,
end: 0,
}
}
pub fn new_static(ptr: &'i S) -> Self {
if ptr.len() == 0 {
return Self::empty();
}
Self {
inner: Inner::Static(ptr),
start: 0,
end: ptr.len(),
}
}
pub fn as_sliced(&self) -> &S {
self
.inner
.as_ref()
.slice(self.start..self.end)
.expect("ArcSlice range cannot be out of bounds")
}
pub fn slice(&self, range: Range<usize>) -> Option<Self> {
let inner = self.inner.as_ref();
let start = range.start + self.start;
let end = range.end + self.start;
inner.slice(start..end)?;
if range.start == range.end {
return Some(Self::empty());
}
Some(ArcSlice {
start,
end,
..self.clone()
})
}
pub fn range(&self) -> Range<usize> {
self.start..self.end
}
pub fn len(&self) -> usize {
self.end - self.start
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn ptr_eq(&self, other: &Self) -> bool {
self.start == other.start
&& self.end == other.end
&& self.inner.as_ref().ptr_value() == other.inner.as_ref().ptr_value()
}
}
impl<S: Seq + ?Sized> Deref for ArcSlice<'_, S> {
type Target = S;
fn deref(&self) -> &Self::Target {
self.as_sliced()
}
}
impl<S: Seq + ?Sized> Borrow<S> for ArcSlice<'_, S> {
fn borrow(&self) -> &S {
self.as_sliced()
}
}
impl<S: Seq + ?Sized, T: Into<Arc<S>>> From<T> for ArcSlice<'_, S> {
fn from(seq: T) -> Self {
Self::new(seq)
}
}
impl<S: Seq + ?Sized + Hash> Hash for ArcSlice<'_, S> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_sliced().hash(state)
}
}
impl<S: Seq + ?Sized + PartialEq> PartialEq for ArcSlice<'_, S> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_sliced().eq(other.as_sliced())
}
}
impl<S: Seq + ?Sized + Eq> Eq for ArcSlice<'_, S> {}
impl<S: ?Sized> Clone for ArcSlice<'_, S> {
fn clone(&self) -> Self {
ArcSlice {
inner: match &self.inner {
Inner::Empty => Inner::Empty,
Inner::Static(p) => Inner::Static(p),
Inner::Dynamic(arc) => Inner::Dynamic(arc.clone()),
},
start: self.start,
end: self.end,
}
}
}
impl fmt::Display for Str<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut buf = String::new();
escaping::escape_alkyne_string(&*self, false, &mut buf);
write!(f, "{}", buf)
}
}
impl fmt::Display for List<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[")?;
let mut first = false;
for v in self.iter() {
if first {
write!(f, "{}", v)?;
first = false;
} else {
write!(f, ", {}", v)?;
}
}
write!(f, "]")
}
}