mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-20 02:07:38 +03:00
formatting of futures in CG
This commit is contained in:
parent
dd6d40edf9
commit
143e9cdc23
@ -46,10 +46,12 @@ pub struct CodeGenerator<'a> {
|
||||
pub(crate) is_transition_function: bool,
|
||||
/// Are we traversing a finalize block?
|
||||
pub(crate) in_finalize: bool,
|
||||
// A reference to program. This is needed to look up external programs.
|
||||
/// A reference to program. This is needed to look up external programs.
|
||||
pub(crate) program: &'a Program,
|
||||
// The program ID of the current program.
|
||||
/// The program ID of the current program.
|
||||
pub(crate) program_id: Option<ProgramId>,
|
||||
/// A reference to the finalize caller.
|
||||
pub(crate) finalize_caller: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> CodeGenerator<'a> {
|
||||
@ -76,6 +78,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
in_finalize: false,
|
||||
program,
|
||||
program_id: None,
|
||||
finalize_caller: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,30 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::CodeGenerator;
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
ArrayAccess,
|
||||
ArrayExpression,
|
||||
AssociatedConstant,
|
||||
AssociatedFunction,
|
||||
BinaryExpression,
|
||||
BinaryOperation,
|
||||
CallExpression,
|
||||
CastExpression,
|
||||
ErrExpression,
|
||||
Expression,
|
||||
Identifier,
|
||||
Literal,
|
||||
MemberAccess,
|
||||
MethodCall,
|
||||
StructExpression,
|
||||
TernaryExpression,
|
||||
TupleExpression,
|
||||
Type,
|
||||
UnaryExpression,
|
||||
UnaryOperation,
|
||||
UnitExpression,
|
||||
};
|
||||
use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedConstant, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, CastExpression, ErrExpression, Expression, Identifier, Literal, MemberAccess, MethodCall, Node, StructExpression, TernaryExpression, TupleExpression, Type, UnaryExpression, UnaryOperation, UnitExpression, Variant};
|
||||
use leo_span::sym;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
@ -298,10 +275,9 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
fn visit_member_access(&mut self, input: &'a MemberAccess) -> (String, String) {
|
||||
let (inner_expr, _) = self.visit_expression(&input.inner);
|
||||
let member_access = match self.type_table.get(&input.id) {
|
||||
Some(Type::Future(_)) => format!("{inner_expr}[{}]", input.name),
|
||||
Some(Type::Composite(_)) => format!("{}.{}", inner_expr, input.name),
|
||||
_ => unreachable!("Member access must be future or struct."),
|
||||
let member_access = match self.type_table.get(&input.inner.id()) {
|
||||
Some(Type::Future(_)) => format!("{inner_expr}[{}u32]", input.name),
|
||||
_ => format!("{}.{}", inner_expr, input.name),
|
||||
};
|
||||
|
||||
(member_access, String::new())
|
||||
@ -482,12 +458,14 @@ impl<'a> CodeGenerator<'a> {
|
||||
.expect("failed to write to string");
|
||||
(destination_register, instruction)
|
||||
}
|
||||
sym::Await => {
|
||||
sym::Future => {
|
||||
let mut instruction = " await".to_string();
|
||||
writeln!(instruction, " {};", arguments[0]).expect("failed to write to string");
|
||||
(String::new(), instruction)
|
||||
}
|
||||
_ => unreachable!("All core functions should be known at this phase of compilation"),
|
||||
_ => {
|
||||
unreachable!("All core functions should be known at this phase of compilation")
|
||||
},
|
||||
};
|
||||
// Add the instruction to the list of instructions.
|
||||
instructions.push_str(&instruction);
|
||||
@ -529,7 +507,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Lookup in symbol table to determine if its an async function.
|
||||
if let Some(func) = self.symbol_table.lookup_fn_symbol(input.program.unwrap(), function_name) {
|
||||
if func.is_async && input.program.unwrap() == self.program_id.unwrap().name.name {
|
||||
format!(" async {}", input.function)
|
||||
format!(" async {}", self.current_function.unwrap().identifier)
|
||||
} else {
|
||||
format!(" call {}", input.function)
|
||||
}
|
||||
@ -548,8 +526,9 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Initialize storage for the destination registers.
|
||||
let mut destinations = Vec::new();
|
||||
|
||||
let return_type = &self.symbol_table.lookup_fn_symbol(main_program, function_name).unwrap().output_type;
|
||||
match return_type {
|
||||
// Create operands for the output registers.
|
||||
let func = self.symbol_table.lookup_fn_symbol(main_program, function_name).unwrap();
|
||||
match &func.output_type {
|
||||
Type::Unit => {} // Do nothing
|
||||
Type::Tuple(tuple) => match tuple.length() {
|
||||
0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"),
|
||||
@ -568,6 +547,13 @@ impl<'a> CodeGenerator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Add a register for async functions to represent the future created.
|
||||
if func.is_async && func.variant == Variant::Standard {
|
||||
let destination_register = format!("r{}", self.next_register);
|
||||
destinations.push(destination_register);
|
||||
self.next_register += 1;
|
||||
}
|
||||
|
||||
// Construct the output operands. These are the destination registers **without** the future.
|
||||
let output_operands = destinations.join(" ");
|
||||
|
||||
|
@ -95,7 +95,10 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
// Attach the associated finalize to async transitions.
|
||||
if function.variant == Variant::Transition && function.is_async {
|
||||
// Set state variables.
|
||||
self.is_transition_function = false;
|
||||
self.finalize_caller = Some(function.identifier.name.clone());
|
||||
// Generate code for the associated finalize function.
|
||||
let finalize = &self
|
||||
.symbol_table
|
||||
.lookup_fn_symbol(
|
||||
@ -188,7 +191,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
let mut function_string = match (function.is_async, function.variant) {
|
||||
(_, Variant::Transition) => format!("\nfunction {}:\n", function.identifier),
|
||||
(false, Variant::Standard) => format!("\nclosure {}:\n", function.identifier),
|
||||
(true, Variant::Standard) => format!("\nfinalize {}:\n", function.identifier),
|
||||
(true, Variant::Standard) => format!("\nfinalize {}:\n", self.finalize_caller.unwrap()),
|
||||
(_, Variant::Inline) => return String::from("\n"),
|
||||
};
|
||||
|
||||
@ -206,8 +209,9 @@ impl<'a> CodeGenerator<'a> {
|
||||
let type_string = match input {
|
||||
functions::Input::Internal(input) => {
|
||||
self.variable_mapping.insert(&input.identifier.name, register_string.clone());
|
||||
let visibility = match (self.is_transition_function, input.mode) {
|
||||
(true, Mode::None) => Mode::Private,
|
||||
let visibility = match (self.is_transition_function, self.in_finalize, input.mode) {
|
||||
(true, _, Mode::None) => Mode::Private,
|
||||
(_, true, Mode::None) => Mode::Public,
|
||||
_ => input.mode,
|
||||
};
|
||||
// Futures are displayed differently in the input section. `input r0 as foo.aleo/bar.future;`
|
||||
|
@ -16,22 +16,7 @@
|
||||
|
||||
use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{
|
||||
AssertStatement,
|
||||
AssertVariant,
|
||||
AssignStatement,
|
||||
Block,
|
||||
ConditionalStatement,
|
||||
ConsoleStatement,
|
||||
DefinitionStatement,
|
||||
Expression,
|
||||
ExpressionStatement,
|
||||
IterationStatement,
|
||||
Mode,
|
||||
Output,
|
||||
ReturnStatement,
|
||||
Statement,
|
||||
};
|
||||
use leo_ast::{AssertStatement, AssertVariant, AssignStatement, Block, ConditionalStatement, ConsoleStatement, DefinitionStatement, Expression, ExpressionStatement, IterationStatement, Mode, Output, ReturnStatement, Statement, Type};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
@ -89,11 +74,13 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Get the output type of the function.
|
||||
let output = self.current_function.unwrap().output.iter();
|
||||
// If the operand string is empty, initialize an empty vector.
|
||||
let operand_strings = match operand.is_empty() {
|
||||
let mut operand_strings = match operand.is_empty() {
|
||||
true => vec![],
|
||||
false => operand.split(' ').collect_vec(),
|
||||
};
|
||||
let instructions = operand_strings
|
||||
|
||||
let mut future_output = String::new();
|
||||
let mut instructions = operand_strings
|
||||
.iter()
|
||||
.zip_eq(output)
|
||||
.map(|(operand, output)| {
|
||||
@ -116,12 +103,20 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Only program functions have visibilities associated with their outputs.
|
||||
Mode::None
|
||||
};
|
||||
if let Type::Future(_) = output.type_ {
|
||||
future_output = format!(
|
||||
" output {} as {}.aleo/{}.future;\n",
|
||||
operand, self.program_id.unwrap().name, self.current_function.unwrap().identifier,
|
||||
);
|
||||
String::new()
|
||||
} else {
|
||||
format!(
|
||||
" output {} as {};\n",
|
||||
operand,
|
||||
self.visit_type_with_visibility(&output.type_, visibility)
|
||||
)
|
||||
}
|
||||
}
|
||||
Output::External(output) => {
|
||||
format!(
|
||||
" output {} as {}.aleo/{}.record;\n",
|
||||
@ -132,6 +127,9 @@ impl<'a> CodeGenerator<'a> {
|
||||
})
|
||||
.join("");
|
||||
|
||||
// Insert future output at the end.
|
||||
instructions.push_str(&future_output);
|
||||
|
||||
expression_instructions.push_str(&instructions);
|
||||
|
||||
expression_instructions
|
||||
|
Loading…
Reference in New Issue
Block a user