mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-08-16 09:10:32 +03:00
WIP
This commit is contained in:
parent
b8a41e483d
commit
4778fe6405
@ -142,18 +142,18 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Flattens an assign statement, if necessary.
|
||||
/// Flattens a definition statement, if necessary.
|
||||
/// Marks variables as structs as necessary.
|
||||
/// Note that new statements are only produced if the right hand side is a ternary expression over structs.
|
||||
/// Otherwise, the statement is returned as is.
|
||||
fn reconstruct_assign(&mut self, assign: AssignStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
// Flatten the rhs of the assignment.
|
||||
let (value, mut statements) = self.reconstruct_expression(assign.value);
|
||||
match (assign.place, value.clone()) {
|
||||
fn reconstruct_definition(&mut self, definition: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
// Flatten the rhs of the definition.
|
||||
let (value, mut statements) = self.reconstruct_expression(definition.value);
|
||||
match (definition.place, value.clone()) {
|
||||
// If the lhs is an identifier and the rhs is a tuple, then add the tuple to `self.tuples`.
|
||||
(Expression::Identifier(identifier), Expression::Tuple(tuple)) => {
|
||||
self.tuples.insert(identifier.name, tuple);
|
||||
// Note that tuple assignments are removed from the AST.
|
||||
// Note that tuple definitions are removed from the AST.
|
||||
(Statement::dummy(Default::default(), self.node_builder.next_id()), statements)
|
||||
}
|
||||
// If the lhs is an identifier and the rhs is an identifier that is a tuple, then add it to `self.tuples`.
|
||||
@ -163,7 +163,7 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
// Lookup the entry in `self.tuples` and add it for the lhs of the assignment.
|
||||
// Note that the `unwrap` is safe since the match arm checks that the entry exists.
|
||||
self.tuples.insert(lhs_identifier.name, self.tuples.get(&rhs_identifier.name).unwrap().clone());
|
||||
// Note that tuple assignments are removed from the AST.
|
||||
// Note that tuple definitions are removed from the AST.
|
||||
(Statement::dummy(Default::default(), self.node_builder.next_id()), statements)
|
||||
}
|
||||
// If the lhs is an identifier and the rhs is a function call that produces a tuple, then add it to `self.tuples`.
|
||||
@ -185,7 +185,7 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
.zip_eq(tuple.0.iter())
|
||||
.map(|(i, type_)| {
|
||||
let identifier = Identifier::new(
|
||||
self.assigner.unique_symbol(lhs_identifier.name, format!("$index${i}$")),
|
||||
self.definer.unique_symbol(lhs_identifier.name, format!("$index${i}$")),
|
||||
self.node_builder.next_id(),
|
||||
);
|
||||
|
||||
@ -281,7 +281,10 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
}
|
||||
(Expression::Identifier(identifier), expression) => {
|
||||
self.update_structs(&identifier, &expression);
|
||||
(self.assigner.simple_assign_statement(identifier, expression, self.node_builder.next_id()), statements)
|
||||
(
|
||||
self.definer.simple_definition_statement(identifier, expression, self.node_builder.next_id()),
|
||||
statements,
|
||||
)
|
||||
}
|
||||
// If the lhs is a tuple and the rhs is a function call, then return the reconstructed statement.
|
||||
(Expression::Tuple(tuple), Expression::Call(call)) => {
|
||||
@ -429,9 +432,9 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
unreachable!("`ConsoleStatement`s should not be in the AST at this phase of compilation.")
|
||||
}
|
||||
|
||||
/// Static single assignment converts definition statements into assignment statements.
|
||||
fn reconstruct_definition(&mut self, _definition: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
unreachable!("`DefinitionStatement`s should not exist in the AST at this phase of compilation.")
|
||||
/// Static single assignment converts assignment statements into definition statements.
|
||||
fn reconstruct_assign(&mut self, _: AssignStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
unreachable!("`AssignStatement`s should not exist in the AST at this phase of compilation.")
|
||||
}
|
||||
|
||||
// TODO: Error message requesting the user to enable loop-unrolling.
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Assigner, SymbolTable};
|
||||
use crate::{Definer, SymbolTable};
|
||||
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
@ -41,8 +41,8 @@ pub struct Flattener<'a> {
|
||||
pub(crate) symbol_table: &'a SymbolTable,
|
||||
/// A counter used to generate unique node IDs.
|
||||
pub(crate) node_builder: &'a NodeBuilder,
|
||||
/// A struct used to construct (unique) assignment statements.
|
||||
pub(crate) assigner: &'a Assigner,
|
||||
/// A struct used to construct (unique) definition statements.
|
||||
pub(crate) definer: &'a Definer,
|
||||
/// The set of variables that are structs.
|
||||
pub(crate) structs: IndexMap<Symbol, Symbol>,
|
||||
/// A stack of condition `Expression`s visited up to the current point in the AST.
|
||||
@ -57,11 +57,11 @@ pub struct Flattener<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Flattener<'a> {
|
||||
pub(crate) fn new(symbol_table: &'a SymbolTable, node_builder: &'a NodeBuilder, assigner: &'a Assigner) -> Self {
|
||||
pub(crate) fn new(symbol_table: &'a SymbolTable, node_builder: &'a NodeBuilder, assigner: &'a Definer) -> Self {
|
||||
Self {
|
||||
symbol_table,
|
||||
node_builder,
|
||||
assigner,
|
||||
definer: assigner,
|
||||
structs: IndexMap::new(),
|
||||
condition_stack: Vec::new(),
|
||||
returns: Vec::new(),
|
||||
@ -115,7 +115,7 @@ impl<'a> Flattener<'a> {
|
||||
let mut construct_ternary_assignment =
|
||||
|guard: Expression, if_true: Expression, if_false: Expression| {
|
||||
let place = Identifier {
|
||||
name: self.assigner.unique_symbol(prefix, "$"),
|
||||
name: self.definer.unique_symbol(prefix, "$"),
|
||||
span: Default::default(),
|
||||
id: self.node_builder.next_id(),
|
||||
};
|
||||
@ -190,11 +190,11 @@ impl<'a> Flattener<'a> {
|
||||
/// A wrapper around `assigner.unique_simple_assign_statement` that updates `self.structs`.
|
||||
pub(crate) fn unique_simple_assign_statement(&mut self, expr: Expression) -> (Identifier, Statement) {
|
||||
// Create a new variable for the expression.
|
||||
let name = self.assigner.unique_symbol("$var", "$");
|
||||
let name = self.definer.unique_symbol("$var", "$");
|
||||
// Construct the lhs of the assignment.
|
||||
let place = Identifier { name, span: Default::default(), id: self.node_builder.next_id() };
|
||||
// Construct the assignment statement.
|
||||
let statement = self.assigner.simple_assign_statement(place, expr, self.node_builder.next_id());
|
||||
let statement = self.definer.simple_definition_statement(place, expr, self.node_builder.next_id());
|
||||
|
||||
match &statement {
|
||||
Statement::Assign(assign) => {
|
||||
@ -208,7 +208,7 @@ impl<'a> Flattener<'a> {
|
||||
/// A wrapper around `assigner.simple_assign_statement` that updates `self.structs`.
|
||||
pub(crate) fn simple_assign_statement(&mut self, lhs: Identifier, rhs: Expression) -> Statement {
|
||||
self.update_structs(&lhs, &rhs);
|
||||
self.assigner.simple_assign_statement(lhs, rhs, self.node_builder.next_id())
|
||||
self.definer.simple_definition_statement(lhs, rhs, self.node_builder.next_id())
|
||||
}
|
||||
|
||||
/// Folds a list of return statements into a single return statement and adds the produced statements to the block.
|
||||
|
@ -59,13 +59,13 @@ mod flatten_statement;
|
||||
pub mod flattener;
|
||||
pub use flattener::*;
|
||||
|
||||
use crate::{Assigner, Pass, SymbolTable};
|
||||
use crate::{Definer, Pass, SymbolTable};
|
||||
|
||||
use leo_ast::{Ast, NodeBuilder, ProgramReconstructor};
|
||||
use leo_errors::Result;
|
||||
|
||||
impl<'a> Pass for Flattener<'a> {
|
||||
type Input = (Ast, &'a SymbolTable, &'a NodeBuilder, &'a Assigner);
|
||||
type Input = (Ast, &'a SymbolTable, &'a NodeBuilder, &'a Definer);
|
||||
type Output = Result<Ast>;
|
||||
|
||||
fn do_pass((ast, st, node_builder, assigner): Self::Input) -> Self::Output {
|
||||
|
@ -59,13 +59,13 @@ mod rename_statement;
|
||||
pub mod static_single_assigner;
|
||||
pub use static_single_assigner::*;
|
||||
|
||||
use crate::{Assigner, Pass, SymbolTable};
|
||||
use crate::{Definer, Pass, SymbolTable};
|
||||
|
||||
use leo_ast::{Ast, NodeBuilder, ProgramConsumer};
|
||||
use leo_errors::Result;
|
||||
|
||||
impl<'a> Pass for StaticSingleAssigner<'a> {
|
||||
type Input = (Ast, &'a NodeBuilder, &'a Assigner, &'a SymbolTable);
|
||||
type Input = (Ast, &'a NodeBuilder, &'a Definer, &'a SymbolTable);
|
||||
type Output = Result<Ast>;
|
||||
|
||||
fn do_pass((ast, node_builder, assigner, symbol_table): Self::Input) -> Self::Output {
|
||||
|
@ -255,7 +255,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
let name = match self.is_lhs {
|
||||
// If consuming the left-hand side of a definition or assignment, a new unique name is introduced.
|
||||
true => {
|
||||
let new_name = self.assigner.unique_symbol(identifier.name, "$");
|
||||
let new_name = self.definer.unique_symbol(identifier.name, "$");
|
||||
self.rename_table.update(identifier.name, new_name);
|
||||
new_name
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
};
|
||||
self.is_lhs = false;
|
||||
|
||||
statements.push(self.assigner.simple_assign_statement(place, value, self.node_builder.next_id()));
|
||||
statements.push(self.definer.simple_definition_statement(place, value, self.node_builder.next_id()));
|
||||
|
||||
statements
|
||||
}
|
||||
@ -180,7 +180,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
};
|
||||
|
||||
// Create a new name for the variable written to in the `ConditionalStatement`.
|
||||
let new_name = self.assigner.unique_symbol(symbol, "$");
|
||||
let new_name = self.definer.unique_symbol(symbol, "$");
|
||||
|
||||
let (value, stmts) = self.consume_ternary(TernaryExpression {
|
||||
condition: Box::new(condition.clone()),
|
||||
@ -193,7 +193,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
statements.extend(stmts);
|
||||
|
||||
// Create a new `AssignStatement` for the phi function.
|
||||
let assignment = self.assigner.simple_assign_statement(
|
||||
let assignment = self.definer.simple_definition_statement(
|
||||
Identifier { name: new_name, span: Default::default(), id: self.node_builder.next_id() },
|
||||
value,
|
||||
self.node_builder.next_id(),
|
||||
@ -233,7 +233,11 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
Expression::Identifier(identifier) => identifier,
|
||||
_ => unreachable!("`self.consume_identifier` will always return an `Identifier`."),
|
||||
};
|
||||
statements.push(self.assigner.simple_assign_statement(identifier, value, self.node_builder.next_id()));
|
||||
statements.push(self.definer.simple_definition_statement(
|
||||
identifier,
|
||||
value,
|
||||
self.node_builder.next_id(),
|
||||
));
|
||||
}
|
||||
Expression::Tuple(tuple) => {
|
||||
let elements = tuple.elements.into_iter().map(|element| {
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Assigner, RenameTable, SymbolTable};
|
||||
use crate::{Definer, RenameTable, SymbolTable};
|
||||
|
||||
use leo_ast::{Expression, Identifier, NodeBuilder, Statement};
|
||||
|
||||
@ -27,14 +27,14 @@ pub struct StaticSingleAssigner<'a> {
|
||||
pub(crate) rename_table: RenameTable,
|
||||
/// A flag to determine whether or not the traversal is on the left-hand side of a definition or an assignment.
|
||||
pub(crate) is_lhs: bool,
|
||||
/// A struct used to construct (unique) assignment statements.
|
||||
pub(crate) assigner: &'a Assigner,
|
||||
/// A struct used to construct (unique) definition statements.
|
||||
pub(crate) definer: &'a Definer,
|
||||
}
|
||||
|
||||
impl<'a> StaticSingleAssigner<'a> {
|
||||
/// Initializes a new `StaticSingleAssigner` with an empty `RenameTable`.
|
||||
pub(crate) fn new(node_builder: &'a NodeBuilder, symbol_table: &'a SymbolTable, assigner: &'a Assigner) -> Self {
|
||||
Self { node_builder, symbol_table, rename_table: RenameTable::new(None), is_lhs: false, assigner }
|
||||
pub(crate) fn new(node_builder: &'a NodeBuilder, symbol_table: &'a SymbolTable, definer: &'a Definer) -> Self {
|
||||
Self { node_builder, symbol_table, rename_table: RenameTable::new(None), is_lhs: false, definer }
|
||||
}
|
||||
|
||||
/// Pushes a new scope, setting the current scope as the new scope's parent.
|
||||
@ -54,13 +54,13 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
/// The lhs is guaranteed to be unique with respect to the `Assigner`.
|
||||
pub(crate) fn unique_simple_assign_statement(&mut self, expr: Expression) -> (Identifier, Statement) {
|
||||
// Create a new variable for the expression.
|
||||
let name = self.assigner.unique_symbol("$var", "$");
|
||||
let name = self.definer.unique_symbol("$var", "$");
|
||||
|
||||
// Create a new identifier for the variable.
|
||||
let place = Identifier { name, span: Default::default(), id: self.node_builder.next_id() };
|
||||
|
||||
// Construct the statement.
|
||||
let statement = self.assigner.simple_assign_statement(place, expr, self.node_builder.next_id());
|
||||
let statement = self.definer.simple_definition_statement(place, expr, self.node_builder.next_id());
|
||||
|
||||
// Construct the identifier to be returned. Note that it must have a unique node ID.
|
||||
let identifier = Identifier { name, span: Default::default(), id: self.node_builder.next_id() };
|
||||
|
Loading…
Reference in New Issue
Block a user