mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-17 23:02:47 +03:00
reconstruction
This commit is contained in:
parent
9252534122
commit
af5a708f8c
87
Cargo.lock
generated
87
Cargo.lock
generated
@ -11,9 +11,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
@ -186,7 +186,7 @@ dependencies = [
|
||||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array 0.12.4",
|
||||
"generic-array 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -575,7 +575,7 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
"generic-array 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -844,9 +844,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
@ -906,9 +906,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78"
|
||||
checksum = "6b67e66362108efccd8ac053abafc8b7a8d86a37e6e48fc4f6f7485eb5e9e6a5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@ -921,6 +921,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1160,9 +1161,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.48"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
|
||||
checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -1396,9 +1397,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.87"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@ -1885,9 +1886,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.6"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
|
||||
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@ -2289,9 +2290,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.1.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166"
|
||||
checksum = "c6af1b6204f89cf0069736daf8b852573e3bc34898eee600e95d3dd855c12e81"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
@ -2302,9 +2303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.1.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d"
|
||||
checksum = "31531d257baab426203cf81c5ce1b0b55159dda7ed602ac81b582ccd62265741"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@ -2393,9 +2394,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.64"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||
checksum = "43535db9747a4ba938c0ce0a98cc631a46ebf943c9e1d604e091df6007620bf6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -2835,9 +2836,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
checksum = "a2ada8616fad06a2d0c455adc530de4ef57605a8120cc65da9653e0e9623ca74"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2944,6 +2945,16 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-futures"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
|
||||
dependencies = [
|
||||
"pin-project",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.2"
|
||||
@ -3133,9 +3144,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.71"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
@ -3145,9 +3156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.71"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
|
||||
checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
@ -3160,9 +3171,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.21"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab"
|
||||
checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
@ -3172,9 +3183,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.71"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
|
||||
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
||||
dependencies = [
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -3182,9 +3193,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.71"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
|
||||
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
@ -3195,15 +3206,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.71"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
|
||||
checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.48"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
|
||||
checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@ -3282,9 +3293,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.5.11"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8264fcea9b7a036a4a5103d7153e988dbc2ebbafb34f68a3c2d404b6b82d74b6"
|
||||
checksum = "5a8977234acab718eb2820494b2f96cbb16004c19dddf88b7445b27381450997"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bzip2",
|
||||
|
@ -52,6 +52,9 @@ pub use self::input::*;
|
||||
pub mod program;
|
||||
pub use self::program::*;
|
||||
|
||||
pub mod reducer;
|
||||
pub use self::reducer::*;
|
||||
|
||||
pub mod statements;
|
||||
pub use self::statements::*;
|
||||
|
||||
|
33
ast/src/reducer/mod.rs
Normal file
33
ast/src/reducer/mod.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
mod monoid;
|
||||
pub use monoid::*;
|
||||
|
||||
mod monoidal_director;
|
||||
pub use monoidal_director::*;
|
||||
|
||||
mod monoidal_reducer;
|
||||
pub use monoidal_reducer::*;
|
||||
|
||||
mod reconstructing_reducer;
|
||||
pub use reconstructing_reducer::*;
|
||||
|
||||
mod reconstructing_director;
|
||||
pub use reconstructing_director::*;
|
68
ast/src/reducer/monoid.rs
Normal file
68
ast/src/reducer/monoid.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
pub trait Monoid: Default {
|
||||
fn append(self, other: Self) -> Self;
|
||||
|
||||
fn append_all(self, others: impl Iterator<Item = Self>) -> Self {
|
||||
let mut current = self;
|
||||
for item in others {
|
||||
current = current.append(item);
|
||||
}
|
||||
current
|
||||
}
|
||||
|
||||
fn append_option(self, other: Option<Self>) -> Self {
|
||||
match other {
|
||||
None => self,
|
||||
Some(other) => self.append(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecAppend<T>(Vec<T>);
|
||||
|
||||
impl<T> Default for VecAppend<T> {
|
||||
fn default() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Monoid for VecAppend<T> {
|
||||
fn append(mut self, other: Self) -> Self {
|
||||
self.0.extend(other.0);
|
||||
VecAppend(self.0)
|
||||
}
|
||||
|
||||
fn append_all(mut self, others: impl Iterator<Item = Self>) -> Self {
|
||||
let all: Vec<Vec<T>> = others.map(|x| x.0).collect();
|
||||
let total_size = all.iter().fold(0, |acc, v| acc + v.len());
|
||||
self.0.reserve(total_size);
|
||||
for item in all.into_iter() {
|
||||
self.0.extend(item);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Into<Vec<T>> for VecAppend<T> {
|
||||
fn into(self) -> Vec<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
450
ast/src/reducer/monoidal_director.rs
Normal file
450
ast/src/reducer/monoidal_director.rs
Normal file
@ -0,0 +1,450 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
use crate::{
|
||||
reducer::*,
|
||||
AssigneeAccess,
|
||||
Circuit,
|
||||
CircuitMember,
|
||||
ConditionalStatement,
|
||||
ConsoleFunction,
|
||||
Expression,
|
||||
Function,
|
||||
FunctionInput,
|
||||
FunctionInputVariable,
|
||||
GroupCoordinate,
|
||||
GroupValue,
|
||||
Identifier,
|
||||
ImportStatement,
|
||||
IntegerType,
|
||||
Monoid,
|
||||
PackageOrPackages,
|
||||
Program,
|
||||
SpreadOrExpression,
|
||||
Statement,
|
||||
TestFunction,
|
||||
Type,
|
||||
ValueExpression,
|
||||
VariableName,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct MonoidalDirector<T: Monoid, R: MonoidalReducer<T>> {
|
||||
reducer: R,
|
||||
_monoid: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Monoid, R: MonoidalReducer<T>> MonoidalDirector<T, R> {
|
||||
pub fn new(reducer: R) -> Self {
|
||||
Self {
|
||||
reducer,
|
||||
_monoid: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reduce_program(&mut self, program: &Program) -> T {
|
||||
let inputs = program
|
||||
.expected_input
|
||||
.iter()
|
||||
.map(|x| self.reduce_function_input(x))
|
||||
.collect();
|
||||
let imports = program
|
||||
.imports
|
||||
.iter()
|
||||
.map(|x| self.reduce_import_statement(x))
|
||||
.collect();
|
||||
let circuits = program
|
||||
.circuits
|
||||
.iter()
|
||||
.map(|(identifier, circuit)| {
|
||||
(
|
||||
identifier.name.clone(),
|
||||
(self.reduce_identifier(identifier), self.reduce_circuit(circuit)),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let functions = program
|
||||
.functions
|
||||
.iter()
|
||||
.map(|(identifier, function)| {
|
||||
(
|
||||
identifier.name.clone(),
|
||||
(self.reduce_identifier(identifier), self.reduce_function(function)),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let test_functions = program
|
||||
.tests
|
||||
.iter()
|
||||
.map(|(identifier, test_function)| {
|
||||
(
|
||||
identifier.name.clone(),
|
||||
(
|
||||
self.reduce_identifier(identifier),
|
||||
self.reduce_test_function(test_function),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.reducer
|
||||
.reduce_program(program, inputs, imports, circuits, functions, test_functions)
|
||||
}
|
||||
|
||||
pub fn reduce_function_input(&mut self, input: &FunctionInput) -> T {
|
||||
let item = match input {
|
||||
FunctionInput::InputKeyword(_) => FunctionInputItem::InputKeyword,
|
||||
FunctionInput::SelfKeyword(_) => FunctionInputItem::SelfKeyword,
|
||||
FunctionInput::MutSelfKeyword(_) => FunctionInputItem::MutSelfKeyword,
|
||||
FunctionInput::Variable(function_input_variable) => {
|
||||
FunctionInputItem::Variable(self.reduce_function_input_variable(function_input_variable))
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_function_input(input, item)
|
||||
}
|
||||
|
||||
pub fn reduce_import_statement(&mut self, import: &ImportStatement) -> T {
|
||||
let package = self.reduce_package(&import.package_or_packages);
|
||||
|
||||
self.reducer.reduce_import_statement(import, package)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit(&mut self, circuit: &Circuit) -> T {
|
||||
let circuit_name = self.reduce_identifier(&circuit.circuit_name);
|
||||
let members = circuit.members.iter().map(|x| self.reduce_circuit_member(x)).collect();
|
||||
|
||||
self.reducer.reduce_circuit(circuit, circuit_name, members)
|
||||
}
|
||||
|
||||
pub fn reduce_function(&mut self, function: &Function) -> T {
|
||||
let identifier = self.reduce_identifier(&function.identifier);
|
||||
let input = function.input.iter().map(|x| self.reduce_function_input(x)).collect();
|
||||
let output = function.output.as_ref().map(|x| self.reduce_type(x));
|
||||
let statements = function
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|x| self.reduce_statement(x))
|
||||
.collect();
|
||||
|
||||
self.reducer
|
||||
.reduce_function(function, identifier, input, output, statements)
|
||||
}
|
||||
|
||||
pub fn reduce_test_function(&mut self, test_function: &TestFunction) -> T {
|
||||
let function = self.reduce_function(&test_function.function);
|
||||
let input_file = test_function.input_file.as_ref().map(|x| self.reduce_identifier(x));
|
||||
|
||||
self.reducer.reduce_test_function(test_function, function, input_file)
|
||||
}
|
||||
|
||||
pub fn reduce_identifier(&mut self, identifier: &Identifier) -> T {
|
||||
self.reducer.reduce_identifier(identifier)
|
||||
}
|
||||
|
||||
pub fn reduce_integer_type(&mut self, integer_type: &IntegerType) -> T {
|
||||
self.reducer.reduce_integer_type(integer_type)
|
||||
}
|
||||
|
||||
pub fn reduce_function_input_variable(&mut self, function_input_variable: &FunctionInputVariable) -> T {
|
||||
let identifier = self.reduce_identifier(&function_input_variable.identifier);
|
||||
let type_ = self.reduce_type(&function_input_variable.type_);
|
||||
|
||||
self.reducer
|
||||
.reduce_function_input_variable(function_input_variable, identifier, type_)
|
||||
}
|
||||
|
||||
pub fn reduce_type(&mut self, type_: &Type) -> T {
|
||||
let items = match type_ {
|
||||
Type::Array(type_, _) => TypeMonoidItems::Array(self.reduce_type(type_)),
|
||||
Type::Tuple(types) => TypeMonoidItems::Tuple(types.iter().map(|x| self.reduce_type(x)).collect()),
|
||||
Type::Circuit(identifier) => TypeMonoidItems::Identifier(self.reduce_identifier(identifier)),
|
||||
_ => TypeMonoidItems::None,
|
||||
};
|
||||
|
||||
self.reducer.reduce_type(type_, items)
|
||||
}
|
||||
|
||||
pub fn reduce_package(&mut self, package_or_packages: &PackageOrPackages) -> T {
|
||||
match package_or_packages {
|
||||
PackageOrPackages::Package(package) => {
|
||||
let name = self.reduce_identifier(&package.name);
|
||||
|
||||
self.reducer.reduce_package(package, name)
|
||||
}
|
||||
PackageOrPackages::Packages(packages) => {
|
||||
let name = self.reduce_identifier(&packages.name);
|
||||
|
||||
self.reducer.reduce_packages(packages, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> T {
|
||||
let items = match circuit_member {
|
||||
CircuitMember::CircuitVariable(identifier, type_) => CircuitMemberMonoidItems::Variable {
|
||||
identifier: self.reduce_identifier(identifier),
|
||||
type_: self.reduce_type(type_),
|
||||
},
|
||||
CircuitMember::CircuitFunction(function) => {
|
||||
CircuitMemberMonoidItems::Function(self.reduce_function(function))
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_circuit_member(circuit_member, items)
|
||||
}
|
||||
|
||||
pub fn reduce_statement(&mut self, statement: &Statement) -> T {
|
||||
let items = match statement {
|
||||
Statement::Return(ret) => StatementMonoidItems::Return(self.reduce_expression(&ret.expression)),
|
||||
Statement::Definition(definition) => StatementMonoidItems::Definition {
|
||||
variables: self.reduce_variable_names(&definition.variable_names),
|
||||
expression: self.reduce_expression(&definition.value),
|
||||
},
|
||||
Statement::Assign(assign) => StatementMonoidItems::Assign {
|
||||
assignee: self.reduce_identifier(&assign.assignee.identifier),
|
||||
assignee_accesses: assign
|
||||
.assignee
|
||||
.accesses
|
||||
.iter()
|
||||
.map(|x| self.reduce_assignee_access(x))
|
||||
.collect(),
|
||||
expression: self.reduce_expression(&assign.value),
|
||||
},
|
||||
Statement::Conditional(conditional) => {
|
||||
StatementMonoidItems::Conditional(self.reduce_conditional_statement(conditional))
|
||||
}
|
||||
Statement::Iteration(iteration) => StatementMonoidItems::Iteration {
|
||||
identifier: self.reduce_identifier(&iteration.variable),
|
||||
start: self.reduce_expression(&iteration.start),
|
||||
stop: self.reduce_expression(&iteration.stop),
|
||||
statements: iteration
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|x| self.reduce_statement(x))
|
||||
.collect(),
|
||||
},
|
||||
Statement::Console(console) => match &console.function {
|
||||
ConsoleFunction::Assert(expression) => {
|
||||
StatementMonoidItems::ConsoleAssert(self.reduce_expression(expression))
|
||||
}
|
||||
ConsoleFunction::Debug(formatted_string)
|
||||
| ConsoleFunction::Error(formatted_string)
|
||||
| ConsoleFunction::Log(formatted_string) => StatementMonoidItems::ConsoleFormat(
|
||||
formatted_string
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|parameter| self.reduce_expression(¶meter))
|
||||
.collect(),
|
||||
),
|
||||
},
|
||||
Statement::Expression(statement) => {
|
||||
StatementMonoidItems::Expression(self.reduce_expression(&statement.expression))
|
||||
}
|
||||
Statement::Block(block) => StatementMonoidItems::Statements(
|
||||
block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| self.reduce_statement(statement))
|
||||
.collect(),
|
||||
),
|
||||
};
|
||||
|
||||
self.reducer.reduce_statement(statement, items)
|
||||
}
|
||||
|
||||
pub fn reduce_assignee_access(&mut self, assignee_access: &AssigneeAccess) -> T {
|
||||
let item = match assignee_access {
|
||||
AssigneeAccess::ArrayRange(start, stop) => {
|
||||
let start_item = start.as_ref().map(|x| self.reduce_expression(x));
|
||||
let stop_item = stop.as_ref().map(|x| self.reduce_expression(x));
|
||||
AssigneeAccessItem::Array(RangeItem::Range(start_item, stop_item))
|
||||
}
|
||||
AssigneeAccess::ArrayIndex(expression) => {
|
||||
AssigneeAccessItem::Array(RangeItem::Index(self.reduce_expression(expression)))
|
||||
}
|
||||
AssigneeAccess::Tuple(_, _) => AssigneeAccessItem::Tuple,
|
||||
AssigneeAccess::Member(identifier) => {
|
||||
let identifier = self.reduce_identifier(identifier);
|
||||
AssigneeAccessItem::Member(identifier)
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_assignee_access(assignee_access, item)
|
||||
}
|
||||
|
||||
pub fn reduce_conditional_statement(&mut self, statement: &ConditionalStatement) -> T {
|
||||
let condition = self.reduce_expression(&statement.condition);
|
||||
let statements = statement
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|x| self.reduce_statement(x))
|
||||
.collect();
|
||||
let next = statement.next.as_ref().map(|x| self.reduce_statement(x));
|
||||
|
||||
self.reducer
|
||||
.reduce_conditional_statement(statement, condition, statements, next)
|
||||
}
|
||||
|
||||
pub fn reduce_variable_name(&mut self, variable_name: &VariableName) -> T {
|
||||
let identifier = self.reduce_identifier(&variable_name.identifier);
|
||||
|
||||
self.reducer.reduce_variable_name(variable_name, identifier)
|
||||
}
|
||||
|
||||
pub fn reduce_variable_names(&mut self, variable_names: &[VariableName]) -> T {
|
||||
let names = variable_names
|
||||
.iter()
|
||||
.map(|variable_name| self.reduce_variable_name(variable_name))
|
||||
.collect();
|
||||
|
||||
self.reducer.reduce_variable_names(names)
|
||||
}
|
||||
|
||||
pub fn reduce_group_coordinate(&mut self, group_coordinate: &GroupCoordinate) -> T {
|
||||
self.reducer.reduce_group_coordinate(group_coordinate)
|
||||
}
|
||||
|
||||
pub fn reduce_value_expression(&mut self, value_expression: &ValueExpression) -> T {
|
||||
let item = match value_expression {
|
||||
ValueExpression::Address(_, _) => ValueExpressionMonoidItems::Address,
|
||||
ValueExpression::Boolean(_, _) => ValueExpressionMonoidItems::Boolean,
|
||||
ValueExpression::Field(_, _) => ValueExpressionMonoidItems::Field,
|
||||
ValueExpression::Group(group_value) => match group_value.as_ref() {
|
||||
GroupValue::Single(_, _) => ValueExpressionMonoidItems::GroupSingle,
|
||||
GroupValue::Tuple(tuple) => {
|
||||
let x = self.reduce_group_coordinate(&tuple.x);
|
||||
let y = self.reduce_group_coordinate(&tuple.y);
|
||||
ValueExpressionMonoidItems::GroupTuple(x, y)
|
||||
}
|
||||
},
|
||||
ValueExpression::Implicit(_, _) => ValueExpressionMonoidItems::Implicit,
|
||||
ValueExpression::Integer(integer_type, _, _) => {
|
||||
ValueExpressionMonoidItems::Integer(self.reduce_integer_type(integer_type))
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_value_expression(value_expression, item)
|
||||
}
|
||||
|
||||
pub fn reduce_expression(&mut self, expression: &Expression) -> T {
|
||||
let items = match expression {
|
||||
Expression::Identifier(identifier) => ExpressionMonoidItems::Unary(self.reduce_identifier(identifier)),
|
||||
Expression::Value(value) => ExpressionMonoidItems::Value(self.reduce_value_expression(value)),
|
||||
Expression::Binary(binary) => {
|
||||
let left = self.reduce_expression(&binary.left);
|
||||
let right = self.reduce_expression(&binary.right);
|
||||
ExpressionMonoidItems::Binary(left, right)
|
||||
}
|
||||
Expression::Unary(unary) => ExpressionMonoidItems::Unary(self.reduce_expression(&unary.inner)),
|
||||
Expression::Ternary(ternary) => {
|
||||
let condition = self.reduce_expression(&ternary.condition);
|
||||
let left = self.reduce_expression(&ternary.if_true);
|
||||
let right = self.reduce_expression(&ternary.if_false);
|
||||
ExpressionMonoidItems::Triary(condition, left, right)
|
||||
}
|
||||
Expression::ArrayInline(array_inline) => ExpressionMonoidItems::Var(
|
||||
array_inline
|
||||
.elements
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
SpreadOrExpression::Expression(expression) | SpreadOrExpression::Spread(expression) => {
|
||||
self.reduce_expression(expression)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
Expression::ArrayInit(array_init) => {
|
||||
let element = self.reduce_expression(&array_init.element);
|
||||
ExpressionMonoidItems::Unary(element)
|
||||
}
|
||||
Expression::ArrayAccess(array_access) => {
|
||||
let array = self.reduce_expression(&array_access.array);
|
||||
let index = self.reduce_expression(&array_access.index);
|
||||
ExpressionMonoidItems::ArrayAccess(array, index)
|
||||
}
|
||||
Expression::ArrayRangeAccess(array_range_access) => {
|
||||
let array = self.reduce_expression(&array_range_access.array);
|
||||
|
||||
match (array_range_access.left.as_ref(), array_range_access.right.as_ref()) {
|
||||
(Some(left_expression), Some(right_expression)) => {
|
||||
let left = self.reduce_expression(&left_expression);
|
||||
let right = self.reduce_expression(&right_expression);
|
||||
ExpressionMonoidItems::Triary(array, left, right)
|
||||
}
|
||||
(Some(left_expression), None) => {
|
||||
let left = self.reduce_expression(&left_expression);
|
||||
ExpressionMonoidItems::Binary(array, left)
|
||||
}
|
||||
(None, Some(right_expression)) => {
|
||||
let right = self.reduce_expression(&right_expression);
|
||||
ExpressionMonoidItems::Binary(array, right)
|
||||
}
|
||||
(None, None) => ExpressionMonoidItems::Unary(array),
|
||||
}
|
||||
}
|
||||
Expression::TupleInit(tuple_init) => {
|
||||
let element_items = tuple_init.elements.iter().map(|x| self.reduce_expression(x)).collect();
|
||||
ExpressionMonoidItems::Var(element_items)
|
||||
}
|
||||
Expression::TupleAccess(tuple_access) => {
|
||||
let tuple_access = self.reduce_expression(&tuple_access.tuple);
|
||||
ExpressionMonoidItems::Unary(tuple_access)
|
||||
}
|
||||
|
||||
Expression::CircuitInit(circuit_init) => {
|
||||
let defined_circuit_name_item = self.reduce_identifier(&circuit_init.name);
|
||||
let members = circuit_init
|
||||
.members
|
||||
.iter()
|
||||
.map(|definition| {
|
||||
let definition_identifier = self.reduce_identifier(&definition.identifier);
|
||||
let definition_expression = self.reduce_expression(&definition.expression);
|
||||
(definition_identifier, definition_expression)
|
||||
})
|
||||
.collect();
|
||||
|
||||
ExpressionMonoidItems::Circuit(defined_circuit_name_item, members)
|
||||
}
|
||||
Expression::CircuitMemberAccess(circuit_member_access) => {
|
||||
let declared_circuit_name = self.reduce_expression(&circuit_member_access.circuit);
|
||||
let circuit_member_name = self.reduce_identifier(&circuit_member_access.name);
|
||||
|
||||
ExpressionMonoidItems::Binary(declared_circuit_name, circuit_member_name)
|
||||
}
|
||||
Expression::CircuitStaticFunctionAccess(circuit_static_func_access) => {
|
||||
let declared_circuit_name = self.reduce_expression(&circuit_static_func_access.circuit);
|
||||
let circuit_static_function_name = self.reduce_identifier(&circuit_static_func_access.name);
|
||||
|
||||
ExpressionMonoidItems::Binary(declared_circuit_name, circuit_static_function_name)
|
||||
}
|
||||
|
||||
Expression::Call(call) => {
|
||||
let function = self.reduce_expression(&call.function);
|
||||
let function_arguments = call.arguments.iter().map(|x| self.reduce_expression(x)).collect();
|
||||
|
||||
ExpressionMonoidItems::FunctionCall(function, function_arguments)
|
||||
}
|
||||
};
|
||||
self.reducer.reduce_expression(expression, items)
|
||||
}
|
||||
}
|
317
ast/src/reducer/monoidal_reducer.rs
Normal file
317
ast/src/reducer/monoidal_reducer.rs
Normal file
@ -0,0 +1,317 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
use crate::{
|
||||
AssigneeAccess,
|
||||
Circuit,
|
||||
CircuitMember,
|
||||
ConditionalStatement,
|
||||
Expression,
|
||||
Function,
|
||||
FunctionInput,
|
||||
FunctionInputVariable,
|
||||
GroupCoordinate,
|
||||
Identifier,
|
||||
ImportStatement,
|
||||
IntegerType,
|
||||
Monoid,
|
||||
Package,
|
||||
Packages,
|
||||
Program,
|
||||
Statement,
|
||||
TestFunction,
|
||||
Type,
|
||||
ValueExpression,
|
||||
VariableName,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub enum TypeMonoidItems<T: Monoid> {
|
||||
None,
|
||||
Tuple(Vec<T>),
|
||||
Array(T),
|
||||
Identifier(T),
|
||||
}
|
||||
|
||||
pub enum CircuitMemberMonoidItems<T: Monoid> {
|
||||
Variable { identifier: T, type_: T },
|
||||
Function(T),
|
||||
}
|
||||
|
||||
pub enum StatementMonoidItems<T: Monoid> {
|
||||
Return(T),
|
||||
Definition {
|
||||
variables: T,
|
||||
expression: T,
|
||||
},
|
||||
Assign {
|
||||
assignee: T,
|
||||
assignee_accesses: Vec<T>,
|
||||
expression: T,
|
||||
},
|
||||
Conditional(T),
|
||||
Iteration {
|
||||
identifier: T,
|
||||
start: T,
|
||||
stop: T,
|
||||
statements: Vec<T>,
|
||||
},
|
||||
ConsoleAssert(T),
|
||||
ConsoleFormat(Vec<T>),
|
||||
Expression(T),
|
||||
Statements(Vec<T>),
|
||||
}
|
||||
|
||||
pub enum AssigneeAccessItem<T: Monoid> {
|
||||
Array(RangeItem<T>),
|
||||
Tuple,
|
||||
Member(T),
|
||||
}
|
||||
|
||||
pub enum RangeItem<T: Monoid> {
|
||||
Range(Option<T>, Option<T>),
|
||||
Index(T),
|
||||
}
|
||||
|
||||
pub enum ExpressionMonoidItems<T: Monoid> {
|
||||
Empty,
|
||||
Unary(T),
|
||||
Binary(T, T),
|
||||
Triary(T, T, T),
|
||||
FunctionCall(T, Vec<T>),
|
||||
ArrayAccess(T, T),
|
||||
Circuit(T, Vec<(T, T)>),
|
||||
Var(Vec<T>),
|
||||
Value(T),
|
||||
}
|
||||
|
||||
pub enum ConditionStatementNextItem<T: Monoid> {
|
||||
Nested(T),
|
||||
End(Vec<T>),
|
||||
}
|
||||
|
||||
pub enum FunctionInputItem<T: Monoid> {
|
||||
InputKeyword,
|
||||
SelfKeyword,
|
||||
MutSelfKeyword,
|
||||
Variable(T),
|
||||
}
|
||||
|
||||
pub enum ValueExpressionMonoidItems<T: Monoid> {
|
||||
Address,
|
||||
Boolean,
|
||||
Field,
|
||||
GroupSingle,
|
||||
GroupTuple(T, T),
|
||||
Implicit,
|
||||
Integer(T),
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub trait MonoidalReducer<T: Monoid> {
|
||||
fn reduce_program(
|
||||
&mut self,
|
||||
program: &Program,
|
||||
expected_input: Vec<T>,
|
||||
imports: Vec<T>,
|
||||
circuits: IndexMap<String, (T, T)>,
|
||||
functions: IndexMap<String, (T, T)>,
|
||||
tests: IndexMap<String, (T, T)>,
|
||||
) -> T {
|
||||
let mut items = T::default()
|
||||
.append_all(expected_input.into_iter())
|
||||
.append_all(imports.into_iter());
|
||||
|
||||
for (_, (identifier, value)) in circuits.into_iter() {
|
||||
items = items.append(identifier).append(value);
|
||||
}
|
||||
for (_, (identifier, value)) in functions.into_iter() {
|
||||
items = items.append(identifier).append(value);
|
||||
}
|
||||
for (_, (identifier, value)) in tests.into_iter() {
|
||||
items = items.append(identifier).append(value);
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
fn reduce_function_input(&mut self, input: &FunctionInput, item: FunctionInputItem<T>) -> T {
|
||||
match item {
|
||||
FunctionInputItem::InputKeyword | FunctionInputItem::SelfKeyword | FunctionInputItem::MutSelfKeyword => {
|
||||
T::default()
|
||||
}
|
||||
FunctionInputItem::Variable(variable) => variable,
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_import_statement(&mut self, import: &ImportStatement, package: T) -> T {
|
||||
package
|
||||
}
|
||||
|
||||
fn reduce_circuit(&mut self, circuit: &Circuit, circuit_name: T, members: Vec<T>) -> T {
|
||||
circuit_name.append_all(members.into_iter())
|
||||
}
|
||||
|
||||
fn reduce_function(
|
||||
&mut self,
|
||||
function: &Function,
|
||||
identifier: T,
|
||||
input: Vec<T>,
|
||||
output: Option<T>,
|
||||
statements: Vec<T>,
|
||||
) -> T {
|
||||
identifier
|
||||
.append_all(input.into_iter())
|
||||
.append_option(output)
|
||||
.append_all(statements.into_iter())
|
||||
}
|
||||
|
||||
fn reduce_test_function(&mut self, test_function: &TestFunction, function: T, input_file: Option<T>) -> T {
|
||||
function.append_option(input_file)
|
||||
}
|
||||
|
||||
fn reduce_identifier(&mut self, identifier: &Identifier) -> T {
|
||||
T::default()
|
||||
}
|
||||
|
||||
fn reduce_integer_type(&mut self, integer_type: &IntegerType) -> T {
|
||||
T::default()
|
||||
}
|
||||
|
||||
fn reduce_function_input_variable(
|
||||
&mut self,
|
||||
function_input_variable: &FunctionInputVariable,
|
||||
identifier: T,
|
||||
type_: T,
|
||||
) -> T {
|
||||
identifier.append(type_)
|
||||
}
|
||||
|
||||
fn reduce_type(&mut self, type_: &Type, items: TypeMonoidItems<T>) -> T {
|
||||
match items {
|
||||
TypeMonoidItems::Tuple(items) => T::default().append_all(items.into_iter()),
|
||||
TypeMonoidItems::Array(item) => item,
|
||||
TypeMonoidItems::Identifier(item) => item,
|
||||
TypeMonoidItems::None => T::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_packages(&mut self, packages: &Packages, name: T) -> T {
|
||||
name
|
||||
}
|
||||
|
||||
fn reduce_package(&mut self, package: &Package, name: T) -> T {
|
||||
name
|
||||
}
|
||||
|
||||
fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember, items: CircuitMemberMonoidItems<T>) -> T {
|
||||
match items {
|
||||
CircuitMemberMonoidItems::Variable { identifier, type_ } => identifier.append(type_),
|
||||
CircuitMemberMonoidItems::Function(identifier) => identifier,
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_statement(&mut self, statement: &Statement, items: StatementMonoidItems<T>) -> T {
|
||||
match items {
|
||||
StatementMonoidItems::Return(expression) => expression,
|
||||
StatementMonoidItems::Definition { variables, expression } => variables.append(expression),
|
||||
StatementMonoidItems::Assign {
|
||||
assignee,
|
||||
assignee_accesses,
|
||||
expression,
|
||||
} => assignee.append_all(assignee_accesses.into_iter()).append(expression),
|
||||
StatementMonoidItems::Conditional(conditional) => conditional,
|
||||
StatementMonoidItems::Iteration {
|
||||
identifier,
|
||||
start,
|
||||
stop,
|
||||
statements,
|
||||
} => identifier.append(start).append(stop).append_all(statements.into_iter()),
|
||||
StatementMonoidItems::ConsoleAssert(expression) => expression,
|
||||
StatementMonoidItems::ConsoleFormat(parameters) => T::default().append_all(parameters.into_iter()),
|
||||
StatementMonoidItems::Expression(expression) => expression,
|
||||
StatementMonoidItems::Statements(statements) => T::default().append_all(statements.into_iter()),
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_assignee_access(&mut self, assignee_access: &AssigneeAccess, item: AssigneeAccessItem<T>) -> T {
|
||||
match item {
|
||||
AssigneeAccessItem::Array(assignee) => match assignee {
|
||||
RangeItem::Index(index) => index,
|
||||
RangeItem::Range(start, stop) => T::default().append_option(start).append_option(stop),
|
||||
},
|
||||
AssigneeAccessItem::Tuple => T::default(),
|
||||
AssigneeAccessItem::Member(identifier) => identifier,
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_conditional_statement(
|
||||
&mut self,
|
||||
statement: &ConditionalStatement,
|
||||
condition: T,
|
||||
statements: Vec<T>,
|
||||
next: Option<T>,
|
||||
) -> T {
|
||||
condition.append_all(statements.into_iter()).append_option(next)
|
||||
}
|
||||
|
||||
fn reduce_variable_name(&mut self, variable_name: &VariableName, identifier: T) -> T {
|
||||
identifier
|
||||
}
|
||||
|
||||
fn reduce_variable_names(&mut self, names: Vec<T>) -> T {
|
||||
T::default().append_all(names.into_iter())
|
||||
}
|
||||
|
||||
fn reduce_group_coordinate(&mut self, group_coordinate: &GroupCoordinate) -> T {
|
||||
T::default()
|
||||
}
|
||||
|
||||
fn reduce_value_expression(
|
||||
&mut self,
|
||||
value_expression: &ValueExpression,
|
||||
value: ValueExpressionMonoidItems<T>,
|
||||
) -> T {
|
||||
match value {
|
||||
ValueExpressionMonoidItems::GroupTuple(x, y) => x.append(y),
|
||||
ValueExpressionMonoidItems::Integer(integer_type) => integer_type,
|
||||
_ => T::default(),
|
||||
}
|
||||
}
|
||||
|
||||
// please be careful matching on array access/range expressions, they can be ExpressionMonoidItems::BiTriary or ExpressionMonoidItems::Binary
|
||||
fn reduce_expression(&mut self, expression: &Expression, items: ExpressionMonoidItems<T>) -> T {
|
||||
match items {
|
||||
ExpressionMonoidItems::Empty => T::default(),
|
||||
ExpressionMonoidItems::Unary(expression) => expression,
|
||||
ExpressionMonoidItems::Binary(left, right) => left.append(right),
|
||||
ExpressionMonoidItems::Triary(left, center, right) => left.append(center).append(right),
|
||||
ExpressionMonoidItems::ArrayAccess(identifier, index) => identifier.append(index),
|
||||
ExpressionMonoidItems::FunctionCall(identifier, arguments) => identifier.append_all(arguments.into_iter()),
|
||||
ExpressionMonoidItems::Circuit(identifier, arguments) => {
|
||||
let mut out = identifier;
|
||||
for (key, value) in arguments.into_iter() {
|
||||
out = out.append(key).append(value);
|
||||
}
|
||||
out
|
||||
}
|
||||
ExpressionMonoidItems::Var(items) => T::default().append_all(items.into_iter()),
|
||||
ExpressionMonoidItems::Value(value) => value,
|
||||
}
|
||||
}
|
||||
}
|
518
ast/src/reducer/reconstructing_director.rs
Normal file
518
ast/src/reducer/reconstructing_director.rs
Normal file
@ -0,0 +1,518 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
use crate::{
|
||||
ArrayAccessExpression,
|
||||
ArrayInitExpression,
|
||||
ArrayInlineExpression,
|
||||
ArrayRangeAccessExpression,
|
||||
AssignStatement,
|
||||
Assignee,
|
||||
AssigneeAccess,
|
||||
BinaryExpression,
|
||||
Block,
|
||||
CallExpression,
|
||||
Circuit,
|
||||
CircuitImpliedVariableDefinition,
|
||||
CircuitInitExpression,
|
||||
CircuitMember,
|
||||
CircuitMemberAccessExpression,
|
||||
CircuitStaticFunctionAccessExpression,
|
||||
ConditionalStatement,
|
||||
ConsoleFunction,
|
||||
ConsoleStatement,
|
||||
DefinitionStatement,
|
||||
Expression,
|
||||
ExpressionStatement,
|
||||
FormattedString,
|
||||
Function,
|
||||
FunctionInput,
|
||||
FunctionInputVariable,
|
||||
Identifier,
|
||||
ImportStatement,
|
||||
IterationStatement,
|
||||
PackageOrPackages,
|
||||
Program,
|
||||
ReconstructingReducer,
|
||||
ReturnStatement,
|
||||
SpreadOrExpression,
|
||||
Statement,
|
||||
TernaryExpression,
|
||||
TestFunction,
|
||||
TupleAccessExpression,
|
||||
TupleInitExpression,
|
||||
Type,
|
||||
UnaryExpression,
|
||||
VariableName,
|
||||
};
|
||||
|
||||
pub struct ReconstructingDirector<R: ReconstructingReducer> {
|
||||
reducer: R,
|
||||
}
|
||||
|
||||
impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
pub fn new(reducer: R) -> Self {
|
||||
Self { reducer }
|
||||
}
|
||||
|
||||
pub fn reduce_program(&mut self, program: &Program) -> Program {
|
||||
let inputs = program
|
||||
.expected_input
|
||||
.iter()
|
||||
.filter_map(|x| self.reduce_function_input(x))
|
||||
.collect();
|
||||
let imports = program
|
||||
.imports
|
||||
.iter()
|
||||
.filter_map(|x| self.reduce_import_statement(x))
|
||||
.collect();
|
||||
let circuits = program
|
||||
.circuits
|
||||
.iter()
|
||||
.filter_map(|(identifier, circuit)| {
|
||||
Some((self.reduce_identifier(identifier), self.reduce_circuit(circuit)?))
|
||||
})
|
||||
.collect();
|
||||
let functions = program
|
||||
.functions
|
||||
.iter()
|
||||
.filter_map(|(identifier, function)| {
|
||||
Some((self.reduce_identifier(identifier), self.reduce_function(function)?))
|
||||
})
|
||||
.collect();
|
||||
let test_functions = program
|
||||
.tests
|
||||
.iter()
|
||||
.filter_map(|(identifier, test_function)| {
|
||||
Some((
|
||||
self.reduce_identifier(identifier),
|
||||
self.reduce_test_function(test_function)?,
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.reducer
|
||||
.reduce_program(program, inputs, imports, circuits, functions, test_functions)
|
||||
}
|
||||
|
||||
pub fn reduce_function_input(&mut self, input: &FunctionInput) -> Option<FunctionInput> {
|
||||
let item = match input {
|
||||
FunctionInput::InputKeyword(input_keyword) => FunctionInput::InputKeyword(input_keyword.clone()),
|
||||
FunctionInput::SelfKeyword(self_keyword) => FunctionInput::SelfKeyword(self_keyword.clone()),
|
||||
FunctionInput::MutSelfKeyword(mut_self_keyword) => FunctionInput::MutSelfKeyword(mut_self_keyword.clone()),
|
||||
FunctionInput::Variable(function_input_variable) => {
|
||||
FunctionInput::Variable(self.reduce_function_input_variable(function_input_variable))
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_function_input(input, item)
|
||||
}
|
||||
|
||||
pub fn reduce_import_statement(&mut self, import: &ImportStatement) -> Option<ImportStatement> {
|
||||
let package = self.reduce_package(&import.package_or_packages);
|
||||
|
||||
self.reducer.reduce_import_statement(import, package)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit(&mut self, circuit: &Circuit) -> Option<Circuit> {
|
||||
let circuit_name = self.reduce_identifier(&circuit.circuit_name);
|
||||
let members = circuit
|
||||
.members
|
||||
.iter()
|
||||
.filter_map(|x| self.reduce_circuit_member(x))
|
||||
.collect();
|
||||
|
||||
self.reducer.reduce_circuit(circuit, circuit_name, members)
|
||||
}
|
||||
|
||||
pub fn reduce_function(&mut self, function: &Function) -> Option<Function> {
|
||||
let identifier = self.reduce_identifier(&function.identifier);
|
||||
let input = function
|
||||
.input
|
||||
.iter()
|
||||
.filter_map(|x| self.reduce_function_input(x))
|
||||
.collect();
|
||||
let output = function.output.as_ref().map(|x| self.reduce_type(x));
|
||||
let block = Block {
|
||||
statements: function
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|x| self.reduce_statement(x))
|
||||
.collect(),
|
||||
span: function.block.span.clone(),
|
||||
};
|
||||
|
||||
self.reducer.reduce_function(function, identifier, input, output, block)
|
||||
}
|
||||
|
||||
pub fn reduce_test_function(&mut self, test_function: &TestFunction) -> Option<TestFunction> {
|
||||
let function = self.reduce_function(&test_function.function);
|
||||
let input_file = test_function.input_file.as_ref().map(|x| self.reduce_identifier(x));
|
||||
|
||||
self.reducer.reduce_test_function(test_function, function?, input_file)
|
||||
}
|
||||
|
||||
pub fn reduce_identifier(&mut self, identifier: &Identifier) -> Identifier {
|
||||
self.reducer.reduce_identifier(identifier)
|
||||
}
|
||||
|
||||
pub fn reduce_function_input_variable(
|
||||
&mut self,
|
||||
function_input_variable: &FunctionInputVariable,
|
||||
) -> FunctionInputVariable {
|
||||
let identifier = self.reduce_identifier(&function_input_variable.identifier);
|
||||
let type_ = self.reduce_type(&function_input_variable.type_);
|
||||
|
||||
self.reducer
|
||||
.reduce_function_input_variable(function_input_variable, identifier, type_)
|
||||
}
|
||||
|
||||
pub fn reduce_type(&mut self, type_: &Type) -> Type {
|
||||
let items = match type_ {
|
||||
// Data type wrappers
|
||||
Type::Array(type_, dimensions) => Type::Array(Box::new(self.reduce_type(type_)), dimensions.clone()),
|
||||
Type::Tuple(types) => Type::Tuple(types.iter().map(|x| self.reduce_type(x)).collect()),
|
||||
Type::Circuit(identifier) => Type::Circuit(self.reduce_identifier(identifier)),
|
||||
_ => type_.clone(),
|
||||
};
|
||||
|
||||
self.reducer.reduce_type(type_, items)
|
||||
}
|
||||
|
||||
pub fn reduce_package(&mut self, package_or_packages: &PackageOrPackages) -> PackageOrPackages {
|
||||
self.reducer.reduce_package(package_or_packages)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> Option<CircuitMember> {
|
||||
let items = match circuit_member {
|
||||
CircuitMember::CircuitVariable(identifier, type_) => {
|
||||
CircuitMember::CircuitVariable(self.reduce_identifier(identifier), self.reduce_type(type_))
|
||||
}
|
||||
CircuitMember::CircuitFunction(function) => CircuitMember::CircuitFunction(self.reduce_function(function)?),
|
||||
};
|
||||
|
||||
self.reducer.reduce_circuit_member(circuit_member, items)
|
||||
}
|
||||
|
||||
pub fn reduce_statement(&mut self, statement: &Statement) -> Statement {
|
||||
let items = match statement {
|
||||
Statement::Return(return_statement) => Statement::Return(ReturnStatement {
|
||||
expression: self.reduce_expression(&return_statement.expression),
|
||||
span: return_statement.span.clone(),
|
||||
}),
|
||||
Statement::Definition(definition) => {
|
||||
Statement::Definition(DefinitionStatement {
|
||||
declaration_type: definition.declaration_type.clone(),
|
||||
variable_names: definition
|
||||
.variable_names
|
||||
.iter()
|
||||
.map(|variable_name| self.reduce_variable_name(variable_name))
|
||||
.collect(),
|
||||
type_: Some(self.reduce_type(&definition.type_.as_ref().unwrap())), // TODO fix
|
||||
value: self.reduce_expression(&definition.value),
|
||||
span: definition.span.clone(),
|
||||
})
|
||||
}
|
||||
Statement::Assign(assign) => Statement::Assign(AssignStatement {
|
||||
operation: assign.operation.clone(),
|
||||
assignee: Assignee {
|
||||
identifier: self.reduce_identifier(&assign.assignee.identifier),
|
||||
accesses: assign
|
||||
.assignee
|
||||
.accesses
|
||||
.iter()
|
||||
.filter_map(|x| self.reduce_assignee_access(x))
|
||||
.collect(),
|
||||
span: assign.assignee.span.clone(),
|
||||
},
|
||||
value: self.reduce_expression(&assign.value),
|
||||
span: assign.span.clone(),
|
||||
}),
|
||||
Statement::Conditional(conditional) => {
|
||||
Statement::Conditional(self.reduce_conditional_statement(conditional))
|
||||
}
|
||||
Statement::Iteration(iteration) => {
|
||||
Statement::Iteration(IterationStatement {
|
||||
variable: self.reduce_identifier(&iteration.variable),
|
||||
start: self.reduce_expression(&iteration.start),
|
||||
stop: self.reduce_expression(&iteration.stop),
|
||||
block: Block {
|
||||
statements: iteration
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| self.reduce_statement(statement))
|
||||
.collect(),
|
||||
span: iteration.block.span.clone(),
|
||||
}, // TODO reduce block that isn't in a statement
|
||||
span: iteration.span.clone(),
|
||||
})
|
||||
}
|
||||
Statement::Console(console_function_call) => {
|
||||
let function = match &console_function_call.function {
|
||||
ConsoleFunction::Assert(expression) => ConsoleFunction::Assert(self.reduce_expression(expression)),
|
||||
ConsoleFunction::Debug(format) | ConsoleFunction::Error(format) | ConsoleFunction::Log(format) => {
|
||||
let formatted = FormattedString {
|
||||
string: format.string.clone(),
|
||||
containers: format.containers.clone(),
|
||||
parameters: format
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|parameter| self.reduce_expression(¶meter))
|
||||
.collect(),
|
||||
span: format.span.clone(),
|
||||
};
|
||||
match &console_function_call.function {
|
||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
||||
_ => unimplemented!(), // impossible
|
||||
}
|
||||
}
|
||||
};
|
||||
Statement::Console(ConsoleStatement {
|
||||
function,
|
||||
span: console_function_call.span.clone(),
|
||||
})
|
||||
}
|
||||
Statement::Expression(expression) => Statement::Expression(ExpressionStatement {
|
||||
expression: self.reduce_expression(&expression.expression),
|
||||
span: expression.span.clone(),
|
||||
}),
|
||||
Statement::Block(block) => Statement::Block(Block {
|
||||
statements: block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| self.reduce_statement(statement))
|
||||
.collect(),
|
||||
span: block.span.clone(),
|
||||
}),
|
||||
};
|
||||
|
||||
self.reducer.reduce_statement(statement, items)
|
||||
}
|
||||
|
||||
pub fn reduce_assignee_access(&mut self, assignee_access: &AssigneeAccess) -> Option<AssigneeAccess> {
|
||||
let item = match assignee_access {
|
||||
AssigneeAccess::ArrayRange(start, stop) => {
|
||||
let start_item = start.as_ref().map(|x| self.reduce_expression(x));
|
||||
let stop_item = stop.as_ref().map(|x| self.reduce_expression(x));
|
||||
AssigneeAccess::ArrayRange(start_item, stop_item)
|
||||
}
|
||||
AssigneeAccess::ArrayIndex(expression) => AssigneeAccess::ArrayIndex(self.reduce_expression(&expression)),
|
||||
AssigneeAccess::Tuple(number, span) => AssigneeAccess::Tuple(number.clone(), span.clone()),
|
||||
AssigneeAccess::Member(identifier) => {
|
||||
let identifier = self.reduce_identifier(identifier);
|
||||
AssigneeAccess::Member(identifier)
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_assignee_access(assignee_access, item)
|
||||
}
|
||||
|
||||
pub fn reduce_conditional_statement(&mut self, statement: &ConditionalStatement) -> ConditionalStatement {
|
||||
let condition = self.reduce_expression(&statement.condition);
|
||||
let statements = Block {
|
||||
statements: statement
|
||||
.block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|x| self.reduce_statement(x))
|
||||
.collect(),
|
||||
span: statement.block.span.clone(),
|
||||
};
|
||||
let next = statement.next.as_ref().map(|x| self.reduce_statement(x));
|
||||
|
||||
self.reducer
|
||||
.reduce_conditional_statement(statement, condition, statements, next)
|
||||
}
|
||||
|
||||
pub fn reduce_variable_name(&mut self, variable_name: &VariableName) -> VariableName {
|
||||
let identifier = self.reduce_identifier(&variable_name.identifier);
|
||||
|
||||
self.reducer.reduce_variable_name(variable_name, identifier)
|
||||
}
|
||||
|
||||
pub fn reduce_expression(&mut self, expression: &Expression) -> Expression {
|
||||
let items = match expression {
|
||||
Expression::Identifier(identifier) => Expression::Identifier(self.reduce_identifier(identifier)),
|
||||
// Expression::Value(value) => Expression::Value(self.reduce_expression(value.))
|
||||
Expression::Binary(binary) => {
|
||||
let left = Box::new(self.reduce_expression(&binary.left));
|
||||
let right = Box::new(self.reduce_expression(&binary.right));
|
||||
|
||||
Expression::Binary(BinaryExpression {
|
||||
left,
|
||||
right,
|
||||
op: binary.op.clone(),
|
||||
span: binary.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::Unary(unary) => {
|
||||
let inner = Box::new(self.reduce_expression(&unary.inner));
|
||||
|
||||
Expression::Unary(UnaryExpression {
|
||||
inner,
|
||||
op: unary.op.clone(),
|
||||
span: unary.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::Ternary(ternary) => {
|
||||
let condition = Box::new(self.reduce_expression(&ternary.condition));
|
||||
let if_true = Box::new(self.reduce_expression(&ternary.if_true));
|
||||
let if_false = Box::new(self.reduce_expression(&ternary.if_false));
|
||||
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition,
|
||||
if_true,
|
||||
if_false,
|
||||
span: ternary.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
Expression::ArrayInline(array_inline) => {
|
||||
let elements = array_inline
|
||||
.elements
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
SpreadOrExpression::Expression(expression) => {
|
||||
SpreadOrExpression::Expression(self.reduce_expression(expression))
|
||||
}
|
||||
SpreadOrExpression::Spread(expression) => {
|
||||
SpreadOrExpression::Spread(self.reduce_expression(expression))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Expression::ArrayInline(ArrayInlineExpression {
|
||||
elements,
|
||||
span: array_inline.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::ArrayInit(array_init) => {
|
||||
let element = Box::new(self.reduce_expression(&array_init.element));
|
||||
|
||||
Expression::ArrayInit(ArrayInitExpression {
|
||||
element,
|
||||
dimensions: array_init.dimensions.clone(),
|
||||
span: array_init.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::ArrayAccess(array_access) => {
|
||||
let array = Box::new(self.reduce_expression(&array_access.array));
|
||||
let index = Box::new(self.reduce_expression(&array_access.index));
|
||||
Expression::ArrayAccess(ArrayAccessExpression {
|
||||
array,
|
||||
index,
|
||||
span: array_access.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::ArrayRangeAccess(array_range_access) => {
|
||||
let array = Box::new(self.reduce_expression(&array_range_access.array));
|
||||
let left = array_range_access
|
||||
.left
|
||||
.as_ref()
|
||||
.map(|left| Box::new(self.reduce_expression(&left)));
|
||||
let right = array_range_access
|
||||
.right
|
||||
.as_ref()
|
||||
.map(|right| Box::new(self.reduce_expression(&right)));
|
||||
|
||||
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
|
||||
array,
|
||||
left,
|
||||
right,
|
||||
span: array_range_access.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
Expression::TupleInit(tuple_init) => {
|
||||
let elements = tuple_init.elements.iter().map(|x| self.reduce_expression(x)).collect();
|
||||
|
||||
Expression::TupleInit(TupleInitExpression {
|
||||
elements,
|
||||
span: tuple_init.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::TupleAccess(tuple_access) => {
|
||||
let tuple = Box::new(self.reduce_expression(&tuple_access.tuple));
|
||||
|
||||
Expression::TupleAccess(TupleAccessExpression {
|
||||
tuple,
|
||||
index: tuple_access.index.clone(),
|
||||
span: tuple_access.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::CircuitInit(circuit_init) => {
|
||||
let name = self.reduce_identifier(&circuit_init.name);
|
||||
let members = circuit_init
|
||||
.members
|
||||
.iter()
|
||||
.map(|definition| {
|
||||
let identifier = self.reduce_identifier(&definition.identifier);
|
||||
let expression = self.reduce_expression(&definition.expression);
|
||||
|
||||
CircuitImpliedVariableDefinition { identifier, expression }
|
||||
})
|
||||
.collect();
|
||||
|
||||
Expression::CircuitInit(CircuitInitExpression {
|
||||
name,
|
||||
members,
|
||||
span: circuit_init.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::CircuitMemberAccess(circuit_member_access) => {
|
||||
let circuit = Box::new(self.reduce_expression(&circuit_member_access.circuit));
|
||||
let name = self.reduce_identifier(&circuit_member_access.name);
|
||||
|
||||
Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
|
||||
circuit,
|
||||
name,
|
||||
span: circuit_member_access.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::CircuitStaticFunctionAccess(circuit_static_func_access) => {
|
||||
let circuit = Box::new(self.reduce_expression(&circuit_static_func_access.circuit));
|
||||
let name = self.reduce_identifier(&circuit_static_func_access.name);
|
||||
|
||||
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
|
||||
circuit,
|
||||
name,
|
||||
span: circuit_static_func_access.span.clone(),
|
||||
})
|
||||
}
|
||||
Expression::Call(call) => {
|
||||
let function = Box::new(self.reduce_expression(&call.function));
|
||||
let arguments = call.arguments.iter().map(|x| self.reduce_expression(x)).collect();
|
||||
|
||||
Expression::Call(CallExpression {
|
||||
function,
|
||||
arguments,
|
||||
span: call.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
x => x.clone(), // leaf nodes we dont reconstruct
|
||||
};
|
||||
|
||||
self.reducer.reduce_expression(expression, items)
|
||||
}
|
||||
}
|
204
ast/src/reducer/reconstructing_reducer.rs
Normal file
204
ast/src/reducer/reconstructing_reducer.rs
Normal file
@ -0,0 +1,204 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module contains the reducer which iterates through ast nodes - converting them into
|
||||
//! asg nodes and saving relevant information.
|
||||
|
||||
use crate::{
|
||||
AssigneeAccess,
|
||||
Block,
|
||||
Circuit,
|
||||
CircuitMember,
|
||||
ConditionalStatement,
|
||||
Expression,
|
||||
Function,
|
||||
FunctionInput,
|
||||
FunctionInputVariable,
|
||||
Identifier,
|
||||
ImportStatement,
|
||||
Package,
|
||||
PackageOrPackages,
|
||||
Packages,
|
||||
Program,
|
||||
Statement,
|
||||
TestFunction,
|
||||
Type,
|
||||
VariableName,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[allow(clippy::redundant_closure)] // Clippy bug line 188
|
||||
pub trait ReconstructingReducer {
|
||||
// ciruits/functions/tests map identifier -> (identifier_item, value_item)
|
||||
fn reduce_program(
|
||||
&mut self,
|
||||
program: &Program,
|
||||
expected_input: Vec<FunctionInput>,
|
||||
imports: Vec<ImportStatement>,
|
||||
circuits: IndexMap<Identifier, Circuit>,
|
||||
functions: IndexMap<Identifier, Function>,
|
||||
tests: IndexMap<Identifier, TestFunction>,
|
||||
) -> Program {
|
||||
Program {
|
||||
name: program.name.clone(),
|
||||
expected_input,
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
tests,
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_function_input(&mut self, input: &FunctionInput, item: FunctionInput) -> Option<FunctionInput> {
|
||||
Some(item)
|
||||
}
|
||||
|
||||
fn reduce_import_statement(
|
||||
&mut self,
|
||||
import: &ImportStatement,
|
||||
package_or_packages: PackageOrPackages,
|
||||
) -> Option<ImportStatement> {
|
||||
Some(ImportStatement {
|
||||
package_or_packages,
|
||||
span: import.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_circuit(
|
||||
&mut self,
|
||||
circuit: &Circuit,
|
||||
circuit_name: Identifier,
|
||||
members: Vec<CircuitMember>,
|
||||
) -> Option<Circuit> {
|
||||
Some(Circuit { circuit_name, members })
|
||||
}
|
||||
|
||||
fn reduce_function(
|
||||
&mut self,
|
||||
function: &Function,
|
||||
identifier: Identifier,
|
||||
input: Vec<FunctionInput>,
|
||||
output: Option<Type>,
|
||||
block: Block,
|
||||
) -> Option<Function> {
|
||||
Some(Function {
|
||||
identifier,
|
||||
input,
|
||||
output,
|
||||
block,
|
||||
span: function.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_test_function(
|
||||
&mut self,
|
||||
test_function: &TestFunction,
|
||||
function: Function,
|
||||
input_file: Option<Identifier>,
|
||||
) -> Option<TestFunction> {
|
||||
Some(TestFunction { function, input_file })
|
||||
}
|
||||
|
||||
fn reduce_identifier(&mut self, identifier: &Identifier) -> Identifier {
|
||||
identifier.clone()
|
||||
}
|
||||
|
||||
fn reduce_function_input_variable(
|
||||
&mut self,
|
||||
function_input_variable: &FunctionInputVariable,
|
||||
identifier: Identifier,
|
||||
type_: Type,
|
||||
) -> FunctionInputVariable {
|
||||
FunctionInputVariable {
|
||||
identifier,
|
||||
const_: function_input_variable.const_,
|
||||
mutable: function_input_variable.mutable,
|
||||
type_,
|
||||
span: function_input_variable.span.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_type(&mut self, type_: &Type, items: Type) -> Type {
|
||||
items
|
||||
}
|
||||
|
||||
fn reduce_package(&mut self, package_or_packages: &PackageOrPackages) -> PackageOrPackages {
|
||||
match package_or_packages {
|
||||
PackageOrPackages::Package(package) => {
|
||||
let name = self.reduce_identifier(&package.name);
|
||||
|
||||
PackageOrPackages::Package(Package {
|
||||
name,
|
||||
access: package.access.clone(),
|
||||
span: package.span.clone(),
|
||||
})
|
||||
}
|
||||
PackageOrPackages::Packages(packages) => {
|
||||
let name = self.reduce_identifier(&packages.name);
|
||||
|
||||
PackageOrPackages::Packages(Packages {
|
||||
name,
|
||||
accesses: packages.accesses.clone(),
|
||||
span: packages.span.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember, items: CircuitMember) -> Option<CircuitMember> {
|
||||
Some(items)
|
||||
}
|
||||
|
||||
fn reduce_statement(&mut self, statement: &Statement, items: Statement) -> Statement {
|
||||
items
|
||||
}
|
||||
|
||||
fn reduce_assignee_access(
|
||||
&mut self,
|
||||
assignee_access: &AssigneeAccess,
|
||||
item: AssigneeAccess,
|
||||
) -> Option<AssigneeAccess> {
|
||||
Some(item)
|
||||
}
|
||||
|
||||
fn reduce_conditional_statement(
|
||||
&mut self,
|
||||
statement: &ConditionalStatement,
|
||||
condition: Expression,
|
||||
block: Block,
|
||||
next: Option<Statement>,
|
||||
) -> ConditionalStatement {
|
||||
ConditionalStatement {
|
||||
condition,
|
||||
block,
|
||||
next: next.map(|item| Box::new(item)),
|
||||
span: statement.span.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_variable_name(&mut self, variable_name: &VariableName, identifier: Identifier) -> VariableName {
|
||||
VariableName {
|
||||
mutable: variable_name.mutable,
|
||||
identifier,
|
||||
span: variable_name.span.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_expression(&mut self, expression: &Expression, items: Expression) -> Expression {
|
||||
items
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user