support all combinations of nested and tuple array syntax. Test small and large arrays

This commit is contained in:
collin 2020-09-03 13:22:05 -07:00
parent b6dc77e112
commit 4932eb688e
22 changed files with 256 additions and 45 deletions

View File

@ -0,0 +1,2 @@
[main]
a: [[u8; 2]; 3] = [[0; 2]; 3];

View File

@ -0,0 +1,2 @@
[main]
a: [[u8; 2]; 3] = [[0; 3]; 2]; // See `type_nested_value_nested_3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4];

View File

@ -0,0 +1,2 @@
[main]
a: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // See `type_nested_value_nested_4x3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [[u8; 2]; 3] = [0; (3, 2)];

View File

@ -0,0 +1,2 @@
[main]
a: [[u8; 2]; 3] = [0; (2, 3)]; // See `type_nested_value_tuple_3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)];

View File

@ -0,0 +1,2 @@
[main]
a: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // See `type_nested_value_tuple_4x3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (3, 2)] = [[0; 2]; 3];

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (3, 2)] = [[0; 3]; 2]; // See `type_tuple_value_nested_3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4];

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // See `type_tuple_value_nested_4x3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (3, 2)] = [0; (3, 2)];

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (3, 2)] = [0; (2, 3)]; // See `type_tuple_value_tuple_3x2.in` for correct dimensions

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (4, 3, 2)] = [0; (4, 3, 2)];

View File

@ -0,0 +1,2 @@
[main]
a: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // See `type_tuple_value_tuple_4x3x2.in` for correct dimensions

View File

@ -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);
}

View File

@ -0,0 +1,5 @@
function main(a: [[u8; 2]; 3]) {
const b = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline
console.assert(a == b);
}

View File

@ -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);
}

View File

@ -1,5 +0,0 @@
function main(a: [u8; (2, 3)) {
let b: [u8; (2, 3)] = [[0; 3]; 2];
console.assert(a == b);
}

View File

@ -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> {

View File

@ -137,27 +137,38 @@ impl InputValue {
array_type: ArrayType,
initializer: ArrayInitializerExpression,
) -> Result<Self, InputParserError> {
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<usize>,
initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> {
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<usize>,
initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> {
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<usize>) -> (Vec<usize>, 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 {