mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-21 18:57:47 +03:00
support nested array type in leo inputs
This commit is contained in:
parent
de3564b98d
commit
b6dc77e112
@ -1,3 +1,3 @@
|
||||
function main(a: [u8; (3, 2)]) {
|
||||
console.assert(a == [[0u8; 2]; 3)]);
|
||||
console.assert(a == [[0u8; 2]; 3]);
|
||||
}
|
||||
|
@ -74,6 +74,15 @@ fn test_type_tuple() {
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_type_tuple_input() {
|
||||
// let program_bytes = include_bytes!("type_tuple_input.leo");
|
||||
// let input_bytes = include_bytes!("input/input_nested_3x2.in");
|
||||
// let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
|
||||
//
|
||||
// assert_satisfied(program);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_type_nested() {
|
||||
let program_bytes = include_bytes!("type_nested.leo");
|
||||
@ -136,8 +145,6 @@ fn test_initializer_input_fail() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
// TODO (howardwu): Add support for this syntax.
|
||||
fn test_input_nested_3x2() {
|
||||
let program_bytes = include_bytes!("input_nested_3x2.leo");
|
||||
let input_bytes = include_bytes!("input/input_nested_3x2.in");
|
||||
|
5
compiler/tests/array/type_tuple_input.leo
Normal file
5
compiler/tests/array/type_tuple_input.leo
Normal file
@ -0,0 +1,5 @@
|
||||
function main(a: [u8; (2, 3)) {
|
||||
let b: [u8; (2, 3)] = [[0; 3]; 2];
|
||||
|
||||
console.assert(a == b);
|
||||
}
|
@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32];
|
||||
commitment_randomness: [u8; 32] = [0u8; 32];
|
||||
|
||||
[state_leaf]
|
||||
path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ];
|
||||
path: [u8; 128] = [0u8; 128];
|
||||
memo: [u8; 32] = [0u8; 32];
|
||||
network_id: u8 = 0;
|
||||
leaf_randomness: [u8; 32] = [0u8; 32];
|
@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32];
|
||||
commitment_randomness: [u8; 32] = [0u8; 32];
|
||||
|
||||
[state_leaf]
|
||||
path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ];
|
||||
path: [u8; 128] = [0u8; 128];
|
||||
memo: [u8; 32] = [0u8; 32];
|
||||
network_id: u8 = 0;
|
||||
leaf_randomness: [u8; 32] = [0u8; 32];
|
@ -89,13 +89,7 @@ type_address = { "address" }
|
||||
type_data = { type_field | type_group | type_boolean | type_address | type_integer }
|
||||
|
||||
// Declared in types/array_type.rs
|
||||
type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" }
|
||||
|
||||
// Declared in types/array_element.rs
|
||||
array_element = {
|
||||
type_tuple
|
||||
| type_data
|
||||
}
|
||||
type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" }
|
||||
|
||||
// Declared in types/array_dimensions.rs
|
||||
array_dimensions = {
|
||||
|
@ -53,7 +53,7 @@ impl<'ast> ArrayDimensions<'ast> {
|
||||
let old_dimension = multiple.numbers.clone();
|
||||
|
||||
ArrayDimensions::Multiple(Multiple {
|
||||
numbers: old_dimension[..old_dimension.len() - 1].to_vec(),
|
||||
numbers: old_dimension[1..].to_vec(),
|
||||
span: multiple.span.clone(),
|
||||
})
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2019-2020 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, types::*};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::array_element))]
|
||||
pub enum ArrayElement<'ast> {
|
||||
Basic(DataType),
|
||||
Tuple(TupleType<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> std::fmt::Display for ArrayElement<'ast> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match *self {
|
||||
ArrayElement::Basic(ref basic) => write!(f, "{}", basic),
|
||||
ArrayElement::Tuple(ref tuple) => write!(f, "{}", tuple),
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
types::{ArrayDimensions, ArrayElement},
|
||||
types::{ArrayDimensions, Type},
|
||||
};
|
||||
|
||||
use pest::Span;
|
||||
@ -25,7 +25,7 @@ use pest_ast::FromPest;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::type_array))]
|
||||
pub struct ArrayType<'ast> {
|
||||
pub type_: ArrayElement<'ast>,
|
||||
pub type_: Box<Type<'ast>>,
|
||||
pub dimensions: ArrayDimensions<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -20,9 +20,6 @@ pub use address_type::*;
|
||||
pub mod array_dimensions;
|
||||
pub use array_dimensions::*;
|
||||
|
||||
pub mod array_element;
|
||||
pub use array_element::*;
|
||||
|
||||
pub mod array_type;
|
||||
pub use array_type::*;
|
||||
|
||||
|
@ -18,7 +18,7 @@ use crate::{Expression as TypedExpression, GroupValue};
|
||||
use leo_input::{
|
||||
errors::InputParserError,
|
||||
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression},
|
||||
types::{ArrayElement, ArrayType, DataType, IntegerType, TupleType, Type},
|
||||
types::{ArrayType, DataType, IntegerType, TupleType, Type},
|
||||
values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value},
|
||||
};
|
||||
|
||||
@ -106,36 +106,31 @@ impl InputValue {
|
||||
mut array_type: ArrayType,
|
||||
inline: ArrayInlineExpression,
|
||||
) -> Result<Self, InputParserError> {
|
||||
let mut array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone());
|
||||
let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.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 array_dimensions[0] != inline.expressions.len() {
|
||||
return Err(InputParserError::array_inline_length(array_dimensions[0], inline));
|
||||
}
|
||||
|
||||
if outer_dimension != inline.expressions.len() {
|
||||
return Err(InputParserError::array_inline_length(outer_dimension, inline));
|
||||
}
|
||||
};
|
||||
array_type.dimensions = array_type.dimensions.next_dimension();
|
||||
|
||||
let inner_array_type = if array_dimensions.len() == 0 {
|
||||
let inner_array_type = if array_dimensions.len() == 1 {
|
||||
// This is a single array
|
||||
match array_type.type_ {
|
||||
ArrayElement::Basic(basic) => Type::Basic(basic),
|
||||
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
|
||||
}
|
||||
*array_type.type_
|
||||
} else {
|
||||
// This is a multi-dimensional array
|
||||
Type::Array(array_type)
|
||||
};
|
||||
|
||||
let mut values = vec![];
|
||||
let mut elements = vec![];
|
||||
for expression in inline.expressions.into_iter() {
|
||||
let value = InputValue::from_expression(inner_array_type.clone(), expression)?;
|
||||
let element = InputValue::from_expression(inner_array_type.clone(), expression)?;
|
||||
|
||||
values.push(value)
|
||||
elements.push(element)
|
||||
}
|
||||
|
||||
Ok(InputValue::Array(values))
|
||||
Ok(InputValue::Array(elements))
|
||||
}
|
||||
|
||||
pub(crate) fn from_array_initializer(
|
||||
@ -145,24 +140,24 @@ impl InputValue {
|
||||
let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone());
|
||||
let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone());
|
||||
|
||||
// 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,
|
||||
));
|
||||
if array_dimensions.eq(&initializer_dimensions) {
|
||||
// The expression is an array initializer with tuple syntax
|
||||
Self::from_array_initializer_tuple(array_type, initializer, initializer_dimensions)
|
||||
} else {
|
||||
// The expression is an array initializer with nested syntax
|
||||
Self::from_array_initializer_nested(array_type, initializer, array_dimensions, initializer_dimensions)
|
||||
}
|
||||
}
|
||||
|
||||
let type_ = match array_type.type_ {
|
||||
ArrayElement::Basic(basic) => Type::Basic(basic),
|
||||
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
|
||||
};
|
||||
|
||||
let value = InputValue::from_expression(type_, *initializer.expression.clone())?;
|
||||
pub(crate) fn from_array_initializer_tuple(
|
||||
array_type: ArrayType,
|
||||
initializer: ArrayInitializerExpression,
|
||||
dimensions: Vec<usize>,
|
||||
) -> Result<Self, InputParserError> {
|
||||
let value = InputValue::from_expression(*array_type.type_, *initializer.expression.clone())?;
|
||||
let mut elements = vec![];
|
||||
|
||||
for (i, dimension) in initializer_dimensions.into_iter().enumerate() {
|
||||
for (i, dimension) in dimensions.into_iter().enumerate() {
|
||||
if i == 0 {
|
||||
elements = vec![value.clone(); dimension];
|
||||
} else {
|
||||
@ -175,6 +170,41 @@ impl InputValue {
|
||||
Ok(InputValue::Array(elements))
|
||||
}
|
||||
|
||||
pub(crate) fn from_array_initializer_nested(
|
||||
mut array_type: ArrayType,
|
||||
initializer: ArrayInitializerExpression,
|
||||
array_dimensions: Vec<usize>,
|
||||
initializer_dimensions: Vec<usize>,
|
||||
) -> Result<Self, InputParserError> {
|
||||
let current_array_dimension = array_dimensions[0];
|
||||
let current_initializer_dimension = initializer_dimensions[0];
|
||||
|
||||
// Return an error if the outer array dimension does not equal the number of array elements.
|
||||
if current_array_dimension.ne(¤t_initializer_dimension) {
|
||||
return Err(InputParserError::array_init_length(
|
||||
array_dimensions,
|
||||
initializer_dimensions,
|
||||
initializer.span,
|
||||
));
|
||||
}
|
||||
|
||||
array_type.dimensions = array_type.dimensions.next_dimension();
|
||||
|
||||
let inner_array_type = if array_dimensions.len() == 1 {
|
||||
// This is the innermost dimension
|
||||
*array_type.type_
|
||||
} else {
|
||||
// This is an outer dimension of a multi-dimensional array
|
||||
Type::Array(array_type)
|
||||
};
|
||||
|
||||
// Evaluate the array initializer
|
||||
let element = InputValue::from_expression(inner_array_type.clone(), *initializer.expression)?;
|
||||
let elements = vec![element; current_initializer_dimension];
|
||||
|
||||
Ok(InputValue::Array(elements))
|
||||
}
|
||||
|
||||
pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result<Self, InputParserError> {
|
||||
let num_types = tuple_type.types_.len();
|
||||
let num_values = tuple.expressions.len();
|
||||
|
@ -17,7 +17,6 @@
|
||||
use crate::{Expression, Identifier, IntegerType};
|
||||
use leo_ast::types::{ArrayType, CircuitType, DataType, TupleType, Type as AstType};
|
||||
use leo_input::types::{
|
||||
ArrayElement as InputArrayElement,
|
||||
ArrayType as InputArrayType,
|
||||
DataType as InputDataType,
|
||||
TupleType as InputTupleType,
|
||||
@ -151,22 +150,13 @@ impl From<InputDataType> for Type {
|
||||
|
||||
impl<'ast> From<InputArrayType<'ast>> for Type {
|
||||
fn from(array_type: InputArrayType<'ast>) -> Self {
|
||||
let element_type = Box::new(Type::from(array_type.type_));
|
||||
let element_type = Box::new(Type::from(*array_type.type_));
|
||||
let dimensions = Expression::get_input_array_dimensions(array_type.dimensions);
|
||||
|
||||
Type::Array(element_type, dimensions)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputArrayElement<'ast>> for Type {
|
||||
fn from(element: InputArrayElement<'ast>) -> Self {
|
||||
match element {
|
||||
InputArrayElement::Basic(type_) => Type::from(type_),
|
||||
InputArrayElement::Tuple(type_) => Type::from(type_),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputTupleType<'ast>> for Type {
|
||||
fn from(tuple_type: InputTupleType<'ast>) -> Self {
|
||||
let types = tuple_type.types_.into_iter().map(|type_| Type::from(type_)).collect();
|
||||
|
Loading…
Reference in New Issue
Block a user