remove redundant array dimension struct

This commit is contained in:
collin 2022-03-04 13:06:22 -08:00
parent 1f7b1b57cc
commit 1a45295372
3 changed files with 28 additions and 72 deletions

View File

@ -20,41 +20,12 @@ use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::{fmt, ops::Deref}; use std::{fmt, ops::Deref};
/// A single array dimension.
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)]
pub enum Dimension {
/// The dimension was specified, e.g., `5` elements.
Number(PositiveNumber),
}
impl fmt::Display for Dimension {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Number(num) => write!(f, "{}", num),
}
}
}
impl Dimension {
/// } Returns `Some(n)` unless the dimension is [`Unspecified`].
pub fn as_specified(&self) -> Option<&PositiveNumber> {
match self {
Self::Number(n) => Some(n),
}
}
/// Returns true if the dimension is known to be zero.
fn is_zero(&self) -> bool {
self.as_specified().filter(|n| n.is_zero()).is_some()
}
}
/// Specifies array dimensions for array [`Type`]s or in array initializer [`Expression`]s. /// Specifies array dimensions for array [`Type`]s or in array initializer [`Expression`]s.
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct ArrayDimensions(pub SmallVec<[Dimension; 1]>); pub struct ArrayDimensions(pub SmallVec<[PositiveNumber; 1]>);
impl Deref for ArrayDimensions { impl Deref for ArrayDimensions {
type Target = [Dimension]; type Target = [PositiveNumber];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&*self.0 &*self.0
@ -63,7 +34,7 @@ impl Deref for ArrayDimensions {
impl ArrayDimensions { impl ArrayDimensions {
/// Returns a single-dimensional array dimension. /// Returns a single-dimensional array dimension.
pub fn single(dim: Dimension) -> Self { pub fn single(dim: PositiveNumber) -> Self {
Self(smallvec![dim]) Self(smallvec![dim])
} }
@ -73,7 +44,7 @@ impl ArrayDimensions {
} }
/// Attempts to remove the first dimension from the array, or returns `None` if it doesn't. /// Attempts to remove the first dimension from the array, or returns `None` if it doesn't.
pub fn remove_first(&mut self) -> Option<Dimension> { pub fn remove_first(&mut self) -> Option<PositiveNumber> {
if self.is_empty() { if self.is_empty() {
None None
} else { } else {
@ -82,7 +53,7 @@ impl ArrayDimensions {
} }
/// Attempts to remove the last dimension from the array, or returns `None` if it doesn't. /// Attempts to remove the last dimension from the array, or returns `None` if it doesn't.
pub fn remove_last(&mut self) -> Option<Dimension> { pub fn remove_last(&mut self) -> Option<PositiveNumber> {
self.0.pop() self.0.pop()
} }
} }
@ -95,9 +66,7 @@ impl Serialize for ArrayDimensions {
{ {
let mut seq = serializer.serialize_seq(Some(self.0.len()))?; let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for dim in self.0.iter() { for dim in self.0.iter() {
match dim { seq.serialize_element(&dim)?;
Dimension::Number(num) => seq.serialize_element(&num)?,
}
} }
seq.end() seq.end()
} }

View File

@ -88,32 +88,28 @@ impl TryFrom<(Type, Expression)> for InputValue {
} }
if let Some(dimension) = array_init.dimensions.remove_first() { if let Some(dimension) = array_init.dimensions.remove_first() {
if let Some(number) = dimension.as_specified() { let size = dimension.value.parse::<usize>().unwrap();
let size = number.value.parse::<usize>().unwrap(); let mut values = Vec::with_capacity(size);
let mut values = Vec::with_capacity(size);
// For when Dimensions are specified in a canonical way: [[u8; 3], 2]; // For when Dimensions are specified in a canonical way: [[u8; 3], 2];
// Else treat as math notation: [u8; (2, 3)]; // Else treat as math notation: [u8; (2, 3)];
if array_init.dimensions.len() == 0 { if array_init.dimensions.len() == 0 {
for _ in 0..size { for _ in 0..size {
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?); values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
} }
// Faking canonical array init is relatively easy: instead of using a straightforward // Faking canonical array init is relatively easy: instead of using a straightforward
// recursion, with each iteration we manually modify ArrayInitExpression cutting off // recursion, with each iteration we manually modify ArrayInitExpression cutting off
// dimension by dimension. // dimension by dimension.
} else {
for _ in 0..size {
values.push(InputValue::try_from((
Type::Array(type_.clone(), array_init.dimensions.clone()),
Expression::ArrayInit(array_init.clone()),
))?);
}
};
Self::Array(values)
} else { } else {
unreachable!("dimensions must be specified"); for _ in 0..size {
} values.push(InputValue::try_from((
Type::Array(type_.clone(), array_init.dimensions.clone()),
Expression::ArrayInit(array_init.clone()),
))?);
}
};
Self::Array(values)
} else { } else {
unreachable!("dimensions are checked for zero"); unreachable!("dimensions are checked for zero");
} }

View File

@ -59,12 +59,12 @@ impl ParserContext<'_> {
/// Returns an [`ArrayDimensions`] AST node if the next tokens represent dimensions for an array type. /// Returns an [`ArrayDimensions`] AST node if the next tokens represent dimensions for an array type.
pub fn parse_array_dimensions(&mut self) -> Result<ArrayDimensions> { pub fn parse_array_dimensions(&mut self) -> Result<ArrayDimensions> {
Ok(if let Some(dim) = self.parse_array_dimension() { Ok(if let Some((dim, _)) = self.eat_int() {
ArrayDimensions(smallvec![dim]) ArrayDimensions(smallvec![dim])
} else { } else {
let mut had_item_err = false; let mut had_item_err = false;
let (dims, _, span) = self.parse_paren_comma_list(|p| { let (dims, _, span) = self.parse_paren_comma_list(|p| {
Ok(if let Some(dim) = p.parse_array_dimension() { Ok(if let Some((dim, _)) = p.eat_int() {
Some(dim) Some(dim)
} else { } else {
let token = p.expect_any()?; let token = p.expect_any()?;
@ -80,15 +80,6 @@ impl ParserContext<'_> {
}) })
} }
/// Parses a basic array dimension, i.e., an integer or `_`.
fn parse_array_dimension(&mut self) -> Option<Dimension> {
if let Some((int, _)) = self.eat_int() {
Some(Dimension::Number(int))
} else {
None
}
}
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type. /// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.
/// Also returns the span of the parsed token. /// Also returns the span of the parsed token.
pub fn parse_type(&mut self) -> Result<(Type, Span)> { pub fn parse_type(&mut self) -> Result<(Type, Span)> {