From 91350a2ffe011958ca4bdb83d2ad91d807225b1b Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 2 Sep 2020 15:47:05 -0700 Subject: [PATCH] impl parenthesis syntax for input array initializer --- input/src/errors/parser.rs | 21 ++++++--- .../array_initializer_expression.rs | 4 +- input/src/expressions/expression.rs | 2 +- input/src/leo-input.pest | 2 +- input/src/types/array_dimensions.rs | 13 +++++- input/src/types/array_type.rs | 2 +- typed/src/input/input_value.rs | 46 +++++++++---------- 7 files changed, 53 insertions(+), 37 deletions(-) diff --git a/input/src/errors/parser.rs b/input/src/errors/parser.rs index 7f3f8ad24e..d808b61b51 100644 --- a/input/src/errors/parser.rs +++ b/input/src/errors/parser.rs @@ -17,7 +17,7 @@ use crate::{ ast::Rule, errors::SyntaxError as InputSyntaxError, - expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression}, + expressions::{ArrayInlineExpression, Expression}, sections::Header, tables::Table, types::{DataType, Type}, @@ -71,14 +71,22 @@ impl InputParserError { } pub fn data_type_mismatch(data_type: DataType, value: Value) -> Self { - let message = format!("expected `{}`, found `{}`", data_type.to_string(), value.to_string()); + let message = format!( + "expected data type `{}`, found `{}`", + data_type.to_string(), + value.to_string() + ); let span = value.span().to_owned(); Self::new_from_span(message, span) } pub fn expression_type_mismatch(type_: Type, expression: Expression) -> Self { - let message = format!("expected `{}`, found `{}`", type_.to_string(), expression.to_string()); + let message = format!( + "expected expression type `{}`, found `{}`", + type_.to_string(), + expression.to_string() + ); let span = expression.span().to_owned(); Self::new_from_span(message, span) @@ -95,12 +103,11 @@ impl InputParserError { Self::new_from_span(message, span) } - pub fn array_init_length(number: usize, array: ArrayInitializerExpression) -> Self { + pub fn array_init_length(expected: Vec, actual: Vec, span: Span) -> Self { let message = format!( - "expected an array with a fixed size of {} elements, found one with {} elements", - number, array.count + "expected an array with a fixed size of {:?} elements, found one with {:?} elements", + expected, actual ); - let span = array.span.to_owned(); Self::new_from_span(message, span) } diff --git a/input/src/expressions/array_initializer_expression.rs b/input/src/expressions/array_initializer_expression.rs index b8ba714780..0a01c4e90d 100644 --- a/input/src/expressions/array_initializer_expression.rs +++ b/input/src/expressions/array_initializer_expression.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, expressions::Expression, values::PositiveNumber}; +use crate::{ast::Rule, expressions::Expression, types::ArrayDimensions}; use pest::Span; use pest_ast::FromPest; @@ -23,7 +23,7 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::expression_array_initializer))] pub struct ArrayInitializerExpression<'ast> { pub expression: Box>, - pub count: PositiveNumber<'ast>, + pub dimensions: ArrayDimensions<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, } diff --git a/input/src/expressions/expression.rs b/input/src/expressions/expression.rs index e533ffc93c..c58bc66490 100644 --- a/input/src/expressions/expression.rs +++ b/input/src/expressions/expression.rs @@ -44,7 +44,7 @@ impl<'ast> fmt::Display for Expression<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Expression::ArrayInitializer(ref expression) => { - write!(f, "array [{} ; {}]", expression.expression, expression.count) + write!(f, "array [{} ; {}]", expression.expression, expression.dimensions) } Expression::ArrayInline(ref array) => { let values = array diff --git a/input/src/leo-input.pest b/input/src/leo-input.pest index 4a27b1a8b0..ec2574644b 100644 --- a/input/src/leo-input.pest +++ b/input/src/leo-input.pest @@ -179,7 +179,7 @@ value_address = {address | address_typed} /// Expressions // Declared in expressions/array_initializer_expression.rs -expression_array_initializer = { "[" ~ expression ~ ";" ~ number_positive ~ "]" } +expression_array_initializer = { "[" ~ expression ~ ";" ~ array_dimensions ~ "]" } // Declared in expressions/array_inline_expression.rs expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} diff --git a/input/src/types/array_dimensions.rs b/input/src/types/array_dimensions.rs index 5ddac86af4..3cb19adc1e 100644 --- a/input/src/types/array_dimensions.rs +++ b/input/src/types/array_dimensions.rs @@ -53,7 +53,7 @@ impl<'ast> ArrayDimensions<'ast> { let old_dimension = multiple.numbers.clone(); ArrayDimensions::Multiple(Multiple { - numbers: old_dimension[..old_dimension.len() - 2].to_vec(), + numbers: old_dimension[..old_dimension.len() - 1].to_vec(), span: multiple.span.clone(), }) } @@ -65,7 +65,16 @@ impl<'ast> std::fmt::Display for ArrayDimensions<'ast> { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { ArrayDimensions::Single(ref single) => write!(f, "{}", single.number), - ArrayDimensions::Multiple(ref multiple) => write!(f, "{:?}", multiple.numbers), + ArrayDimensions::Multiple(ref multiple) => { + let string = multiple + .numbers + .iter() + .map(|x| x.value.clone()) + .collect::>() + .join(", "); + + write!(f, "{}", string) + } } } } diff --git a/input/src/types/array_type.rs b/input/src/types/array_type.rs index 82e2ec688f..0110d7c030 100644 --- a/input/src/types/array_type.rs +++ b/input/src/types/array_type.rs @@ -33,6 +33,6 @@ pub struct ArrayType<'ast> { impl<'ast> std::fmt::Display for ArrayType<'ast> { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "[{}; {}]", self.type_, self.dimensions) + write!(f, "[{}; ({})]", self.type_, self.dimensions) } } diff --git a/typed/src/input/input_value.rs b/typed/src/input/input_value.rs index f1bb3670ad..6f23861860 100644 --- a/typed/src/input/input_value.rs +++ b/typed/src/input/input_value.rs @@ -139,40 +139,40 @@ impl InputValue { } pub(crate) fn from_array_initializer( - mut array_type: ArrayType, + array_type: ArrayType, initializer: ArrayInitializerExpression, ) -> Result { let mut array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); - let initializer_count = initializer.count.to_string().parse::()?; + let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone()); - // Return an error if the outer array dimension does not equal the number of array elements - if let Some(outer_dimension) = array_dimensions.pop() { - array_type.dimensions = array_type.dimensions.next_dimension(); - - if outer_dimension != initializer_count { - return Err(InputParserError::array_init_length(outer_dimension, initializer)); - } + // Return an error if the array type does not equal the array expression + if array_dimensions.ne(&initializer_dimensions) { + return Err(InputParserError::array_init_length( + array_dimensions, + initializer_dimensions, + initializer.span, + )); } - let inner_array_type = if array_dimensions.len() == 0 { - // this is a single array - match array_type.type_ { - ArrayElement::Basic(basic) => Type::Basic(basic), - ArrayElement::Tuple(tuple) => Type::Tuple(tuple), - } - } else { - // this is a multi-dimensional array - Type::Array(array_type) + let type_ = match array_type.type_ { + ArrayElement::Basic(basic) => Type::Basic(basic), + ArrayElement::Tuple(tuple) => Type::Tuple(tuple), }; - let mut values = vec![]; - for _ in 0..initializer_count { - let value = InputValue::from_expression(inner_array_type.clone(), *initializer.expression.clone())?; + let value = InputValue::from_expression(type_, *initializer.expression.clone())?; + let mut elements = vec![]; - values.push(value) + for (i, dimension) in initializer_dimensions.into_iter().enumerate() { + if i == 0 { + elements = vec![value.clone(); dimension]; + } else { + let element = InputValue::Array(elements.clone()); + + elements = vec![element; dimension]; + } } - Ok(InputValue::Array(values)) + Ok(InputValue::Array(elements)) } pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result {