mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-25 19:22:01 +03:00
Merge pull request #347 from AleoHQ/feature/array-type
Feature/array type
This commit is contained in:
commit
eff7d9d599
@ -79,7 +79,7 @@ cd leo
|
|||||||
$ cargo build --release
|
$ 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
|
```bash
|
||||||
./target/release/leo
|
./target/release/leo
|
||||||
```
|
```
|
||||||
|
@ -197,15 +197,7 @@ type_self = { "Self" }
|
|||||||
type_circuit = { identifier }
|
type_circuit = { identifier }
|
||||||
|
|
||||||
// Declared in types/array_type.rs
|
// Declared in types/array_type.rs
|
||||||
type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" }
|
type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" }
|
||||||
|
|
||||||
// Declared in types/array_element.rs
|
|
||||||
array_element = {
|
|
||||||
type_self
|
|
||||||
| type_tuple
|
|
||||||
| type_data
|
|
||||||
| type_circuit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declared in types/array_dimensions.rs
|
// Declared in types/array_dimensions.rs
|
||||||
array_dimensions = {
|
array_dimensions = {
|
||||||
|
@ -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>),
|
|
||||||
}
|
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::Rule,
|
ast::Rule,
|
||||||
types::{ArrayDimensions, ArrayElement},
|
types::{ArrayDimensions, Type},
|
||||||
SpanDef,
|
SpanDef,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ use serde::Serialize;
|
|||||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||||
#[pest_ast(rule(Rule::type_array))]
|
#[pest_ast(rule(Rule::type_array))]
|
||||||
pub struct ArrayType<'ast> {
|
pub struct ArrayType<'ast> {
|
||||||
pub type_: ArrayElement<'ast>,
|
pub type_: Box<Type<'ast>>,
|
||||||
pub dimensions: ArrayDimensions<'ast>,
|
pub dimensions: ArrayDimensions<'ast>,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
#[serde(with = "SpanDef")]
|
#[serde(with = "SpanDef")]
|
||||||
|
@ -20,9 +20,6 @@ pub use address_type::*;
|
|||||||
pub mod array_dimensions;
|
pub mod array_dimensions;
|
||||||
pub use array_dimensions::*;
|
pub use array_dimensions::*;
|
||||||
|
|
||||||
pub mod array_element;
|
|
||||||
pub use array_element::*;
|
|
||||||
|
|
||||||
pub mod array_type;
|
pub mod array_type;
|
||||||
pub use array_type::*;
|
pub use array_type::*;
|
||||||
|
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[u8; 2]; 3] = [[0; 2]; 3];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[u8; 2]; 3] = [0; (3, 2)];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (3, 2)] = [[0; 2]; 3];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (3, 2)] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
|
2
compiler/tests/array/input/type_tuple_value_tuple_3x2.in
Normal file
2
compiler/tests/array/input/type_tuple_value_tuple_3x2.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (3, 2)] = [0; (3, 2)];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (3, 2)] = [0; (2, 3)]; // initializer (incorrectly reversed ordering)
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (4, 3, 2)] = [0; (4, 3, 2)];
|
@ -0,0 +1,2 @@
|
|||||||
|
[main]
|
||||||
|
a: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering)
|
@ -1,3 +1,3 @@
|
|||||||
function main(a: [u8; (3, 2)]) {
|
function main(a: [u8; (3, 2)]) {
|
||||||
console.assert(a == [[0u8; 2]; 3)]);
|
console.assert(a == [[0u8; 2]; 3]);
|
||||||
}
|
}
|
||||||
|
@ -58,14 +58,6 @@ fn test_registers() {
|
|||||||
|
|
||||||
// Expressions
|
// 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]
|
#[test]
|
||||||
fn test_inline() {
|
fn test_inline() {
|
||||||
let program_bytes = include_bytes!("inline.leo");
|
let program_bytes = include_bytes!("inline.leo");
|
||||||
@ -120,8 +112,6 @@ fn test_initializer_input_fail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
// TODO (howardwu): Add support for this syntax.
|
|
||||||
fn test_input_nested_3x2() {
|
fn test_input_nested_3x2() {
|
||||||
let program_bytes = include_bytes!("input_nested_3x2.leo");
|
let program_bytes = include_bytes!("input_nested_3x2.leo");
|
||||||
let input_bytes = include_bytes!("input/input_nested_3x2.in");
|
let input_bytes = include_bytes!("input/input_nested_3x2.in");
|
||||||
@ -238,3 +228,289 @@ fn test_slice() {
|
|||||||
|
|
||||||
assert_satisfied(program);
|
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);
|
||||||
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
let main() {
|
function main() {
|
||||||
let a: [u8; -2] = [0u32; 2];
|
let a: [u8; -2] = [0u32; 2];
|
||||||
}
|
}
|
5
compiler/tests/array/type_input_3x2.leo
Normal file
5
compiler/tests/array/type_input_3x2.leo
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
function main(a: [[u8; 2]; 3]) {
|
||||||
|
const b = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline
|
||||||
|
|
||||||
|
console.assert(a == b);
|
||||||
|
}
|
8
compiler/tests/array/type_input_4x3x2.leo
Normal file
8
compiler/tests/array/type_input_4x3x2.leo
Normal 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);
|
||||||
|
}
|
7
compiler/tests/array/type_nested_value_nested_3x2.leo
Normal file
7
compiler/tests/array/type_nested_value_nested_3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
10
compiler/tests/array/type_nested_value_nested_4x3x2.leo
Normal file
10
compiler/tests/array/type_nested_value_nested_4x3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
7
compiler/tests/array/type_nested_value_tuple_3x2.leo
Normal file
7
compiler/tests/array/type_nested_value_tuple_3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
10
compiler/tests/array/type_nested_value_tuple_4x3x2.leo
Normal file
10
compiler/tests/array/type_nested_value_tuple_4x3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
7
compiler/tests/array/type_tuple_value_nested_3x2.leo
Normal file
7
compiler/tests/array/type_tuple_value_nested_3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [u8; (2, 3)] = [[0; 2]; 3]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
10
compiler/tests/array/type_tuple_value_nested_4x3x2.leo
Normal file
10
compiler/tests/array/type_tuple_value_nested_4x3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
7
compiler/tests/array/type_tuple_value_tuple_3x2.leo
Normal file
7
compiler/tests/array/type_tuple_value_tuple_3x2.leo
Normal 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);
|
||||||
|
}
|
3
compiler/tests/array/type_tuple_value_tuple_3x2_fail.leo
Normal file
3
compiler/tests/array/type_tuple_value_tuple_3x2_fail.leo
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [u8; (2, 3)] = [0; (3, 2)]; // initializer (incorrectly reversed ordering)
|
||||||
|
}
|
10
compiler/tests/array/type_tuple_value_tuple_4x3x2.leo
Normal file
10
compiler/tests/array/type_tuple_value_tuple_4x3x2.leo
Normal 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);
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
function main() {
|
||||||
|
const b: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed order)
|
||||||
|
}
|
@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32];
|
|||||||
commitment_randomness: [u8; 32] = [0u8; 32];
|
commitment_randomness: [u8; 32] = [0u8; 32];
|
||||||
|
|
||||||
[state_leaf]
|
[state_leaf]
|
||||||
path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ];
|
path: [u8; 128] = [0u8; 128];
|
||||||
memo: [u8; 32] = [0u8; 32];
|
memo: [u8; 32] = [0u8; 32];
|
||||||
network_id: u8 = 0;
|
network_id: u8 = 0;
|
||||||
leaf_randomness: [u8; 32] = [0u8; 32];
|
leaf_randomness: [u8; 32] = [0u8; 32];
|
@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32];
|
|||||||
commitment_randomness: [u8; 32] = [0u8; 32];
|
commitment_randomness: [u8; 32] = [0u8; 32];
|
||||||
|
|
||||||
[state_leaf]
|
[state_leaf]
|
||||||
path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ];
|
path: [u8; 128] = [0u8; 128];
|
||||||
memo: [u8; 32] = [0u8; 32];
|
memo: [u8; 32] = [0u8; 32];
|
||||||
network_id: u8 = 0;
|
network_id: u8 = 0;
|
||||||
leaf_randomness: [u8; 32] = [0u8; 32];
|
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 }
|
type_data = { type_field | type_group | type_boolean | type_address | type_integer }
|
||||||
|
|
||||||
// Declared in types/array_type.rs
|
// Declared in types/array_type.rs
|
||||||
type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" }
|
type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" }
|
||||||
|
|
||||||
// Declared in types/array_element.rs
|
|
||||||
array_element = {
|
|
||||||
type_tuple
|
|
||||||
| type_data
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declared in types/array_dimensions.rs
|
// Declared in types/array_dimensions.rs
|
||||||
array_dimensions = {
|
array_dimensions = {
|
||||||
|
@ -53,12 +53,19 @@ impl<'ast> ArrayDimensions<'ast> {
|
|||||||
let old_dimension = multiple.numbers.clone();
|
let old_dimension = multiple.numbers.clone();
|
||||||
|
|
||||||
ArrayDimensions::Multiple(Multiple {
|
ArrayDimensions::Multiple(Multiple {
|
||||||
numbers: old_dimension[..old_dimension.len() - 1].to_vec(),
|
numbers: old_dimension[1..].to_vec(),
|
||||||
span: multiple.span.clone(),
|
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> {
|
impl<'ast> std::fmt::Display for ArrayDimensions<'ast> {
|
||||||
|
@ -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::{
|
use crate::{
|
||||||
ast::Rule,
|
ast::Rule,
|
||||||
types::{ArrayDimensions, ArrayElement},
|
types::{ArrayDimensions, Type},
|
||||||
};
|
};
|
||||||
|
|
||||||
use pest::Span;
|
use pest::Span;
|
||||||
@ -25,7 +25,7 @@ use pest_ast::FromPest;
|
|||||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||||
#[pest_ast(rule(Rule::type_array))]
|
#[pest_ast(rule(Rule::type_array))]
|
||||||
pub struct ArrayType<'ast> {
|
pub struct ArrayType<'ast> {
|
||||||
pub type_: ArrayElement<'ast>,
|
pub type_: Box<Type<'ast>>,
|
||||||
pub dimensions: ArrayDimensions<'ast>,
|
pub dimensions: ArrayDimensions<'ast>,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
pub span: Span<'ast>,
|
pub span: Span<'ast>,
|
||||||
|
@ -20,9 +20,6 @@ pub use address_type::*;
|
|||||||
pub mod array_dimensions;
|
pub mod array_dimensions;
|
||||||
pub use array_dimensions::*;
|
pub use array_dimensions::*;
|
||||||
|
|
||||||
pub mod array_element;
|
|
||||||
pub use array_element::*;
|
|
||||||
|
|
||||||
pub mod array_type;
|
pub mod array_type;
|
||||||
pub use array_type::*;
|
pub use array_type::*;
|
||||||
|
|
||||||
|
@ -71,27 +71,27 @@ impl StateFile {
|
|||||||
|
|
||||||
[state]
|
[state]
|
||||||
leaf_index: u32 = 0;
|
leaf_index: u32 = 0;
|
||||||
root: [u8; 32] = [0u8; 32];
|
root: [u8; 32] = [0; 32];
|
||||||
|
|
||||||
[[private]]
|
[[private]]
|
||||||
|
|
||||||
[record]
|
[record]
|
||||||
serial_number: [u8; 64] = [0u8; 64];
|
serial_number: [u8; 64] = [0; 64];
|
||||||
commitment: [u8; 32] = [0u8; 32];
|
commitment: [u8; 32] = [0; 32];
|
||||||
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
|
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
|
||||||
is_dummy: bool = false;
|
is_dummy: bool = false;
|
||||||
value: u64 = 5;
|
value: u64 = 0;
|
||||||
payload: [u8; 32] = [0u8; 32];
|
payload: [u8; 32] = [0; 32];
|
||||||
birth_program_id: [u8; 48] = [0u8; 48];
|
birth_program_id: [u8; 48] = [0; 48];
|
||||||
death_program_id: [u8; 48] = [0u8; 48];
|
death_program_id: [u8; 48] = [0; 48];
|
||||||
serial_number_nonce: [u8; 32] = [0u8; 32];
|
serial_number_nonce: [u8; 32] = [0; 32];
|
||||||
commitment_randomness: [u8; 32] = [0u8; 32];
|
commitment_randomness: [u8; 32] = [0; 32];
|
||||||
|
|
||||||
[state_leaf]
|
[state_leaf]
|
||||||
path: [u8; 128] = [0u8; 128];
|
path: [u8; 128] = [0; 128];
|
||||||
memo: [u8; 32] = [0u8; 32];
|
memo: [u8; 32] = [0; 32];
|
||||||
network_id: u8 = 0;
|
network_id: u8 = 0;
|
||||||
leaf_randomness: [u8; 32] = [0u8; 32];
|
leaf_randomness: [u8; 32] = [0; 32];
|
||||||
"#,
|
"#,
|
||||||
self.package_name
|
self.package_name
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,7 @@ use crate::{Expression as TypedExpression, GroupValue};
|
|||||||
use leo_input::{
|
use leo_input::{
|
||||||
errors::InputParserError,
|
errors::InputParserError,
|
||||||
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression},
|
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},
|
values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,46 +106,56 @@ impl InputValue {
|
|||||||
mut array_type: ArrayType,
|
mut array_type: ArrayType,
|
||||||
inline: ArrayInlineExpression,
|
inline: ArrayInlineExpression,
|
||||||
) -> Result<Self, InputParserError> {
|
) -> 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.
|
// 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();
|
array_type.dimensions = array_type.dimensions.next_dimension();
|
||||||
|
|
||||||
if outer_dimension != inline.expressions.len() {
|
let inner_array_type = if array_dimensions.len() == 1 {
|
||||||
return Err(InputParserError::array_inline_length(outer_dimension, inline));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let inner_array_type = if array_dimensions.len() == 0 {
|
|
||||||
// This is a single array
|
// This is a single array
|
||||||
match array_type.type_ {
|
*array_type.type_
|
||||||
ArrayElement::Basic(basic) => Type::Basic(basic),
|
|
||||||
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// This is a multi-dimensional array
|
// This is a multi-dimensional array
|
||||||
Type::Array(array_type)
|
Type::Array(array_type)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut values = vec![];
|
let mut elements = vec![];
|
||||||
for expression in inline.expressions.into_iter() {
|
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(
|
pub(crate) fn from_array_initializer(
|
||||||
array_type: ArrayType,
|
array_type: ArrayType,
|
||||||
initializer: ArrayInitializerExpression,
|
initializer: ArrayInitializerExpression,
|
||||||
) -> Result<Self, InputParserError> {
|
) -> 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());
|
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) {
|
if array_dimensions.ne(&initializer_dimensions) {
|
||||||
return Err(InputParserError::array_init_length(
|
return Err(InputParserError::array_init_length(
|
||||||
array_dimensions,
|
array_dimensions,
|
||||||
@ -154,14 +164,10 @@ impl InputValue {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_ = match array_type.type_ {
|
let value = InputValue::from_expression(array_element_type, *initializer.expression.clone())?;
|
||||||
ArrayElement::Basic(basic) => Type::Basic(basic),
|
|
||||||
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = InputValue::from_expression(type_, *initializer.expression.clone())?;
|
|
||||||
let mut elements = vec![];
|
let mut elements = vec![];
|
||||||
|
|
||||||
|
// Build the elements of the array using the `vec!` macro
|
||||||
for (i, dimension) in initializer_dimensions.into_iter().enumerate() {
|
for (i, dimension) in initializer_dimensions.into_iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
elements = vec![value.clone(); dimension];
|
elements = vec![value.clone(); dimension];
|
||||||
@ -175,6 +181,42 @@ impl InputValue {
|
|||||||
Ok(InputValue::Array(elements))
|
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(¤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> {
|
pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result<Self, InputParserError> {
|
||||||
let num_types = tuple_type.types_.len();
|
let num_types = tuple_type.types_.len();
|
||||||
let num_values = tuple.expressions.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 {
|
impl fmt::Display for InputValue {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -15,9 +15,8 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Expression, Identifier, IntegerType};
|
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::{
|
use leo_input::types::{
|
||||||
ArrayElement as InputArrayElement,
|
|
||||||
ArrayType as InputArrayType,
|
ArrayType as InputArrayType,
|
||||||
DataType as InputDataType,
|
DataType as InputDataType,
|
||||||
TupleType as InputTupleType,
|
TupleType as InputTupleType,
|
||||||
@ -102,24 +101,13 @@ impl From<DataType> for Type {
|
|||||||
|
|
||||||
impl<'ast> From<ArrayType<'ast>> for Type {
|
impl<'ast> From<ArrayType<'ast>> for Type {
|
||||||
fn from(array_type: ArrayType<'ast>) -> Self {
|
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);
|
let dimensions = Expression::get_array_dimensions(array_type.dimensions);
|
||||||
|
|
||||||
Type::Array(element_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 {
|
impl<'ast> From<TupleType<'ast>> for Type {
|
||||||
fn from(tuple_type: TupleType<'ast>) -> Self {
|
fn from(tuple_type: TupleType<'ast>) -> Self {
|
||||||
let types = tuple_type.types.into_iter().map(|type_| Type::from(type_)).collect();
|
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 {
|
impl<'ast> From<InputArrayType<'ast>> for Type {
|
||||||
fn from(array_type: InputArrayType<'ast>) -> Self {
|
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);
|
let dimensions = Expression::get_input_array_dimensions(array_type.dimensions);
|
||||||
|
|
||||||
Type::Array(element_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 {
|
impl<'ast> From<InputTupleType<'ast>> for Type {
|
||||||
fn from(tuple_type: InputTupleType<'ast>) -> Self {
|
fn from(tuple_type: InputTupleType<'ast>) -> Self {
|
||||||
let types = tuple_type.types_.into_iter().map(|type_| Type::from(type_)).collect();
|
let types = tuple_type.types_.into_iter().map(|type_| Type::from(type_)).collect();
|
||||||
|
Loading…
Reference in New Issue
Block a user