mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-10 10:05:56 +03:00
Fix failing case
This commit is contained in:
parent
2354cc8b41
commit
047575f9bf
@ -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)?;
|
||||
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
@ -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
|
@ -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
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user