Merge pull request #347 from AleoHQ/feature/array-type

Feature/array type
This commit is contained in:
Howard Wu 2020-09-07 15:47:23 -07:00 committed by GitHub
commit eff7d9d599
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 535 additions and 167 deletions

View File

@ -79,7 +79,7 @@ cd leo
$ cargo build --release
```
This will generate an executable under the `./target/release` directory. To run snarkOS, run the following command:
This will generate an executable under the `./target/release` directory. To run Leo, run the following command:
```bash
./target/release/leo
```

View File

@ -197,15 +197,7 @@ type_self = { "Self" }
type_circuit = { identifier }
// Declared in types/array_type.rs
type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" }
// Declared in types/array_element.rs
array_element = {
type_self
| type_tuple
| type_data
| type_circuit
}
type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" }
// Declared in types/array_dimensions.rs
array_dimensions = {

View File

@ -1,29 +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;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::array_element))]
pub enum ArrayElement<'ast> {
Basic(DataType),
Tuple(TupleType<'ast>),
Circuit(CircuitType<'ast>),
SelfType(SelfType<'ast>),
}

View File

@ -16,7 +16,7 @@
use crate::{
ast::Rule,
types::{ArrayDimensions, ArrayElement},
types::{ArrayDimensions, Type},
SpanDef,
};
@ -27,7 +27,7 @@ use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[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())]
#[serde(with = "SpanDef")]

View File

@ -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::*;

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]; // initializer (incorrectly reversed ordering)

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]; // initializer (incorrectly reversed ordering)

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)]; // initializer (incorrectly reversed ordering)

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)]; // initializer (incorrectly reversed ordering)

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]; // initializer (incorrectly reversed ordering)

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]; // initializer (incorrectly reversed ordering)

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)]; // initializer (incorrectly reversed ordering)

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)]; // initializer (incorrectly reversed ordering)

View File

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

View File

@ -58,14 +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_inline() {
let program_bytes = include_bytes!("inline.leo");
@ -120,8 +112,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");
@ -238,3 +228,289 @@ 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_nested_value_nested_3x2() {
let program_bytes = include_bytes!("type_nested_value_nested_3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_nested_value_nested_3x2_fail() {
let program_bytes = include_bytes!("type_nested_value_nested_3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_nested_value_nested_4x3x2() {
let program_bytes = include_bytes!("type_nested_value_nested_4x3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_nested_value_nested_4x3x2_fail() {
let program_bytes = include_bytes!("type_nested_value_nested_4x3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_nested_value_tuple_3x2() {
let program_bytes = include_bytes!("type_nested_value_tuple_3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_nested_value_tuple_3x2_fail() {
let program_bytes = include_bytes!("type_nested_value_tuple_3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_nested_value_tuple_4x3x2() {
let program_bytes = include_bytes!("type_nested_value_tuple_4x3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_nested_value_tuple_4x3x2_fail() {
let program_bytes = include_bytes!("type_nested_value_tuple_4x3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_tuple_value_nested_3x2() {
let program_bytes = include_bytes!("type_tuple_value_nested_3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_tuple_value_nested_3x2_fail() {
let program_bytes = include_bytes!("type_tuple_value_nested_3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_tuple_value_nested_4x3x2() {
let program_bytes = include_bytes!("type_tuple_value_nested_4x3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_tuple_value_nested_4x3x2_fail() {
let program_bytes = include_bytes!("type_tuple_value_nested_4x3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_tuple_value_tuple_3x2() {
let program_bytes = include_bytes!("type_tuple_value_tuple_3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_tuple_value_tuple_3x2_fail() {
let program_bytes = include_bytes!("type_tuple_value_tuple_3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_type_tuple_value_tuple_4x3x2() {
let program_bytes = include_bytes!("type_tuple_value_tuple_4x3x2.leo");
let program = parse_program(program_bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_type_tuple_value_tuple_4x3x2_fail() {
let program_bytes = include_bytes!("type_tuple_value_tuple_4x3x2_fail.leo");
let program = parse_program(program_bytes).unwrap();
expect_compiler_error(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

@ -1,3 +1,3 @@
let main() {
function main() {
let a: [u8; -2] = [0u32; 2];
}

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

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

View File

@ -0,0 +1,3 @@
function main() {
const b: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering)
}

View File

@ -0,0 +1,10 @@
function main() {
const a = [[[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
const b: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4]; // initializer
console.assert(a == b);
}

View File

@ -0,0 +1,3 @@
function main() {
const b: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
}

View File

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

View File

@ -0,0 +1,3 @@
function main() {
const b: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering)
}

View File

@ -0,0 +1,10 @@
function main() {
const a = [[[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
const b: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)]; // initializer
console.assert(a == b);
}

View File

@ -0,0 +1,3 @@
function main() {
const b: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering)
}

View File

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

View File

@ -0,0 +1,3 @@
function main() {
const b: [u8; (2, 3)] = [[0; 2]; 3]; // initializer (incorrectly reversed ordering)
}

View File

@ -0,0 +1,10 @@
function main() {
const a = [[[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
const b: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4]; // initializer
console.assert(a == b);
}

View File

@ -0,0 +1,3 @@
function main() {
const b: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
}

View File

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

View File

@ -0,0 +1,3 @@
function main() {
const b: [u8; (2, 3)] = [0; (3, 2)]; // initializer (incorrectly reversed ordering)
}

View File

@ -0,0 +1,10 @@
function main() {
const a = [[[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
const b: [u8; (4, 3, 2)] = [0; (4, 3, 2)]; // initializer
console.assert(a == b);
}

View File

@ -0,0 +1,3 @@
function main() {
const b: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed order)
}

View File

@ -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];

View File

@ -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];

View File

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

View File

@ -53,12 +53,19 @@ 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(),
})
}
}
}
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

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

View File

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

View File

@ -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::*;

View File

@ -71,27 +71,27 @@ impl StateFile {
[state]
leaf_index: u32 = 0;
root: [u8; 32] = [0u8; 32];
root: [u8; 32] = [0; 32];
[[private]]
[record]
serial_number: [u8; 64] = [0u8; 64];
commitment: [u8; 32] = [0u8; 32];
serial_number: [u8; 64] = [0; 64];
commitment: [u8; 32] = [0; 32];
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
is_dummy: bool = false;
value: u64 = 5;
payload: [u8; 32] = [0u8; 32];
birth_program_id: [u8; 48] = [0u8; 48];
death_program_id: [u8; 48] = [0u8; 48];
serial_number_nonce: [u8; 32] = [0u8; 32];
commitment_randomness: [u8; 32] = [0u8; 32];
value: u64 = 0;
payload: [u8; 32] = [0; 32];
birth_program_id: [u8; 48] = [0; 48];
death_program_id: [u8; 48] = [0; 48];
serial_number_nonce: [u8; 32] = [0; 32];
commitment_randomness: [u8; 32] = [0; 32];
[state_leaf]
path: [u8; 128] = [0u8; 128];
memo: [u8; 32] = [0u8; 32];
path: [u8; 128] = [0; 128];
memo: [u8; 32] = [0; 32];
network_id: u8 = 0;
leaf_randomness: [u8; 32] = [0u8; 32];
leaf_randomness: [u8; 32] = [0; 32];
"#,
self.package_name
)

View File

@ -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,46 +106,56 @@ 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() {
if array_dimensions[0] != inline.expressions.len() {
return Err(InputParserError::array_inline_length(array_dimensions[0], inline));
}
array_type.dimensions = array_type.dimensions.next_dimension();
if outer_dimension != inline.expressions.len() {
return Err(InputParserError::array_inline_length(outer_dimension, inline));
}
};
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(
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());
// Return an error if the array type does not equal the array expression
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, initializer_dimensions)
}
}
pub(crate) fn from_array_initializer_tuple(
array_type: ArrayType,
initializer: ArrayInitializerExpression,
initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> {
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,
@ -154,14 +164,10 @@ impl InputValue {
));
}
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())?;
let value = InputValue::from_expression(array_element_type, *initializer.expression.clone())?;
let mut elements = vec![];
// 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];
@ -175,6 +181,42 @@ impl InputValue {
Ok(InputValue::Array(elements))
}
pub(crate) fn from_array_initializer_nested(
mut array_type: ArrayType,
initializer: ArrayInitializerExpression,
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];
// Return an error if the outer array dimension does not equal the number of array elements.
if current_array_dimension.ne(&current_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();
@ -198,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 {

View File

@ -15,9 +15,8 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier, IntegerType};
use leo_ast::types::{ArrayElement, ArrayType, CircuitType, DataType, TupleType, Type as AstType};
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,
@ -102,24 +101,13 @@ impl From<DataType> for Type {
impl<'ast> From<ArrayType<'ast>> for Type {
fn from(array_type: ArrayType<'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_array_dimensions(array_type.dimensions);
Type::Array(element_type, dimensions)
}
}
impl<'ast> From<ArrayElement<'ast>> for Type {
fn from(element: ArrayElement<'ast>) -> Self {
match element {
ArrayElement::Basic(type_) => Type::from(type_),
ArrayElement::Tuple(type_) => Type::from(type_),
ArrayElement::Circuit(type_) => Type::from(type_),
ArrayElement::SelfType(_type) => Type::SelfType,
}
}
}
impl<'ast> From<TupleType<'ast>> for Type {
fn from(tuple_type: TupleType<'ast>) -> Self {
let types = tuple_type.types.into_iter().map(|type_| Type::from(type_)).collect();
@ -162,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();