From 4932eb688e9263f3a93501b6bed050259e96b9a5 Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 3 Sep 2020 13:22:05 -0700 Subject: [PATCH] support all combinations of nested and tuple array syntax. Test small and large arrays --- .../input/type_nested_value_nested_3x2.in | 2 + .../type_nested_value_nested_3x2_fail.in | 2 + .../input/type_nested_value_nested_4x3x2.in | 2 + .../type_nested_value_nested_4x3x2_fail.in | 2 + .../input/type_nested_value_tuple_3x2.in | 2 + .../input/type_nested_value_tuple_3x2_fail.in | 2 + .../input/type_nested_value_tuple_4x3x2.in | 2 + .../type_nested_value_tuple_4x3x2_fail.in | 2 + .../input/type_tuple_value_nested_3x2.in | 2 + .../input/type_tuple_value_nested_3x2_fail.in | 2 + .../input/type_tuple_value_nested_4x3x2.in | 2 + .../type_tuple_value_nested_4x3x2_fail.in | 2 + .../array/input/type_tuple_value_tuple_3x2.in | 2 + .../input/type_tuple_value_tuple_3x2_fail.in | 2 + .../input/type_tuple_value_tuple_4x3x2.in | 2 + .../type_tuple_value_tuple_4x3x2_fail.in | 2 + compiler/tests/array/mod.rs | 207 +++++++++++++++--- compiler/tests/array/type_input_3x2.leo | 5 + compiler/tests/array/type_input_4x3x2.leo | 8 + compiler/tests/array/type_tuple_input.leo | 5 - input/src/types/array_dimensions.rs | 7 + typed/src/input/input_value.rs | 37 +++- 22 files changed, 256 insertions(+), 45 deletions(-) create mode 100644 compiler/tests/array/input/type_nested_value_nested_3x2.in create mode 100644 compiler/tests/array/input/type_nested_value_nested_3x2_fail.in create mode 100644 compiler/tests/array/input/type_nested_value_nested_4x3x2.in create mode 100644 compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in create mode 100644 compiler/tests/array/input/type_nested_value_tuple_3x2.in create mode 100644 compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in create mode 100644 compiler/tests/array/input/type_nested_value_tuple_4x3x2.in create mode 100644 compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in create mode 100644 compiler/tests/array/input/type_tuple_value_nested_3x2.in create mode 100644 compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in create mode 100644 compiler/tests/array/input/type_tuple_value_nested_4x3x2.in create mode 100644 compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in create mode 100644 compiler/tests/array/input/type_tuple_value_tuple_3x2.in create mode 100644 compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in create mode 100644 compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in create mode 100644 compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in create mode 100644 compiler/tests/array/type_input_3x2.leo create mode 100644 compiler/tests/array/type_input_4x3x2.leo delete mode 100644 compiler/tests/array/type_tuple_input.leo diff --git a/compiler/tests/array/input/type_nested_value_nested_3x2.in b/compiler/tests/array/input/type_nested_value_nested_3x2.in new file mode 100644 index 0000000000..21fc9b953f --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [[0; 2]; 3]; diff --git a/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in b/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in new file mode 100644 index 0000000000..7ccb8c5f60 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [[0; 3]; 2]; // See `type_nested_value_nested_3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_nested_value_nested_4x3x2.in b/compiler/tests/array/input/type_nested_value_nested_4x3x2.in new file mode 100644 index 0000000000..53ca13b024 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4]; diff --git a/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in b/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in new file mode 100644 index 0000000000..a31242e064 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // See `type_nested_value_nested_4x3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_nested_value_tuple_3x2.in b/compiler/tests/array/input/type_nested_value_tuple_3x2.in new file mode 100644 index 0000000000..689e164b73 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [0; (3, 2)]; diff --git a/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in b/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in new file mode 100644 index 0000000000..3f70a19a92 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [0; (2, 3)]; // See `type_nested_value_tuple_3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in b/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in new file mode 100644 index 0000000000..649a7154ad --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)]; diff --git a/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in b/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in new file mode 100644 index 0000000000..f4fc43c867 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // See `type_nested_value_tuple_4x3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_tuple_value_nested_3x2.in b/compiler/tests/array/input/type_tuple_value_nested_3x2.in new file mode 100644 index 0000000000..cb3943365b --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [[0; 2]; 3]; diff --git a/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in b/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in new file mode 100644 index 0000000000..a5f0c53004 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [[0; 3]; 2]; // See `type_tuple_value_nested_3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in b/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in new file mode 100644 index 0000000000..8105eae543 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4]; diff --git a/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in b/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in new file mode 100644 index 0000000000..d18e017f94 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // See `type_tuple_value_nested_4x3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_tuple_value_tuple_3x2.in b/compiler/tests/array/input/type_tuple_value_tuple_3x2.in new file mode 100644 index 0000000000..cbfeb6d5f1 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [0; (3, 2)]; diff --git a/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in b/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in new file mode 100644 index 0000000000..e2b3fbbf0d --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [0; (2, 3)]; // See `type_tuple_value_tuple_3x2.in` for correct dimensions diff --git a/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in new file mode 100644 index 0000000000..6fd97ee2d2 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [0; (4, 3, 2)]; diff --git a/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in new file mode 100644 index 0000000000..1cb833e84e --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // See `type_tuple_value_tuple_4x3x2.in` for correct dimensions diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index 3a53be50cc..1ba20c9676 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -58,39 +58,6 @@ fn test_registers() { // Expressions -#[test] -fn test_type_fail() { - let program_bytes = include_bytes!("type_fail.leo"); - let syntax_error = parse_program(program_bytes).is_err(); - - assert!(syntax_error); -} - -#[test] -fn test_type_tuple() { - let program_bytes = include_bytes!("type_tuple.leo"); - let program = parse_program(program_bytes).unwrap(); - - 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"); - let program = parse_program(program_bytes).unwrap(); - - assert_satisfied(program); -} - #[test] fn test_inline() { let program_bytes = include_bytes!("inline.leo"); @@ -261,3 +228,177 @@ fn test_slice() { assert_satisfied(program); } + +// Array type tests + +#[test] +fn test_type_fail() { + let program_bytes = include_bytes!("type_fail.leo"); + let syntax_error = parse_program(program_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_type_tuple() { + let program_bytes = include_bytes!("type_tuple.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_nested() { + let program_bytes = include_bytes!("type_nested.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +// Tests for nested multi-dimensional arrays as input to the program + +#[test] +fn test_input_type_nested_value_nested_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_tuple_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program) +} + +#[test] +fn test_input_type_nested_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +// Tests for multi-dimensional arrays using tuple syntax as input to the program + +#[test] +fn test_input_type_tuple_value_nested_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_tuple_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} diff --git a/compiler/tests/array/type_input_3x2.leo b/compiler/tests/array/type_input_3x2.leo new file mode 100644 index 0000000000..ea60a0cc24 --- /dev/null +++ b/compiler/tests/array/type_input_3x2.leo @@ -0,0 +1,5 @@ +function main(a: [[u8; 2]; 3]) { + const b = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_input_4x3x2.leo b/compiler/tests/array/type_input_4x3x2.leo new file mode 100644 index 0000000000..2d9c4cff22 --- /dev/null +++ b/compiler/tests/array/type_input_4x3x2.leo @@ -0,0 +1,8 @@ +function main(a: [[[u8; 2]; 3]; 4]) { + const b = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_input.leo b/compiler/tests/array/type_tuple_input.leo deleted file mode 100644 index 11582aafe8..0000000000 --- a/compiler/tests/array/type_tuple_input.leo +++ /dev/null @@ -1,5 +0,0 @@ -function main(a: [u8; (2, 3)) { - let b: [u8; (2, 3)] = [[0; 3]; 2]; - - console.assert(a == b); -} \ No newline at end of file diff --git a/input/src/types/array_dimensions.rs b/input/src/types/array_dimensions.rs index 6f6c69a8fb..58d9e14703 100644 --- a/input/src/types/array_dimensions.rs +++ b/input/src/types/array_dimensions.rs @@ -59,6 +59,13 @@ impl<'ast> ArrayDimensions<'ast> { } } } + + pub fn is_empty(&self) -> bool { + match self { + ArrayDimensions::Single(_) => false, + ArrayDimensions::Multiple(multiple) => multiple.numbers.is_empty(), + } + } } impl<'ast> std::fmt::Display for ArrayDimensions<'ast> { diff --git a/typed/src/input/input_value.rs b/typed/src/input/input_value.rs index 24871ece71..14fa81209e 100644 --- a/typed/src/input/input_value.rs +++ b/typed/src/input/input_value.rs @@ -137,27 +137,38 @@ impl InputValue { array_type: ArrayType, initializer: ArrayInitializerExpression, ) -> Result { - let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone()); - if array_dimensions.eq(&initializer_dimensions) { + if initializer_dimensions.len() > 1 { // 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) + Self::from_array_initializer_nested(array_type, initializer, initializer_dimensions) } } pub(crate) fn from_array_initializer_tuple( array_type: ArrayType, initializer: ArrayInitializerExpression, - dimensions: Vec, + initializer_dimensions: Vec, ) -> Result { - let value = InputValue::from_expression(*array_type.type_, *initializer.expression.clone())?; + let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![]); + + // Return an error if the dimensions of the array are incorrect. + if array_dimensions.ne(&initializer_dimensions) { + return Err(InputParserError::array_init_length( + array_dimensions, + initializer_dimensions, + initializer.span, + )); + } + + let value = InputValue::from_expression(array_element_type, *initializer.expression.clone())?; let mut elements = vec![]; - for (i, dimension) in dimensions.into_iter().enumerate() { + // Build the elements of the array using the `vec!` macro + for (i, dimension) in initializer_dimensions.into_iter().enumerate() { if i == 0 { elements = vec![value.clone(); dimension]; } else { @@ -173,9 +184,10 @@ impl InputValue { pub(crate) fn from_array_initializer_nested( mut array_type: ArrayType, initializer: ArrayInitializerExpression, - array_dimensions: Vec, initializer_dimensions: Vec, ) -> Result { + let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); + let current_array_dimension = array_dimensions[0]; let current_initializer_dimension = initializer_dimensions[0]; @@ -228,6 +240,17 @@ impl InputValue { } } +// Recursively fetch all dimensions from the array type +fn fetch_nested_array_type_dimensions(array_type: ArrayType, mut array_dimensions: Vec) -> (Vec, Type) { + let mut current_dimension = TypedExpression::get_input_array_dimensions(array_type.dimensions); + array_dimensions.append(&mut current_dimension); + + match *array_type.type_ { + Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions), + type_ => (array_dimensions, type_), + } +} + impl fmt::Display for InputValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self {