Fix failing case

This commit is contained in:
Pranav Gaddamadugu 2022-10-07 00:21:05 -07:00 committed by d0cd
parent 2354cc8b41
commit 047575f9bf
10 changed files with 86 additions and 28 deletions

View File

@ -177,8 +177,8 @@ impl<'a> Compiler<'a> {
}
/// Runs the static single assignment pass.
pub fn static_single_assignment_pass(&mut self) -> Result<Assigner> {
let (ast, assigner) = StaticSingleAssigner::do_pass(std::mem::take(&mut self.ast))?;
pub fn static_single_assignment_pass(&mut self, symbol_table: &SymbolTable) -> Result<Assigner> {
let (ast, assigner) = StaticSingleAssigner::do_pass((std::mem::take(&mut self.ast), symbol_table))?;
self.ast = ast;
if self.output_options.ssa_ast {
@ -208,7 +208,7 @@ impl<'a> Compiler<'a> {
let st = self.loop_unrolling_pass(st)?;
// TODO: Make this pass optional.
let assigner = self.static_single_assignment_pass()?;
let assigner = self.static_single_assignment_pass(&st)?;
self.flattening_pass(&st, assigner)?;

View File

@ -196,7 +196,7 @@ fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>, handler: &Handler) -> R
let st = parsed.symbol_table_pass()?;
let st = parsed.type_checker_pass(st)?;
let st = parsed.loop_unrolling_pass(st)?;
let assigner = parsed.static_single_assignment_pass()?;
let assigner = parsed.static_single_assignment_pass(&st)?;
parsed.flattening_pass(&st, assigner)?;

View File

@ -65,17 +65,17 @@ pub(crate) use rename_table::*;
pub mod static_single_assigner;
pub use static_single_assigner::*;
use crate::Pass;
use crate::{Pass, SymbolTable};
use leo_ast::{Ast, ProgramConsumer};
use leo_errors::Result;
impl Pass for StaticSingleAssigner {
type Input = Ast;
impl<'a> Pass for StaticSingleAssigner<'a> {
type Input = (Ast, &'a SymbolTable);
type Output = Result<(Ast, Assigner)>;
fn do_pass(ast: Self::Input) -> Self::Output {
let mut consumer = StaticSingleAssigner::new();
fn do_pass((ast, symbol_table): Self::Input) -> Self::Output {
let mut consumer = StaticSingleAssigner::new(symbol_table);
let program = consumer.consume_program(ast.into_repr());
Ok((Ast::new(program), consumer.assigner))

View File

@ -15,15 +15,17 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::StaticSingleAssigner;
use indexmap::IndexMap;
use std::borrow::Borrow;
use leo_ast::{
AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, Expression, ExpressionConsumer, Identifier,
Literal, MemberAccess, Statement, StructExpression, StructVariableInitializer, TernaryExpression, TupleAccess,
TupleExpression, UnaryExpression,
Literal, MemberAccess, Statement, Struct, StructExpression, StructVariableInitializer, TernaryExpression,
TupleAccess, TupleExpression, UnaryExpression,
};
use leo_span::sym;
use leo_span::{sym, Symbol};
impl ExpressionConsumer for StaticSingleAssigner {
impl ExpressionConsumer for StaticSingleAssigner<'_> {
type Output = (Expression, Vec<Statement>);
/// Consumes an access expression, accumulating any statements that are generated.
@ -146,7 +148,7 @@ impl ExpressionConsumer for StaticSingleAssigner {
let mut statements = Vec::new();
// Process the members, accumulating any statements produced.
let members = input
let members: Vec<StructVariableInitializer> = input
.members
.into_iter()
.map(|arg| {
@ -169,13 +171,46 @@ impl ExpressionConsumer for StaticSingleAssigner {
})
.collect();
// Reorder the members to match that of the struct definition.
// Lookup the struct definition.
// Note that type checking guarantees that the correct struct definition exists.
let struct_definition: &Struct = self.symbol_table.borrow().structs.get(&input.name.name).unwrap();
// Initialize the list of reordered members.
let mut reordered_members = Vec::with_capacity(members.len());
// Collect the members of the init expression into a map.
let mut member_map: IndexMap<Symbol, StructVariableInitializer> = members
.into_iter()
.map(|member| (member.identifier.name, member))
.collect();
// If we are initializing a record, add the `owner` and `gates` fields, first and second respectively.
// Note that type checking guarantees that the above fields exist.
if struct_definition.is_record {
// Add the `owner` field.
reordered_members.push(member_map.remove(&sym::owner).unwrap());
// Add the `gates` field.
reordered_members.push(member_map.remove(&sym::gates).unwrap());
}
// For each member of the struct definition, push the corresponding member of the init expression.
for member in &struct_definition.members {
// If the member is part of a record and it is `owner` or `gates`, then we have already added it.
if !(struct_definition.is_record && matches!(member.identifier.name, sym::owner | sym::gates)) {
// Lookup and push the member of the init expression.
reordered_members.push(member_map.remove(&member.identifier.name).unwrap());
}
}
// Construct and accumulate a new assignment statement for the struct expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members,
members: reordered_members,
}));
statements.push(statement);

View File

@ -24,7 +24,7 @@ use leo_span::{sym, Symbol};
use indexmap::IndexMap;
impl StructConsumer for StaticSingleAssigner {
impl StructConsumer for StaticSingleAssigner<'_> {
type Output = Struct;
/// Reconstructs records in the program, ordering its fields such that `owner` and `gates` are the first and second fields, respectively.
@ -56,7 +56,7 @@ impl StructConsumer for StaticSingleAssigner {
}
}
impl FunctionConsumer for StaticSingleAssigner {
impl FunctionConsumer for StaticSingleAssigner<'_> {
type Output = Function;
/// Reconstructs the `Function`s in the `Program`, while allocating the appropriate `RenameTable`s.
@ -122,7 +122,7 @@ impl FunctionConsumer for StaticSingleAssigner {
}
}
impl ProgramScopeConsumer for StaticSingleAssigner {
impl ProgramScopeConsumer for StaticSingleAssigner<'_> {
type Output = ProgramScope;
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
@ -144,7 +144,7 @@ impl ProgramScopeConsumer for StaticSingleAssigner {
}
}
impl ProgramConsumer for StaticSingleAssigner {
impl ProgramConsumer for StaticSingleAssigner<'_> {
type Output = Program;
fn consume_program(&mut self, input: Program) -> Self::Output {

View File

@ -25,7 +25,7 @@ use leo_span::Symbol;
use indexmap::IndexSet;
impl StatementConsumer for StaticSingleAssigner {
impl StatementConsumer for StaticSingleAssigner<'_> {
type Output = Vec<Statement>;
/// Consume all `AssignStatement`s, renaming as necessary.

View File

@ -14,9 +14,11 @@
// 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};
use crate::{Assigner, RenameTable, SymbolTable};
pub struct StaticSingleAssigner {
pub struct StaticSingleAssigner<'a> {
/// The `SymbolTable` of the program.
pub(crate) symbol_table: &'a SymbolTable,
/// The `RenameTable` for the current basic block in the AST
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.
@ -25,10 +27,11 @@ pub struct StaticSingleAssigner {
pub(crate) assigner: Assigner,
}
impl StaticSingleAssigner {
impl<'a> StaticSingleAssigner<'a> {
/// Initializes a new `StaticSingleAssigner` with an empty `RenameTable`.
pub(crate) fn new() -> Self {
pub(crate) fn new(symbol_table: &'a SymbolTable) -> Self {
Self {
symbol_table,
rename_table: RenameTable::new(None),
is_lhs: false,
assigner: Assigner::default(),

View File

@ -0,0 +1,10 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: no input
initial_ast: 1d8d043ee6b48779b075545750e30307dd37c32f19bf20b51dd1b0b6b1c6724c
unrolled_ast: 1d8d043ee6b48779b075545750e30307dd37c32f19bf20b51dd1b0b6b1c6724c
ssa_ast: 12bfaf3afdf7d49c6a26f28afe115db389c0fb877b2c99c36eff9e2d3c4fd8f5
flattened_ast: 9d5413f75e5527394ff2e7ebcfb1c689e9c9b6dcfee3f891552e4a21e8db4b83

View File

@ -0,0 +1,10 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: no input
initial_ast: 188c7f18a83e56a322c8c42eee233a33f069b3397d7b891a39c54c7ed975d2f0
unrolled_ast: 188c7f18a83e56a322c8c42eee233a33f069b3397d7b891a39c54c7ed975d2f0
ssa_ast: d983bf3954f632ad6ef783bda9b8621b32aa6d90e1a7093d2e564ac430df427b
flattened_ast: d1ab80cf91a61740d2bae792cd31e663900f643cce7c14e5e6bd6282365bec56

View File

@ -187,11 +187,11 @@ impl Sample {
let symbol_table = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
compiler
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let start = Instant::now();
let out = compiler.static_single_assignment_pass();
let out = compiler.static_single_assignment_pass(&symbol_table);
let time = start.elapsed();
out.expect("failed to run ssa pass");
time
@ -208,7 +208,7 @@ impl Sample {
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass()
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let start = Instant::now();
let out = compiler.flattening_pass(&symbol_table, assigner);
@ -233,7 +233,7 @@ impl Sample {
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass()
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
compiler
.flattening_pass(&symbol_table, assigner)