mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-24 07:48:04 +03:00
Fixes array indices for both nested and tuple cases
This commit is contained in:
parent
40ac13e317
commit
981d272fa6
@ -52,7 +52,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
};
|
||||
|
||||
expected_dimensions.push(number);
|
||||
expected_type = Some(type_.inner_dimension(dimensions).clone());
|
||||
expected_type = Some(type_.outer_dimension(dimensions).clone());
|
||||
}
|
||||
ref type_ => {
|
||||
return Err(ExpressionError::unexpected_array(type_.to_string(), span));
|
||||
@ -69,9 +69,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
match self.get(&array_name) {
|
||||
Some(value) => match value {
|
||||
ConstrainedValue::Array(array) => result.extend(array.clone()),
|
||||
value => {
|
||||
return Err(ExpressionError::invalid_spread(value.to_string(), span));
|
||||
}
|
||||
value => return Err(ExpressionError::invalid_spread(value.to_string(), span)),
|
||||
},
|
||||
None => return Err(ExpressionError::undefined_array(identifier.name, span)),
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
let array_type = types[0].to_type(span.clone())?;
|
||||
let count = types.len();
|
||||
|
||||
// nested array type
|
||||
// Nested array type
|
||||
if let Type::Array(inner_type, inner_dimensions) = &array_type {
|
||||
let mut dimensions = inner_dimensions.clone();
|
||||
dimensions.push(count);
|
||||
|
@ -1,2 +1,2 @@
|
||||
[main]
|
||||
a: [u8; (3, 2)] = [0; (2, 2)];
|
||||
a: [u8; (3, 2)] = [0u8; (2, 2)];
|
||||
|
2
compiler/tests/array/input/input_nested_3x2.in
Normal file
2
compiler/tests/array/input/input_nested_3x2.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
a: [u8; (3, 2)] = [[0u8; 2]; 3];
|
2
compiler/tests/array/input/input_nested_3x2_fail.in
Normal file
2
compiler/tests/array/input/input_nested_3x2_fail.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
a: [u8; (3, 2)] = [[0u8; 3]; 2)];
|
2
compiler/tests/array/input/input_tuple_3x2.in
Normal file
2
compiler/tests/array/input/input_tuple_3x2.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
a: [u8; (3, 2)] = [0u8; (3, 2)];
|
2
compiler/tests/array/input/input_tuple_3x2_fail.in
Normal file
2
compiler/tests/array/input/input_tuple_3x2_fail.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
a: [u8; (3, 2)] = [0u8; (2, 3)];
|
3
compiler/tests/array/input_nested_3x2.leo
Normal file
3
compiler/tests/array/input_nested_3x2.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: [u8; (3, 2)]) {
|
||||
console.assert(a == [[0u8; 2]; 3)]);
|
||||
}
|
3
compiler/tests/array/input_nested_3x2_fail.leo
Normal file
3
compiler/tests/array/input_nested_3x2_fail.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: [u8; (3, 2)]) {
|
||||
console.assert(a == [[0u8; 2]; 3)]); // This should be written the right way as this test is for the input file.
|
||||
}
|
3
compiler/tests/array/input_tuple_3x2.leo
Normal file
3
compiler/tests/array/input_tuple_3x2.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: [u8; (3, 2)]) {
|
||||
console.assert(a == [0u8; (3, 2)]);
|
||||
}
|
3
compiler/tests/array/input_tuple_3x2_fail.leo
Normal file
3
compiler/tests/array/input_tuple_3x2_fail.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: [u8; (3, 2)]) {
|
||||
console.assert(a == [0u8; (3, 2)]);
|
||||
}
|
@ -120,37 +120,41 @@ fn test_initializer_input_fail() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spread() {
|
||||
let program_bytes = include_bytes!("spread.leo");
|
||||
let input_bytes = include_bytes!("input/three_ones.in");
|
||||
#[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");
|
||||
let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
let program_bytes = include_bytes!("slice.leo");
|
||||
let input_bytes = include_bytes!("input/three_ones.in");
|
||||
fn test_input_nested_3x2_fail() {
|
||||
let program_bytes = include_bytes!("input_nested_3x2_fail.leo");
|
||||
let input_bytes = include_bytes!("input/input_nested_3x2_fail.in");
|
||||
let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err();
|
||||
|
||||
assert!(syntax_error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_tuple_3x2() {
|
||||
let program_bytes = include_bytes!("input_tuple_3x2.leo");
|
||||
let input_bytes = include_bytes!("input/input_tuple_3x2.in");
|
||||
let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi() {
|
||||
let program_bytes = include_bytes!("multi.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
fn test_input_tuple_3x2_fail() {
|
||||
let program_bytes = include_bytes!("input_tuple_3x2_fail.leo");
|
||||
let input_bytes = include_bytes!("input/input_tuple_3x2_fail.in");
|
||||
let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_fail() {
|
||||
let program_bytes = include_bytes!("multi_fail.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
assert!(syntax_error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -184,3 +188,53 @@ fn test_multi_initializer_fail() {
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_3x2_value() {
|
||||
let program_bytes = include_bytes!("nested_3x2_value.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_3x2_value_fail() {
|
||||
let program_bytes = include_bytes!("nested_3x2_value_fail.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_3x2_value() {
|
||||
let program_bytes = include_bytes!("tuple_3x2_value.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_3x2_value_fail() {
|
||||
let program_bytes = include_bytes!("tuple_3x2_value_fail.leo");
|
||||
let program = parse_program(program_bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spread() {
|
||||
let program_bytes = include_bytes!("spread.leo");
|
||||
let input_bytes = include_bytes!("input/three_ones.in");
|
||||
let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
let program_bytes = include_bytes!("slice.leo");
|
||||
let input_bytes = include_bytes!("input/three_ones.in");
|
||||
let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
8
compiler/tests/array/tuple_3x2_value.leo
Normal file
8
compiler/tests/array/tuple_3x2_value.leo
Normal file
@ -0,0 +1,8 @@
|
||||
// Multidimensional array syntax in leo
|
||||
function main() {
|
||||
const a = [[0u32, 0u32], [0u32, 0u32], [0u32, 0u32]]; // inline
|
||||
|
||||
const b: [u32; (3, 2)] = [0; (3, 2)]; // initializer
|
||||
|
||||
console.assert(a == b);
|
||||
}
|
4
compiler/tests/array/tuple_3x2_value_fail.leo
Normal file
4
compiler/tests/array/tuple_3x2_value_fail.leo
Normal file
@ -0,0 +1,4 @@
|
||||
// Multidimensional array syntax in leo
|
||||
function main() {
|
||||
const a: [u32; (3, 2)] = [0; (2, 3)]; // initializer (incorrectly reversed ordering)
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// 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 pest::{Position, Span as AstSpan};
|
||||
use pest::Span as AstSpan;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
|
@ -501,7 +501,7 @@ impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
|
||||
// Initializes an arrays elements using the rust `vec!` macro.
|
||||
// If there are multiple array dimensions, then `elements` is used as the first expression in a `vec!` macro.
|
||||
// This creates a multi-dimensional array by chaining `vec!` macros.
|
||||
for (i, dimension) in dimensions.into_iter().enumerate() {
|
||||
for (i, dimension) in dimensions.into_iter().rev().enumerate() {
|
||||
if i == 0 {
|
||||
elements = vec![expression.clone(); dimension];
|
||||
} else {
|
||||
|
@ -108,7 +108,7 @@ impl InputValue {
|
||||
) -> Result<Self, InputParserError> {
|
||||
let mut 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
|
||||
// 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();
|
||||
|
||||
@ -118,13 +118,13 @@ impl InputValue {
|
||||
};
|
||||
|
||||
let inner_array_type = if array_dimensions.len() == 0 {
|
||||
// this is a single array
|
||||
// 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
|
||||
// This is a multi-dimensional array
|
||||
Type::Array(array_type)
|
||||
};
|
||||
|
||||
|
@ -64,7 +64,7 @@ impl Type {
|
||||
|
||||
if dimensions.len() > 1 {
|
||||
let mut next = vec![];
|
||||
next.extend_from_slice(&dimensions[..dimensions.len() - 1]);
|
||||
next.extend_from_slice(&dimensions[1..]);
|
||||
|
||||
return Type::Array(Box::new(type_), next);
|
||||
}
|
||||
@ -77,7 +77,7 @@ impl Type {
|
||||
|
||||
if dimensions.len() > 1 {
|
||||
let mut next = vec![];
|
||||
next.extend_from_slice(&dimensions[1..dimensions.len()]);
|
||||
next.extend_from_slice(&dimensions[..dimensions.len() - 1]);
|
||||
|
||||
return Type::Array(Box::new(type_), next);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user