mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-26 16:37:30 +03:00
Fix flattening
This commit is contained in:
parent
962526dab5
commit
6f48a4a01c
@ -281,6 +281,8 @@ pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a, CurrentNetwork>) ->
|
|||||||
// Compile Leo program to bytecode.
|
// Compile Leo program to bytecode.
|
||||||
let bytecode = parsed.code_generation_pass(&st, &struct_graph, &call_graph)?;
|
let bytecode = parsed.code_generation_pass(&st, &struct_graph, &call_graph)?;
|
||||||
|
|
||||||
|
println!("Bytecode: {bytecode}");
|
||||||
|
|
||||||
Ok(bytecode)
|
Ok(bytecode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +41,9 @@ impl ProgramReconstructor for Flattener<'_> {
|
|||||||
|
|
||||||
/// Flattens a function's body
|
/// Flattens a function's body
|
||||||
fn reconstruct_function(&mut self, function: Function) -> Function {
|
fn reconstruct_function(&mut self, function: Function) -> Function {
|
||||||
// If the function is an async function, then return it as is.
|
// Set when the function is an async function.
|
||||||
// Note that async functions are not flattened since it uses `branch` instructions to produce correct code in for conditional execution.
|
self.is_async = function.variant.is_async_function();
|
||||||
if function.variant.is_async_function() {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
// Otherwise, flatten the function body.
|
|
||||||
else {
|
|
||||||
// Flatten the function body.
|
// Flatten the function body.
|
||||||
let mut block = self.reconstruct_block(function.block).0;
|
let mut block = self.reconstruct_block(function.block).0;
|
||||||
|
|
||||||
@ -69,5 +65,4 @@ impl ProgramReconstructor for Flattener<'_> {
|
|||||||
id: function.id,
|
id: function.id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,11 @@ impl StatementReconstructor for Flattener<'_> {
|
|||||||
fn reconstruct_assert(&mut self, input: AssertStatement) -> (Statement, Self::AdditionalOutput) {
|
fn reconstruct_assert(&mut self, input: AssertStatement) -> (Statement, Self::AdditionalOutput) {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
|
// If we are traversing an async function, then we can return the assert as it.
|
||||||
|
if self.is_async {
|
||||||
|
return (Statement::Assert(input), statements);
|
||||||
|
}
|
||||||
|
|
||||||
// Flatten the arguments of the assert statement.
|
// Flatten the arguments of the assert statement.
|
||||||
let assert = AssertStatement {
|
let assert = AssertStatement {
|
||||||
span: input.span,
|
span: input.span,
|
||||||
@ -222,6 +227,29 @@ impl StatementReconstructor for Flattener<'_> {
|
|||||||
fn reconstruct_conditional(&mut self, conditional: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
|
fn reconstruct_conditional(&mut self, conditional: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
|
||||||
let mut statements = Vec::with_capacity(conditional.then.statements.len());
|
let mut statements = Vec::with_capacity(conditional.then.statements.len());
|
||||||
|
|
||||||
|
// If we are traversing an async function, reconstruct the if and else blocks, but do not flatten them.
|
||||||
|
if self.is_async {
|
||||||
|
let then_block = self.reconstruct_block(conditional.then).0;
|
||||||
|
let otherwise_block = match conditional.otherwise {
|
||||||
|
Some(statement) => match *statement {
|
||||||
|
Statement::Block(block) => self.reconstruct_block(block).0,
|
||||||
|
_ => unreachable!("SSA guarantees that the `otherwise` is always a `Block`"),
|
||||||
|
},
|
||||||
|
None => Block { span: Default::default(), statements: Vec::new(), id: self.node_builder.next_id() },
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
Statement::Conditional(ConditionalStatement {
|
||||||
|
condition: conditional.condition,
|
||||||
|
then: then_block,
|
||||||
|
otherwise: Some(Box::new(Statement::Block(otherwise_block))),
|
||||||
|
span: conditional.span,
|
||||||
|
id: conditional.id,
|
||||||
|
}),
|
||||||
|
statements,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Add condition to the condition stack.
|
// Add condition to the condition stack.
|
||||||
self.condition_stack.push(conditional.condition.clone());
|
self.condition_stack.push(conditional.condition.clone());
|
||||||
|
|
||||||
@ -269,6 +297,10 @@ impl StatementReconstructor for Flattener<'_> {
|
|||||||
/// Transforms a return statement into an empty block statement.
|
/// Transforms a return statement into an empty block statement.
|
||||||
/// Stores the arguments to the return statement, which are later folded into a single return statement at the end of the function.
|
/// Stores the arguments to the return statement, which are later folded into a single return statement at the end of the function.
|
||||||
fn reconstruct_return(&mut self, input: ReturnStatement) -> (Statement, Self::AdditionalOutput) {
|
fn reconstruct_return(&mut self, input: ReturnStatement) -> (Statement, Self::AdditionalOutput) {
|
||||||
|
// If we are traversing an async function, return as is.
|
||||||
|
if self.is_async {
|
||||||
|
return (Statement::Return(input), Default::default());
|
||||||
|
}
|
||||||
// Construct the associated guard.
|
// Construct the associated guard.
|
||||||
let guard = self.construct_guard();
|
let guard = self.construct_guard();
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ pub struct Flattener<'a> {
|
|||||||
pub(crate) returns: Vec<(Option<Expression>, ReturnStatement)>,
|
pub(crate) returns: Vec<(Option<Expression>, ReturnStatement)>,
|
||||||
/// The program name.
|
/// The program name.
|
||||||
pub(crate) program: Option<Symbol>,
|
pub(crate) program: Option<Symbol>,
|
||||||
|
/// Whether the function is an async function.
|
||||||
|
pub(crate) is_async: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Flattener<'a> {
|
impl<'a> Flattener<'a> {
|
||||||
@ -84,6 +86,7 @@ impl<'a> Flattener<'a> {
|
|||||||
condition_stack: Vec::new(),
|
condition_stack: Vec::new(),
|
||||||
returns: Vec::new(),
|
returns: Vec::new(),
|
||||||
program: None,
|
program: None,
|
||||||
|
is_async: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +9,10 @@ outputs:
|
|||||||
initial_ast: 31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0
|
initial_ast: 31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0
|
||||||
unrolled_ast: 31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0
|
unrolled_ast: 31d6210343f8a439e9a731aa2b344a0a35bb4828fcbfb5b7f3d3c532aa0d49e0
|
||||||
ssa_ast: ed0d528c739439b087da26d083d1a1c6705e5e9b020f6dbb6d1510929df3079f
|
ssa_ast: ed0d528c739439b087da26d083d1a1c6705e5e9b020f6dbb6d1510929df3079f
|
||||||
flattened_ast: 6022517c96f9f27f698a3763e2745248829606c98f0089a6ec969c21e46c17e8
|
flattened_ast: 853653a2db1cb618cf7fe214cc90ff1ee6f952dbc6e945b6b3c4b34ca07e906d
|
||||||
destructured_ast: d3da411156bdf490343160266cbc638347e8699097e129137eaf2eb328d5227c
|
destructured_ast: 0fa73a1e802c55fe76758295dbeb0e4a9340fd95c14b05b033fd9aec1a039fed
|
||||||
inlined_ast: ab6e5a75c050c438cf92aeb65992405668b7587c04c088d5b158a9bbecf31c55
|
inlined_ast: 17df43530f88543010218898759c3459f380370012717bebaec75f9a27d40130
|
||||||
dce_ast: ab6e5a75c050c438cf92aeb65992405668b7587c04c088d5b158a9bbecf31c55
|
dce_ast: 17df43530f88543010218898759c3459f380370012717bebaec75f9a27d40130
|
||||||
bytecode: d6edcce70bf27b2fad397a62ae0bee08448a0c157d89e49867d843d83a04bfb7
|
bytecode: ed6b317a872c3d7083d96539a0f0601af2dcc1a6d198d897edf7f6d4db26e47a
|
||||||
errors: ""
|
errors: ""
|
||||||
warnings: ""
|
warnings: ""
|
||||||
|
Loading…
Reference in New Issue
Block a user