From 250c8ce5ec9976d4ef05ad783ef5b3290be2c90a Mon Sep 17 00:00:00 2001 From: gluax Date: Fri, 12 Mar 2021 14:32:20 -0500 Subject: [PATCH] reducer clean up --- ast/src/reducer/canonicalization.rs | 57 +- ast/src/reducer/mod.rs | 12 - ast/src/reducer/monoid.rs | 68 -- ast/src/reducer/monoidal_director.rs | 433 ----------- ast/src/reducer/monoidal_reducer.rs | 315 -------- ast/src/reducer/reconstructing_director.rs | 866 +++++++++++---------- ast/src/reducer/reconstructing_reducer.rs | 537 +++++++++---- 7 files changed, 855 insertions(+), 1433 deletions(-) delete mode 100644 ast/src/reducer/monoid.rs delete mode 100644 ast/src/reducer/monoidal_director.rs delete mode 100644 ast/src/reducer/monoidal_reducer.rs diff --git a/ast/src/reducer/canonicalization.rs b/ast/src/reducer/canonicalization.rs index c8aa3a4843..bab7238090 100644 --- a/ast/src/reducer/canonicalization.rs +++ b/ast/src/reducer/canonicalization.rs @@ -14,29 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! This module contains the reducer which iterates through ast nodes - converting them into -//! asg nodes and saving relevant information. - -use crate::{ - reducer::ReconstructingReducer, - Block, - CallExpression, - Circuit, - CircuitInitExpression, - CircuitMember, - CircuitMemberAccessExpression, - CircuitStaticFunctionAccessExpression, - DefinitionStatement, - Expression, - ExpressionStatement, - Function, - FunctionInput, - FunctionInputVariable, - Identifier, - ReturnStatement, - Statement, - Type, -}; +use crate::*; pub struct Canonicalizer; @@ -45,16 +23,6 @@ impl Canonicalizer { matches!(identifier.name.as_str(), "Self") } - fn _is_self_keyword(&self, function_inputs: &[FunctionInput]) -> bool { - for function_input in function_inputs { - if let FunctionInput::SelfKeyword(_) = function_input { - return true; - } - } - - false - } - fn is_self_type(&self, type_option: Option<&Type>) -> bool { matches!(type_option, Some(Type::SelfType)) } @@ -184,14 +152,6 @@ impl Canonicalizer { span: function.block.span.clone(), }; - // probably shouldn't do this its self not Self - // if self.is_self_keyword(&input) { - // input = input - // .iter() - // .map(|function_input| self.canonicalize_function_input(function_input, circuit_name)) - // .collect(); - // } - if self.is_self_type(output.as_ref()) { output = Some(Type::Circuit(circuit_name.clone())); } @@ -212,22 +172,15 @@ impl Canonicalizer { } impl ReconstructingReducer for Canonicalizer { - fn reduce_circuit( - &mut self, - _: &Circuit, - circuit_name: Identifier, - members: Vec, - ) -> Option { - let new_circuit = Circuit { + fn reduce_circuit(&mut self, _circuit: &Circuit, circuit_name: Identifier, members: Vec) -> Circuit { + Circuit { circuit_name: circuit_name.clone(), members: members .iter() .map(|member| self.canonicalize_circuit_member(member, &circuit_name)) .collect(), - }; - - Some(new_circuit) + } } - // TODO make all self/Self outside of circuit error out + // fn reduce_program(program: &Program, expected_input: Vec, imports: Vec, circuits: IndexMap, functions: IndexMap) } diff --git a/ast/src/reducer/mod.rs b/ast/src/reducer/mod.rs index ae9e09287e..144997d8e1 100644 --- a/ast/src/reducer/mod.rs +++ b/ast/src/reducer/mod.rs @@ -14,21 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! This module contains the reducer which iterates through ast nodes - converting them into -//! asg nodes and saving relevant information. - mod canonicalization; pub use canonicalization::*; -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::*; diff --git a/ast/src/reducer/monoid.rs b/ast/src/reducer/monoid.rs deleted file mode 100644 index e2f6e2ac70..0000000000 --- a/ast/src/reducer/monoid.rs +++ /dev/null @@ -1,68 +0,0 @@ -// 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 . - -//! 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) -> Self { - let mut current = self; - for item in others { - current = current.append(item); - } - current - } - - fn append_option(self, other: Option) -> Self { - match other { - None => self, - Some(other) => self.append(other), - } - } -} - -pub struct VecAppend(Vec); - -impl Default for VecAppend { - fn default() -> Self { - Self(vec![]) - } -} - -impl Monoid for VecAppend { - fn append(mut self, other: Self) -> Self { - self.0.extend(other.0); - VecAppend(self.0) - } - - fn append_all(mut self, others: impl Iterator) -> Self { - let all: Vec> = 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 Into> for VecAppend { - fn into(self) -> Vec { - self.0 - } -} diff --git a/ast/src/reducer/monoidal_director.rs b/ast/src/reducer/monoidal_director.rs deleted file mode 100644 index fa7408aa79..0000000000 --- a/ast/src/reducer/monoidal_director.rs +++ /dev/null @@ -1,433 +0,0 @@ -// 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 . - -//! 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, - Type, - ValueExpression, - VariableName, -}; -use std::marker::PhantomData; - -pub struct MonoidalDirector> { - reducer: R, - _monoid: PhantomData, -} - -impl> MonoidalDirector { - 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(); - - self.reducer - .reduce_program(program, inputs, imports, circuits, 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_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 = - definition.expression.as_ref().map(|expr| self.reduce_expression(&expr)); - (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) - } - - // TODO casts? - _ => ExpressionMonoidItems::Empty, - }; - self.reducer.reduce_expression(expression, items) - } -} diff --git a/ast/src/reducer/monoidal_reducer.rs b/ast/src/reducer/monoidal_reducer.rs deleted file mode 100644 index dc47e16ec8..0000000000 --- a/ast/src/reducer/monoidal_reducer.rs +++ /dev/null @@ -1,315 +0,0 @@ -// 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 . - -//! 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, - Type, - ValueExpression, - VariableName, -}; -use indexmap::IndexMap; - -pub enum TypeMonoidItems { - None, - Tuple(Vec), - Array(T), - Identifier(T), -} - -pub enum CircuitMemberMonoidItems { - Variable { identifier: T, type_: T }, - Function(T), -} - -pub enum StatementMonoidItems { - Return(T), - Definition { - variables: T, - expression: T, - }, - Assign { - assignee: T, - assignee_accesses: Vec, - expression: T, - }, - Conditional(T), - Iteration { - identifier: T, - start: T, - stop: T, - statements: Vec, - }, - ConsoleAssert(T), - ConsoleFormat(Vec), - Expression(T), - Statements(Vec), -} - -pub enum AssigneeAccessItem { - Array(RangeItem), - Tuple, - Member(T), -} - -pub enum RangeItem { - Range(Option, Option), - Index(T), -} - -pub enum ExpressionMonoidItems { - Empty, - Unary(T), - Binary(T, T), - Triary(T, T, T), - FunctionCall(T, Vec), - ArrayAccess(T, T), - Circuit(T, Vec<(T, Option)>), - Var(Vec), - Value(T), -} - -pub enum ConditionStatementNextItem { - Nested(T), - End(Vec), -} - -pub enum FunctionInputItem { - InputKeyword, - SelfKeyword, - MutSelfKeyword, - Variable(T), -} - -pub enum ValueExpressionMonoidItems { - Address, - Boolean, - Field, - GroupSingle, - GroupTuple(T, T), - Implicit, - Integer(T), -} - -#[allow(unused_variables)] -pub trait MonoidalReducer { - fn reduce_program( - &mut self, - program: &Program, - expected_input: Vec, - imports: Vec, - circuits: IndexMap, - functions: IndexMap, - ) -> 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); - } - items - } - - fn reduce_function_input(&mut self, input: &FunctionInput, item: FunctionInputItem) -> 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 { - circuit_name.append_all(members.into_iter()) - } - - fn reduce_function( - &mut self, - function: &Function, - identifier: T, - input: Vec, - output: Option, - statements: Vec, - ) -> T { - identifier - .append_all(input.into_iter()) - .append_option(output) - .append_all(statements.into_iter()) - } - - 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 { - 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 { - match items { - CircuitMemberMonoidItems::Variable { identifier, type_ } => identifier.append(type_), - CircuitMemberMonoidItems::Function(identifier) => identifier, - } - } - - fn reduce_statement(&mut self, statement: &Statement, items: StatementMonoidItems) -> 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 { - 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, - next: Option, - ) -> 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::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 { - 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 { - 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() { - match value { - Some(val) => { - out = out.append(key).append(val); - } - None => { - out = out.append(key); - } - } - } - out - } - ExpressionMonoidItems::Var(items) => T::default().append_all(items.into_iter()), - ExpressionMonoidItems::Value(value) => value, - } - } -} diff --git a/ast/src/reducer/reconstructing_director.rs b/ast/src/reducer/reconstructing_director.rs index a9fdb85148..5503448c5a 100644 --- a/ast/src/reducer/reconstructing_director.rs +++ b/ast/src/reducer/reconstructing_director.rs @@ -17,49 +17,7 @@ //! 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, - TupleAccessExpression, - TupleInitExpression, - Type, - UnaryExpression, - VariableName, -}; +use crate::*; pub struct ReconstructingDirector { reducer: R, @@ -70,430 +28,496 @@ impl ReconstructingDirector { Self { reducer } } + pub fn reduce_type(&mut self, type_: &Type) -> Type { + let new = 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(|type_| self.reduce_type(type_)).collect()), + Type::Circuit(identifier) => Type::Circuit(self.reduce_identifier(identifier)), + _ => type_.clone(), + }; + + self.reducer.reduce_type(type_, new) + } + + // Expressions + pub fn reduce_expression(&mut self, expression: &Expression) -> Expression { + let new = match expression { + Expression::Identifier(identifier) => Expression::Identifier(self.reduce_identifier(&identifier)), + Expression::Value(value) => Expression::Value(self.reduce_value(&value)), + Expression::Binary(binary) => Expression::Binary(self.reduce_binary(&binary)), + Expression::Unary(unary) => Expression::Unary(self.reduce_unary(&unary)), + Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(&ternary)), + Expression::Cast(cast) => Expression::Cast(self.reduce_cast(&cast)), + + Expression::ArrayInline(array_inline) => Expression::ArrayInline(self.reduce_array_inline(&array_inline)), + Expression::ArrayInit(array_init) => Expression::ArrayInit(self.reduce_array_init(&array_init)), + Expression::ArrayAccess(array_access) => Expression::ArrayAccess(self.reduce_array_access(&array_access)), + Expression::ArrayRangeAccess(array_range_access) => { + Expression::ArrayRangeAccess(self.reduce_array_range_access(&array_range_access)) + } + + Expression::TupleInit(tuple_init) => Expression::TupleInit(self.reduce_tuple_init(&tuple_init)), + Expression::TupleAccess(tuple_access) => Expression::TupleAccess(self.reduce_tuple_access(&tuple_access)), + + Expression::CircuitInit(circuit_init) => Expression::CircuitInit(self.reduce_circuit_init(&circuit_init)), + Expression::CircuitMemberAccess(circuit_member_access) => { + Expression::CircuitMemberAccess(self.reduce_circuit_member_access(&circuit_member_access)) + } + Expression::CircuitStaticFunctionAccess(circuit_static_fn_access) => { + Expression::CircuitStaticFunctionAccess(self.reduce_circuit_static_fn_access(&circuit_static_fn_access)) + } + + Expression::Call(call) => Expression::Call(self.reduce_call(&call)), + }; + + self.reducer.reduce_expression(expression, new) + } + + pub fn reduce_identifier(&mut self, identifier: &Identifier) -> Identifier { + self.reducer.reduce_identifier(identifier, identifier.span.clone()) + } + + pub fn reduce_group_tuple(&mut self, group_tuple: &GroupTuple) -> GroupTuple { + self.reducer.reduce_group_tuple(group_tuple, group_tuple.span.clone()) + } + + pub fn reduce_group_value(&mut self, group_value: &GroupValue) -> GroupValue { + let new = match group_value { + GroupValue::Tuple(group_tuple) => GroupValue::Tuple(self.reduce_group_tuple(&group_tuple)), + _ => group_value.clone(), + }; + + self.reducer.reduce_group_value(group_value, new) + } + + pub fn reduce_value(&mut self, value: &ValueExpression) -> ValueExpression { + let new = match value { + ValueExpression::Group(group_value) => { + ValueExpression::Group(Box::new(self.reduce_group_value(&group_value))) + } + _ => value.clone(), + }; + + self.reducer.reduce_value(value, new) + } + + pub fn reduce_binary(&mut self, binary: &BinaryExpression) -> BinaryExpression { + let left = self.reduce_expression(&binary.left); + let right = self.reduce_expression(&binary.right); + + self.reducer + .reduce_binary(binary, left, right, binary.op.clone(), binary.span.clone()) + } + + pub fn reduce_unary(&mut self, unary: &UnaryExpression) -> UnaryExpression { + let inner = self.reduce_expression(&unary.inner); + + self.reducer + .reduce_unary(unary, inner, unary.op.clone(), unary.span.clone()) + } + + pub fn reduce_ternary(&mut self, ternary: &TernaryExpression) -> TernaryExpression { + let condition = self.reduce_expression(&ternary.condition); + let if_true = self.reduce_expression(&ternary.if_true); + let if_false = self.reduce_expression(&ternary.if_false); + + self.reducer + .reduce_ternary(ternary, condition, if_true, if_false, ternary.span.clone()) + } + + pub fn reduce_cast(&mut self, cast: &CastExpression) -> CastExpression { + let inner = self.reduce_expression(&cast.inner); + let target_type = cast.target_type.clone(); // TODO reduce + + self.reducer.reduce_cast(cast, inner, target_type, cast.span.clone()) + } + + pub fn reduce_array_inline(&mut self, array_inline: &ArrayInlineExpression) -> ArrayInlineExpression { + let elements = array_inline + .elements + .iter() + .map(|element| match element { + SpreadOrExpression::Expression(expression) => { + SpreadOrExpression::Expression(self.reduce_expression(expression)) + } + SpreadOrExpression::Spread(expression) => { + SpreadOrExpression::Spread(self.reduce_expression(expression)) + } + }) + .collect(); + + self.reducer + .reduce_array_inline(array_inline, elements, array_inline.span.clone()) + } + + pub fn reduce_array_init(&mut self, array_init: &ArrayInitExpression) -> ArrayInitExpression { + let element = self.reduce_expression(&array_init.element); + + self.reducer + .reduce_array_init(array_init, element, array_init.span.clone()) + } + + pub fn reduce_array_access(&mut self, array_access: &ArrayAccessExpression) -> ArrayAccessExpression { + let array = self.reduce_expression(&array_access.array); + let index = self.reduce_expression(&array_access.index); + + self.reducer + .reduce_array_access(array_access, array, index, array_access.span.clone()) + } + + pub fn reduce_array_range_access( + &mut self, + array_range_access: &ArrayRangeAccessExpression, + ) -> ArrayRangeAccessExpression { + let array = self.reduce_expression(&array_range_access.array); + let left = array_range_access + .left + .as_ref() + .map(|left| self.reduce_expression(left)); + let right = array_range_access + .right + .as_ref() + .map(|right| self.reduce_expression(right)); + + self.reducer + .reduce_array_range_access(array_range_access, array, left, right, array_range_access.span.clone()) + } + + pub fn reduce_tuple_init(&mut self, tuple_init: &TupleInitExpression) -> TupleInitExpression { + let elements = tuple_init + .elements + .iter() + .map(|expr| self.reduce_expression(expr)) + .collect(); + + self.reducer + .reduce_tuple_init(tuple_init, elements, tuple_init.span.clone()) + } + + pub fn reduce_tuple_access(&mut self, tuple_access: &TupleAccessExpression) -> TupleAccessExpression { + let tuple = self.reduce_expression(&tuple_access.tuple); + + self.reducer + .reduce_tuple_access(tuple_access, tuple, tuple_access.span.clone()) + } + + pub fn reduce_circuit_init(&mut self, circuit_init: &CircuitInitExpression) -> CircuitInitExpression { + 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 = definition.expression.as_ref().map(|expr| self.reduce_expression(expr)); + + CircuitImpliedVariableDefinition { identifier, expression } + }) + .collect(); + + self.reducer + .reduce_circuit_init(circuit_init, name, members, circuit_init.span.clone()) + } + + pub fn reduce_circuit_member_access( + &mut self, + circuit_member_access: &CircuitMemberAccessExpression, + ) -> CircuitMemberAccessExpression { + let circuit = self.reduce_expression(&circuit_member_access.circuit); + let name = self.reduce_identifier(&circuit_member_access.name); + + self.reducer.reduce_circuit_member_access( + circuit_member_access, + circuit, + name, + circuit_member_access.span.clone(), + ) + } + + pub fn reduce_circuit_static_fn_access( + &mut self, + circuit_static_fn_access: &CircuitStaticFunctionAccessExpression, + ) -> CircuitStaticFunctionAccessExpression { + let circuit = self.reduce_expression(&circuit_static_fn_access.circuit); + let name = self.reduce_identifier(&circuit_static_fn_access.name); + + self.reducer.reduce_circuit_static_fn_access( + circuit_static_fn_access, + circuit, + name, + circuit_static_fn_access.span.clone(), + ) + } + + pub fn reduce_call(&mut self, call: &CallExpression) -> CallExpression { + let function = self.reduce_expression(&call.function); + let arguments = call.arguments.iter().map(|expr| self.reduce_expression(expr)).collect(); + + self.reducer.reduce_call(call, function, arguments, call.span.clone()) + } + + // Statements + pub fn reduce_statement(&mut self, statement: &Statement) -> Statement { + let new = match statement { + Statement::Return(return_statement) => Statement::Return(self.reduce_return(&return_statement)), + Statement::Definition(definition) => Statement::Definition(self.reduce_definition(&definition)), + Statement::Assign(assign) => Statement::Assign(self.reduce_assign(&assign)), + Statement::Conditional(conditional) => Statement::Conditional(self.reduce_conditional(&conditional)), + Statement::Iteration(iteration) => Statement::Iteration(self.reduce_iteration(&iteration)), + Statement::Console(console) => Statement::Console(self.reduce_console(&console)), + Statement::Expression(expression) => Statement::Expression(self.reduce_expression_statement(&expression)), + Statement::Block(block) => Statement::Block(self.reduce_block(&block)), + }; + + self.reducer.reduce_statement(statement, new) + } + + pub fn reduce_return(&mut self, return_statement: &ReturnStatement) -> ReturnStatement { + let expression = self.reduce_expression(&return_statement.expression); + + self.reducer + .reduce_return(return_statement, expression, return_statement.span.clone()) + } + + 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, variable_name.span.clone()) + } + + pub fn reduce_definition(&mut self, definition: &DefinitionStatement) -> DefinitionStatement { + let variable_names = definition + .variable_names + .iter() + .map(|variable_name| self.reduce_variable_name(variable_name)) + .collect(); + let type_ = definition.type_.as_ref().map(|inner| self.reduce_type(inner)); + let value = self.reduce_expression(&definition.value); + + self.reducer + .reduce_definition(definition, variable_names, type_, value, definition.span.clone()) + } + + pub fn reduce_assignee_access(&mut self, access: &AssigneeAccess) -> AssigneeAccess { + let new = match access { + AssigneeAccess::ArrayRange(left, right) => AssigneeAccess::ArrayRange( + left.as_ref().map(|expr| self.reduce_expression(expr)), + right.as_ref().map(|expr| self.reduce_expression(expr)), + ), + AssigneeAccess::ArrayIndex(index) => AssigneeAccess::ArrayIndex(self.reduce_expression(&index)), + AssigneeAccess::Member(identifier) => AssigneeAccess::Member(self.reduce_identifier(&identifier)), + _ => access.clone(), + }; + + self.reducer.reduce_assignee_access(access, new) + } + + pub fn reduce_assignee(&mut self, assignee: &Assignee) -> Assignee { + let identifier = self.reduce_identifier(&assignee.identifier); + let accesses = assignee + .accesses + .iter() + .map(|access| self.reduce_assignee_access(access)) + .collect(); + + self.reducer + .reduce_assignee(assignee, identifier, accesses, assignee.span.clone()) + } + + pub fn reduce_assign(&mut self, assign: &AssignStatement) -> AssignStatement { + let assignee = self.reduce_assignee(&assign.assignee); + let value = self.reduce_expression(&assign.value); + + self.reducer.reduce_assign(assign, assignee, value, assign.span.clone()) + } + + pub fn reduce_conditional(&mut self, conditional: &ConditionalStatement) -> ConditionalStatement { + let condition = self.reduce_expression(&conditional.condition); + let block = self.reduce_block(&conditional.block); + let next = conditional + .next + .as_ref() + .map(|condition| self.reduce_statement(condition)); + + self.reducer + .reduce_conditional(conditional, condition, block, next, conditional.span.clone()) + } + + pub fn reduce_iteration(&mut self, iteration: &IterationStatement) -> IterationStatement { + let variable = self.reduce_identifier(&iteration.variable); + let start = self.reduce_expression(&iteration.start); + let stop = self.reduce_expression(&iteration.stop); + let block = self.reduce_block(&iteration.block); + + self.reducer + .reduce_iteration(iteration, variable, start, stop, block, iteration.span.clone()) + } + + pub fn reduce_console(&mut self, console_function_call: &ConsoleStatement) -> ConsoleStatement { + 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 { + parts: format.parts.clone(), + parameters: format + .parameters + .iter() + .map(|parameter| self.reduce_expression(parameter)) + .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 + } + } + }; + + self.reducer + .reduce_console(console_function_call, function, console_function_call.span.clone()) + } + + pub fn reduce_expression_statement(&mut self, expression: &ExpressionStatement) -> ExpressionStatement { + let inner_expression = self.reduce_expression(&expression.expression); + self.reducer + .reduce_expression_statement(expression, inner_expression, expression.span.clone()) + } + + pub fn reduce_block(&mut self, block: &Block) -> Block { + let statements = block + .statements + .iter() + .map(|statement| self.reduce_statement(statement)) + .collect(); + + self.reducer.reduce_block(block, statements, block.span.clone()) + } + + // Program pub fn reduce_program(&mut self, program: &Program) -> Program { let inputs = program .expected_input .iter() - .filter_map(|x| self.reduce_function_input(x)) + .map(|input| self.reduce_function_input(input)) .collect(); let imports = program .imports .iter() - .filter_map(|x| self.reduce_import_statement(x)) + .map(|import| self.reduce_import(import)) .collect(); let circuits = program .circuits .iter() - .filter_map(|(identifier, circuit)| { - Some((self.reduce_identifier(identifier), self.reduce_circuit(circuit)?)) - }) + .map(|(identifier, circuit)| (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)?)) - }) + .map(|(identifier, function)| (self.reduce_identifier(identifier), self.reduce_function(function))) .collect(); self.reducer .reduce_program(program, inputs, imports, circuits, functions) } - pub fn reduce_function_input(&mut self, input: &FunctionInput) -> Option { - 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()), + pub fn reduce_function_input_variable(&mut self, variable: &FunctionInputVariable) -> FunctionInputVariable { + let identifier = self.reduce_identifier(&variable.identifier); + let type_ = self.reduce_type(&variable.type_); + + self.reducer + .reduce_function_input_variable(variable, identifier, type_, variable.span.clone()) + } + + pub fn reduce_function_input(&mut self, input: &FunctionInput) -> FunctionInput { + let new = match input { FunctionInput::Variable(function_input_variable) => { FunctionInput::Variable(self.reduce_function_input_variable(function_input_variable)) } + _ => input.clone(), }; - self.reducer.reduce_function_input(input, item) + self.reducer.reduce_function_input(input, new) } - pub fn reduce_import_statement(&mut self, import: &ImportStatement) -> Option { - let package = self.reduce_package(&import.package_or_packages); + pub fn reduce_package_or_packages(&mut self, package_or_packages: &PackageOrPackages) -> PackageOrPackages { + let new = match package_or_packages { + PackageOrPackages::Package(package) => PackageOrPackages::Package(Package { + name: self.reduce_identifier(&package.name), + access: package.access.clone(), + span: package.span.clone(), + }), + PackageOrPackages::Packages(packages) => PackageOrPackages::Packages(Packages { + name: self.reduce_identifier(&packages.name), + accesses: packages.accesses.clone(), + span: packages.span.clone(), + }), + }; - self.reducer.reduce_import_statement(import, package) + self.reducer.reduce_package_or_packages(package_or_packages, new) } - pub fn reduce_circuit(&mut self, circuit: &Circuit) -> Option { + pub fn reduce_import(&mut self, import: &ImportStatement) -> ImportStatement { + let package_or_packages = self.reduce_package_or_packages(&import.package_or_packages); + + self.reducer + .reduce_import(import, package_or_packages, import.span.clone()) + } + + pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> CircuitMember { + let new = 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, new) + } + + pub fn reduce_circuit(&mut self, circuit: &Circuit) -> Circuit { let circuit_name = self.reduce_identifier(&circuit.circuit_name); let members = circuit .members .iter() - .filter_map(|x| self.reduce_circuit_member(x)) + .map(|member| self.reduce_circuit_member(member)) .collect(); self.reducer.reduce_circuit(circuit, circuit_name, members) } - pub fn reduce_function(&mut self, function: &Function) -> Option { + fn reduce_annotation(&mut self, annotation: &Annotation) -> Annotation { + let name = self.reduce_identifier(&annotation.name); + + self.reducer + .reduce_annotation(annotation, annotation.span.clone(), name) + } + + pub fn reduce_function(&mut self, function: &Function) -> Function { let identifier = self.reduce_identifier(&function.identifier); - let annotations = function.annotations.clone(); // TODO reduce + let annotations = function + .annotations + .iter() + .map(|annotation| self.reduce_annotation(annotation)) + .collect(); let input = function .input .iter() - .filter_map(|x| self.reduce_function_input(x)) + .map(|input| self.reduce_function_input(input)) .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(), - }; + let output = function.output.as_ref().map(|output| self.reduce_type(output)); + let block = self.reduce_block(&function.block); - self.reducer - .reduce_function(function, annotations, identifier, input, output, block) - } - - 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 { - 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_: definition.type_.as_ref().map(|inner| self.reduce_type(&inner)), - 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 { - parts: format.parts.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 { - 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 = definition.expression.as_ref().map(|expr| self.reduce_expression(&expr)); - - 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) + self.reducer.reduce_function( + function, + identifier, + annotations, + input, + output, + block, + function.span.clone(), + ) } } diff --git a/ast/src/reducer/reconstructing_reducer.rs b/ast/src/reducer/reconstructing_reducer.rs index 472ddcecbd..ce9cbd1e49 100644 --- a/ast/src/reducer/reconstructing_reducer.rs +++ b/ast/src/reducer/reconstructing_reducer.rs @@ -14,36 +14,364 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! This module contains the reducer which iterates through ast nodes - converting them into -//! asg nodes and saving relevant information. - -use crate::{ - Annotation, - AssigneeAccess, - Block, - Circuit, - CircuitMember, - ConditionalStatement, - Expression, - Function, - FunctionInput, - FunctionInputVariable, - Identifier, - ImportStatement, - Package, - PackageOrPackages, - Packages, - Program, - Statement, - Type, - VariableName, -}; +use crate::*; use indexmap::IndexMap; -#[allow(unused_variables)] -#[allow(clippy::redundant_closure)] // Clippy bug line 188 +// Needed to fix clippy bug. +#[allow(clippy::redudant_closure)] pub trait ReconstructingReducer { - // ciruits/functions/tests map identifier -> (identifier_item, value_item) + fn reduce_type(&mut self, _type_: &Type, new: Type) -> Type { + new + } + + // Expressions + fn reduce_expression(&mut self, _expression: &Expression, new: Expression) -> Expression { + new + } + + fn reduce_identifier(&mut self, identifier: &Identifier, span: Span) -> Identifier { + Identifier { + name: identifier.name.clone(), + span, + } + } + + fn reduce_group_tuple(&mut self, group_tuple: &GroupTuple, span: Span) -> GroupTuple { + GroupTuple { + x: group_tuple.x.clone(), + y: group_tuple.y.clone(), + span, + } + } + + fn reduce_group_value(&mut self, _group_value: &GroupValue, new: GroupValue) -> GroupValue { + new + } + + fn reduce_value(&mut self, _value: &ValueExpression, new: ValueExpression) -> ValueExpression { + new + } + + fn reduce_binary( + &mut self, + _binary: &BinaryExpression, + left: Expression, + right: Expression, + op: BinaryOperation, + span: Span, + ) -> BinaryExpression { + BinaryExpression { + left: Box::new(left), + right: Box::new(right), + op, + span, + } + } + + fn reduce_unary( + &mut self, + _unary: &UnaryExpression, + inner: Expression, + op: UnaryOperation, + span: Span, + ) -> UnaryExpression { + UnaryExpression { + inner: Box::new(inner), + op, + span, + } + } + + fn reduce_ternary( + &mut self, + _ternary: &TernaryExpression, + condition: Expression, + if_true: Expression, + if_false: Expression, + span: Span, + ) -> TernaryExpression { + TernaryExpression { + condition: Box::new(condition), + if_true: Box::new(if_true), + if_false: Box::new(if_false), + span, + } + } + + fn reduce_cast( + &mut self, + _cast: &CastExpression, + inner: Expression, + target_type: Type, + span: Span, + ) -> CastExpression { + CastExpression { + inner: Box::new(inner), + target_type, + span, + } + } + + fn reduce_array_inline( + &mut self, + _array_inline: &ArrayInlineExpression, + elements: Vec, + span: Span, + ) -> ArrayInlineExpression { + ArrayInlineExpression { elements, span } + } + + fn reduce_array_init( + &mut self, + array_init: &ArrayInitExpression, + element: Expression, + span: Span, + ) -> ArrayInitExpression { + ArrayInitExpression { + element: Box::new(element), + dimensions: array_init.dimensions.clone(), + span, + } + } + + fn reduce_array_access( + &mut self, + _array_access: &ArrayAccessExpression, + array: Expression, + index: Expression, + span: Span, + ) -> ArrayAccessExpression { + ArrayAccessExpression { + array: Box::new(array), + index: Box::new(index), + span, + } + } + + fn reduce_array_range_access( + &mut self, + _array_rage_access: &ArrayRangeAccessExpression, + array: Expression, + left: Option, + right: Option, + span: Span, + ) -> ArrayRangeAccessExpression { + ArrayRangeAccessExpression { + array: Box::new(array), + left: left.map(|expr| Box::new(expr)), + right: right.map(|expr| Box::new(expr)), + span, + } + } + + fn reduce_tuple_init( + &mut self, + _tuple_init: &TupleInitExpression, + elements: Vec, + span: Span, + ) -> TupleInitExpression { + TupleInitExpression { elements, span } + } + + fn reduce_tuple_access( + &mut self, + tuple_access: &TupleAccessExpression, + tuple: Expression, + span: Span, + ) -> TupleAccessExpression { + TupleAccessExpression { + tuple: Box::new(tuple), + index: tuple_access.index.clone(), + span, + } + } + + fn reduce_circuit_init( + &mut self, + _circuit_init: &CircuitInitExpression, + name: Identifier, + members: Vec, + span: Span, + ) -> CircuitInitExpression { + CircuitInitExpression { name, members, span } + } + + fn reduce_circuit_member_access( + &mut self, + _circuit_member_access: &CircuitMemberAccessExpression, + circuit: Expression, + name: Identifier, + span: Span, + ) -> CircuitMemberAccessExpression { + CircuitMemberAccessExpression { + circuit: Box::new(circuit), + name, + span, + } + } + + fn reduce_circuit_static_fn_access( + &mut self, + _circuit_static_fn_access: &CircuitStaticFunctionAccessExpression, + circuit: Expression, + name: Identifier, + span: Span, + ) -> CircuitStaticFunctionAccessExpression { + CircuitStaticFunctionAccessExpression { + circuit: Box::new(circuit), + name, + span, + } + } + + fn reduce_call( + &mut self, + _call: &CallExpression, + function: Expression, + arguments: Vec, + span: Span, + ) -> CallExpression { + CallExpression { + function: Box::new(function), + arguments, + span, + } + } + + // Statements + fn reduce_statement(&mut self, _statement: &Statement, new: Statement) -> Statement { + new + } + + fn reduce_return( + &mut self, + _return_statement: &ReturnStatement, + expression: Expression, + span: Span, + ) -> ReturnStatement { + ReturnStatement { expression, span } + } + + fn reduce_variable_name( + &mut self, + variable_name: &VariableName, + identifier: Identifier, + span: Span, + ) -> VariableName { + VariableName { + mutable: variable_name.mutable.clone(), + identifier, + span, + } + } + + fn reduce_definition( + &mut self, + definition: &DefinitionStatement, + variable_names: Vec, + type_: Option, + value: Expression, + span: Span, + ) -> DefinitionStatement { + DefinitionStatement { + declaration_type: definition.declaration_type.clone(), + variable_names, + type_, + value, + span, + } + } + + fn reduce_assignee_access(&mut self, _access: &AssigneeAccess, new: AssigneeAccess) -> AssigneeAccess { + new + } + + fn reduce_assignee( + &mut self, + _assignee: &Assignee, + identifier: Identifier, + accesses: Vec, + span: Span, + ) -> Assignee { + Assignee { + identifier, + accesses, + span, + } + } + + fn reduce_assign( + &mut self, + assign: &AssignStatement, + assignee: Assignee, + value: Expression, + span: Span, + ) -> AssignStatement { + AssignStatement { + operation: assign.operation.clone(), + assignee, + value, + span, + } + } + + fn reduce_conditional( + &mut self, + _conditional: &ConditionalStatement, + condition: Expression, + block: Block, + statement: Option, + span: Span, + ) -> ConditionalStatement { + ConditionalStatement { + condition, + block, + next: statement.map(|statement| Box::new(statement)), + span, + } + } + + fn reduce_iteration( + &mut self, + _iteration: &IterationStatement, + variable: Identifier, + start: Expression, + stop: Expression, + block: Block, + span: Span, + ) -> IterationStatement { + IterationStatement { + variable, + start, + stop, + block, + span, + } + } + + fn reduce_console( + &mut self, + _console: &ConsoleStatement, + function: ConsoleFunction, + span: Span, + ) -> ConsoleStatement { + ConsoleStatement { function, span } + } + + fn reduce_expression_statement( + &mut self, + _expression_statement: &ExpressionStatement, + expression: Expression, + span: Span, + ) -> ExpressionStatement { + ExpressionStatement { expression, span } + } + + fn reduce_block(&mut self, _block: &Block, statements: Vec, span: Span) -> Block { + Block { statements, span } + } + + // Program fn reduce_program( &mut self, program: &Program, @@ -61,135 +389,80 @@ pub trait ReconstructingReducer { } } - fn reduce_function_input(&mut self, input: &FunctionInput, item: FunctionInput) -> Option { - Some(item) - } - - fn reduce_import_statement( - &mut self, - import: &ImportStatement, - package_or_packages: PackageOrPackages, - ) -> Option { - Some(ImportStatement { - package_or_packages, - span: import.span.clone(), - }) - } - - fn reduce_circuit( - &mut self, - circuit: &Circuit, - circuit_name: Identifier, - members: Vec, - ) -> Option { - Some(Circuit { circuit_name, members }) - } - - fn reduce_function( - &mut self, - function: &Function, - annotations: Vec, - identifier: Identifier, - input: Vec, - output: Option, - block: Block, - ) -> Option { - Some(Function { - annotations, - identifier, - input, - output, - block, - span: function.span.clone(), - }) - } - - fn reduce_identifier(&mut self, identifier: &Identifier) -> Identifier { - identifier.clone() - } - fn reduce_function_input_variable( &mut self, - function_input_variable: &FunctionInputVariable, + variable: &FunctionInputVariable, identifier: Identifier, type_: Type, + span: Span, ) -> FunctionInputVariable { FunctionInputVariable { identifier, - const_: function_input_variable.const_, - mutable: function_input_variable.mutable, + const_: variable.const_.clone(), + mutable: variable.mutable, type_, - span: function_input_variable.span.clone(), + span, } } - fn reduce_type(&mut self, type_: &Type, items: Type) -> Type { - items + fn reduce_function_input(&mut self, _input: &FunctionInput, new: FunctionInput) -> FunctionInput { + new } - fn reduce_package(&mut self, package_or_packages: &PackageOrPackages) -> PackageOrPackages { - match package_or_packages { - PackageOrPackages::Package(package) => { - let name = self.reduce_identifier(&package.name); + fn reduce_package_or_packages( + &mut self, + _package_or_packages: &PackageOrPackages, + new: PackageOrPackages, + ) -> PackageOrPackages { + new + } - 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_import( + &mut self, + _import: &ImportStatement, + package_or_packages: PackageOrPackages, + span: Span, + ) -> ImportStatement { + ImportStatement { + package_or_packages, + span, } } - fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember, items: CircuitMember) -> Option { - Some(items) + fn reduce_circuit_member(&mut self, _circuit_member: &CircuitMember, new: CircuitMember) -> CircuitMember { + new } - fn reduce_statement(&mut self, statement: &Statement, items: Statement) -> Statement { - items + fn reduce_circuit(&mut self, _circuit: &Circuit, circuit_name: Identifier, members: Vec) -> Circuit { + Circuit { circuit_name, members } } - fn reduce_assignee_access( + fn reduce_annotation(&mut self, annotation: &Annotation, span: Span, name: Identifier) -> Annotation { + Annotation { + span, + name, + arguments: annotation.arguments.clone(), + } + } + + #[allow(clippy::too_many_arguments)] + fn reduce_function( &mut self, - assignee_access: &AssigneeAccess, - item: AssigneeAccess, - ) -> Option { - Some(item) - } - - fn reduce_conditional_statement( - &mut self, - statement: &ConditionalStatement, - condition: Expression, + _function: &Function, + identifier: Identifier, + annotations: Vec, + input: Vec, + output: Option, block: Block, - next: Option, - ) -> 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, + span: Span, + ) -> Function { + Function { identifier, - span: variable_name.span.clone(), + annotations, + input, + output, + block, + span, } } - - fn reduce_expression(&mut self, expression: &Expression, items: Expression) -> Expression { - items - } }