Remove flattening circuits and nested tuples

This commit is contained in:
d0cd 2022-10-10 16:15:41 -07:00
parent 6ae2d9727b
commit fdddb8054a
3 changed files with 10 additions and 117 deletions

View File

@ -18,7 +18,7 @@ use crate::Flattener;
use itertools::Itertools;
use leo_ast::{
AccessExpression, AssociatedFunction, Expression, ExpressionReconstructor, Member, MemberAccess, Statement, Struct,
AccessExpression, AssociatedFunction, Expression, ExpressionReconstructor, Member, MemberAccess, Statement,
StructExpression, StructVariableInitializer, TernaryExpression, TupleExpression,
};
@ -75,7 +75,7 @@ impl ExpressionReconstructor for Flattener<'_> {
/// Reconstructs a struct init expression, flattening any tuples in the expression.
fn reconstruct_struct_init(&mut self, input: StructExpression) -> (Expression, Self::AdditionalOutput) {
let mut statements = Vec::new();
let mut flattened_expressions = Vec::with_capacity(input.members.len());
let mut members = Vec::with_capacity(input.members.len());
// Reconstruct and flatten the argument expressions.
for member in input.members.into_iter() {
@ -83,33 +83,17 @@ impl ExpressionReconstructor for Flattener<'_> {
let (expr, stmts) = self.reconstruct_expression(member.expression.unwrap());
// Accumulate any statements produced.
statements.extend(stmts);
// Flatten the expression.
flattened_expressions.extend(self.flatten_subexpression(expr));
// Accunulate the struct members.
members.push(StructVariableInitializer {
identifier: member.identifier,
expression: Some(expr),
});
}
// Lookup the flattened definition of the struct.
// Note that this unwrap is safe since TYC guarantees that all struct are declared.
let struct_: &Struct = self.flattened_structs.get(&input.name.name).unwrap();
// Collect the names of the flattened struct members.
let names = struct_
.members
.iter()
.map(|Member { identifier, .. }| identifier)
.cloned();
let flattened_members = names
.zip_eq(flattened_expressions)
.map(|(identifier, expression)| StructVariableInitializer {
identifier,
expression: Some(expression),
})
.collect();
(
Expression::Struct(StructExpression {
name: input.name,
members: flattened_members,
members,
span: input.span,
}),
statements,

View File

@ -16,11 +16,7 @@
use crate::Flattener;
use leo_ast::{
Finalize, FinalizeStatement, Function, Identifier, Member, ProgramReconstructor, Statement, StatementReconstructor,
Struct, Type,
};
use leo_span::Symbol;
use leo_ast::{Finalize, FinalizeStatement, Function, ProgramReconstructor, Statement, StatementReconstructor, Type};
impl ProgramReconstructor for Flattener<'_> {
/// Flattens a function's body and finalize block, if it exists.
@ -102,8 +98,6 @@ impl ProgramReconstructor for Flattener<'_> {
}
};
// TODO: Flatten any tuples in the produced finalize statement.
// Add the `FinalizeStatement` to the end of the block.
block.statements.push(Statement::Finalize(FinalizeStatement {
arguments,
@ -123,75 +117,4 @@ impl ProgramReconstructor for Flattener<'_> {
span: function.span,
}
}
/// Flattens the struct definitions in the program, flattening any tuples in the definitions.
/// For example, the follow struct definitions:
/// ```leo
/// struct Bar {
/// a: u8,
/// b: (u16, u32),
/// }
///
/// struct Foo {
/// c: u8,
/// d: (Bar, (Bar, Bar)),
/// }
/// ```
/// are flattened in the following way.
/// ```leo
/// struct Bar {
/// a_0: u8,
/// b_0: u16,
/// b_1: u32,
/// }
///
/// struct Foo {
/// c_0: u8,
/// d_0: Bar,
/// d_1_0: Bar,
/// d_1_1: Bar,
/// }
fn reconstruct_struct(&mut self, input: Struct) -> Struct {
// Helper to rename and flatten a struct member.
fn rename_member(identifier: Identifier, type_: Type, index: usize) -> Vec<Member> {
// Construct the new name for the identifier.
let identifier = Identifier::new(Symbol::intern(&format!("{}_{}", identifier.name, index)));
match type_ {
// If the member is a tuple, then it must be flattened.
Type::Tuple(tuple) => {
let mut members = Vec::with_capacity(tuple.0.len());
tuple.0.into_iter().enumerate().for_each(|(i, element_type)| {
members.extend(rename_member(identifier, element_type, i));
});
members
}
// Otherwise, rename the member and return it as a singleton list.
type_ => vec![Member { identifier, type_ }],
}
}
// Flatten the circuit members.
let mut members = Vec::with_capacity(input.members.len());
input
.members
.into_iter()
.enumerate()
.for_each(|(i, Member { identifier, type_ })| {
members.extend(rename_member(identifier, type_, i));
});
// Construct the flattened struct.
let struct_ = Struct {
identifier: input.identifier,
members,
is_record: input.is_record,
span: input.span,
};
// Add the flattened struct to the struct map.
self.flattened_structs.insert(struct_.identifier.name, struct_.clone());
// Return the flattened struct.
struct_
}
}

View File

@ -18,7 +18,7 @@ use crate::{Assigner, SymbolTable};
use leo_ast::{
AccessExpression, BinaryExpression, BinaryOperation, Block, Expression, ExpressionReconstructor, Identifier,
Member, ReturnStatement, Statement, Struct, TernaryExpression, Type,
Member, ReturnStatement, Statement, TernaryExpression, Type,
};
use leo_span::Symbol;
@ -43,8 +43,6 @@ pub struct Flattener<'a> {
/// Note that finalizes are inserted in the order they are encountered during a pre-order traversal of the AST.
/// Note that type checking guarantees that there is at most one finalize in a basic block.
pub(crate) finalizes: Vec<Vec<(Option<Expression>, Expression)>>,
/// A mapping between struct names and flattened struct declarations.
pub(crate) flattened_structs: IndexMap<Symbol, Struct>,
/// A mapping between variables and flattened tuple expressions.
pub(crate) tuples: IndexMap<Symbol, Vec<Expression>>,
}
@ -58,7 +56,6 @@ impl<'a> Flattener<'a> {
condition_stack: Vec::new(),
returns: Vec::new(),
finalizes: Vec::new(),
flattened_structs: IndexMap::new(),
tuples: IndexMap::new(),
}
}
@ -216,15 +213,4 @@ impl<'a> Flattener<'a> {
}));
}
}
/// Flattens a sub-expression, returning a vector of expressions (if we a flattening a tuple).
pub(crate) fn flatten_subexpression(&self, expression: Expression) -> Vec<Expression> {
match expression {
Expression::Literal(literal) => vec![Expression::Literal(literal)],
Expression::Identifier(_identifier) => {
todo!()
}
_ => unreachable!("SSA guarantees that all sub-expressions are either literals or identifiers."),
}
}
}