mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 02:31:44 +03:00
remove redundant array dimension struct
This commit is contained in:
parent
1f7b1b57cc
commit
1a45295372
@ -20,41 +20,12 @@ use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
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.
|
||||
#[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 {
|
||||
type Target = [Dimension];
|
||||
type Target = [PositiveNumber];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.0
|
||||
@ -63,7 +34,7 @@ impl Deref for ArrayDimensions {
|
||||
|
||||
impl ArrayDimensions {
|
||||
/// Returns a single-dimensional array dimension.
|
||||
pub fn single(dim: Dimension) -> Self {
|
||||
pub fn single(dim: PositiveNumber) -> Self {
|
||||
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.
|
||||
pub fn remove_first(&mut self) -> Option<Dimension> {
|
||||
pub fn remove_first(&mut self) -> Option<PositiveNumber> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
@ -82,7 +53,7 @@ impl ArrayDimensions {
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
||||
@ -95,9 +66,7 @@ impl Serialize for ArrayDimensions {
|
||||
{
|
||||
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
|
||||
for dim in self.0.iter() {
|
||||
match dim {
|
||||
Dimension::Number(num) => seq.serialize_element(&num)?,
|
||||
}
|
||||
seq.serialize_element(&dim)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
@ -88,32 +88,28 @@ impl TryFrom<(Type, Expression)> for InputValue {
|
||||
}
|
||||
|
||||
if let Some(dimension) = array_init.dimensions.remove_first() {
|
||||
if let Some(number) = dimension.as_specified() {
|
||||
let size = number.value.parse::<usize>().unwrap();
|
||||
let mut values = Vec::with_capacity(size);
|
||||
let size = dimension.value.parse::<usize>().unwrap();
|
||||
let mut values = Vec::with_capacity(size);
|
||||
|
||||
// For when Dimensions are specified in a canonical way: [[u8; 3], 2];
|
||||
// Else treat as math notation: [u8; (2, 3)];
|
||||
if array_init.dimensions.len() == 0 {
|
||||
for _ in 0..size {
|
||||
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
|
||||
}
|
||||
// Faking canonical array init is relatively easy: instead of using a straightforward
|
||||
// recursion, with each iteration we manually modify ArrayInitExpression cutting off
|
||||
// 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)
|
||||
// For when Dimensions are specified in a canonical way: [[u8; 3], 2];
|
||||
// Else treat as math notation: [u8; (2, 3)];
|
||||
if array_init.dimensions.len() == 0 {
|
||||
for _ in 0..size {
|
||||
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
|
||||
}
|
||||
// Faking canonical array init is relatively easy: instead of using a straightforward
|
||||
// recursion, with each iteration we manually modify ArrayInitExpression cutting off
|
||||
// dimension by dimension.
|
||||
} 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 {
|
||||
unreachable!("dimensions are checked for zero");
|
||||
}
|
||||
|
@ -59,12 +59,12 @@ impl ParserContext<'_> {
|
||||
|
||||
/// Returns an [`ArrayDimensions`] AST node if the next tokens represent dimensions for an array type.
|
||||
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])
|
||||
} else {
|
||||
let mut had_item_err = false;
|
||||
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)
|
||||
} else {
|
||||
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.
|
||||
/// Also returns the span of the parsed token.
|
||||
pub fn parse_type(&mut self) -> Result<(Type, Span)> {
|
||||
|
Loading…
Reference in New Issue
Block a user