use core::fmt;
use smallvec::SmallVec;
use crate::{
AttrPrinter, attributes::InferAttributeValueType, derive::DialectAttribute,
dialects::builtin::BuiltinDialect, formatter::DisplayValues, print::AsmPrinter,
};
#[derive(DialectAttribute)]
#[attribute(
name = "array_u32",
dialect = BuiltinDialect,
remote = "Array<u32>",
implements(AttrPrinter),
)]
#[allow(unused)]
struct U32Array;
#[derive(DialectAttribute)]
#[attribute(
dialect = BuiltinDialect,
remote = "Array<crate::Type>",
implements(AttrPrinter),
)]
#[allow(unused)]
struct TypeArray;
#[derive(DialectAttribute)]
#[attribute(
dialect = BuiltinDialect,
remote = "Array<super::MemoryEffectDescriptor>",
implements(AttrPrinter),
)]
#[allow(unused)]
struct MemoryEffectArray;
#[derive(DialectAttribute)]
#[attribute(
dialect = BuiltinDialect,
remote = "Array<super::AdviceEffectDescriptor>",
implements(AttrPrinter),
)]
#[allow(unused)]
struct AdviceEffectArray;
#[derive(DialectAttribute)]
#[attribute(
dialect = BuiltinDialect,
remote = "Array<super::LocalVariable>",
implements(AttrPrinter),
)]
#[allow(unused)]
struct LocalVariableArray;
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Array<T>(SmallVec<[T; 2]>);
impl<T> Array<T> {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.0.iter()
}
pub fn push(&mut self, value: T) {
self.0.push(value);
}
pub fn remove(&mut self, index: usize) -> T {
self.0.remove(index)
}
}
default impl<I: IntoIterator> From<I> for Array<<I as IntoIterator>::Item> {
#[inline(always)]
fn from(iter: I) -> Self {
Self::from_iter(iter)
}
}
impl<T, const N: usize> From<[T; N]> for Array<T> {
#[inline]
fn from(value: [T; N]) -> Self {
Self(SmallVec::from_iter(value))
}
}
impl<T> From<SmallVec<[T; 2]>> for Array<T> {
fn from(value: SmallVec<[T; 2]>) -> Self {
Self(value)
}
}
impl<T> From<alloc::vec::Vec<T>> for Array<T> {
fn from(value: alloc::vec::Vec<T>) -> Self {
Self(SmallVec::from_vec(value))
}
}
impl<T> FromIterator<T> for Array<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self(SmallVec::from_iter(iter))
}
}
impl<T> Default for Array<T> {
#[inline]
fn default() -> Self {
Self(SmallVec::new_const())
}
}
impl<T> Array<T>
where
T: Eq,
{
pub fn contains(&self, value: &T) -> bool {
self.0.contains(value)
}
}
impl<T> fmt::Debug for Array<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.iter()).finish()
}
}
impl<T> fmt::Display for Array<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}]", DisplayValues::new(self.0.iter()))
}
}
impl<T> crate::formatter::PrettyPrint for Array<T>
where
T: crate::formatter::PrettyPrint,
{
fn render(&self) -> crate::formatter::Document {
use crate::formatter::*;
let entries = self.iter().fold(Document::Empty, |acc, v| match acc {
Document::Empty => v.render(),
_ => acc + const_text(", ") + v.render(),
});
if self.is_empty() {
const_text("[]")
} else {
const_text("[") + entries + const_text("]")
}
}
}
impl<T> core::ops::Index<usize> for Array<T> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl<T> core::ops::Index<core::ops::Range<usize>> for Array<T> {
type Output = [T];
#[inline]
fn index(&self, range: core::ops::Range<usize>) -> &Self::Output {
&self.0[range]
}
}
impl<T> core::ops::Index<core::ops::RangeTo<usize>> for Array<T> {
type Output = [T];
#[inline]
fn index(&self, range: core::ops::RangeTo<usize>) -> &Self::Output {
&self.0[range]
}
}
impl<T> core::ops::Index<core::ops::RangeToInclusive<usize>> for Array<T> {
type Output = [T];
#[inline]
fn index(&self, range: core::ops::RangeToInclusive<usize>) -> &Self::Output {
&self.0[range]
}
}
impl<T> core::ops::Index<core::ops::RangeFrom<usize>> for Array<T> {
type Output = [T];
#[inline]
fn index(&self, range: core::ops::RangeFrom<usize>) -> &Self::Output {
&self.0[range]
}
}
impl<T> core::ops::Index<core::ops::RangeFull> for Array<T> {
type Output = [T];
#[inline]
fn index(&self, _range: core::ops::RangeFull) -> &Self::Output {
self.0.as_slice()
}
}
impl<T> core::ops::IndexMut<usize> for Array<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl<T: Clone + InferAttributeValueType> InferAttributeValueType for Array<T> {
fn infer_type() -> crate::Type {
<T as InferAttributeValueType>::infer_type()
}
fn infer_type_from_value(&self) -> crate::Type {
if self.0.is_empty() {
Self::infer_type()
} else {
<T as InferAttributeValueType>::infer_type_from_value(&self.0[0])
}
}
}
impl crate::print::AttrPrinter for U32ArrayAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use crate::formatter::*;
for (i, value) in self.0.iter().enumerate() {
if i > 0 {
*printer += const_text(", ");
}
*printer += value.render();
}
}
}
impl crate::print::AttrPrinter for TypeArrayAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use crate::formatter::*;
for (i, value) in self.0.iter().enumerate() {
if i > 0 {
*printer += const_text(", ");
}
printer.print_type(value);
}
}
}
impl crate::print::AttrPrinter for LocalVariableArrayAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use crate::formatter::*;
for (i, value) in self.0.iter().enumerate() {
if i > 0 {
*printer += const_text(", ");
}
*printer += text(alloc::format!("{value}"));
}
}
}
impl crate::print::AttrPrinter for MemoryEffectArrayAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use crate::formatter::*;
for (i, value) in self.0.iter().enumerate() {
if i > 0 {
*printer += const_text(", ");
}
*printer += const_text("{");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_string(value.effect);
if let Some(argument) = value.argument {
*printer += const_text(", ");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_decimal_integer(argument);
}
if let Some(result) = value.result {
*printer += const_text(", ");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_decimal_integer(result);
}
*printer += const_text("}");
}
}
}
impl crate::print::AttrPrinter for AdviceEffectArrayAttr {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use crate::formatter::*;
for (i, value) in self.0.iter().enumerate() {
if i > 0 {
*printer += const_text(", ");
}
*printer += const_text("{");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_string(value.effect);
if let Some(argument) = value.argument {
*printer += const_text(", ");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_decimal_integer(argument);
}
if let Some(result) = value.result {
*printer += const_text(", ");
printer.print_bare_identifier("effect".into());
*printer += const_text(" = ");
printer.print_decimal_integer(result);
}
*printer += const_text("}");
}
}
}