use crate::{
convert_mapping,
convert_mode,
convert_plaintext,
convert_record,
convert_struct,
prune_non_interface_types,
};
use leo_abi_types as abi;
use leo_ast as ast;
use leo_span::Symbol;
use std::collections::HashSet;
pub fn generate(aleo: &ast::AleoProgram) -> abi::Program {
let program = aleo.stub_id.to_string();
let structs: Vec<abi::Struct> =
aleo.composites.iter().filter(|(_, c)| !c.is_record).map(|(_, c)| convert_struct(c, &[])).collect();
let records: Vec<abi::Record> =
aleo.composites.iter().filter(|(_, c)| c.is_record).map(|(_, c)| convert_record(c, &[])).collect();
let mappings = aleo.mappings.iter().map(|(_, m)| convert_mapping(m)).collect();
let storage_variables = vec![];
let record_names: HashSet<Symbol> =
aleo.composites.iter().filter(|(_, c)| c.is_record).map(|(name, _)| *name).collect();
let transitions = aleo
.functions
.iter()
.filter(|(_, f)| f.variant.is_transition())
.map(|(_, f)| convert_function_stub(f, &record_names))
.collect();
let mut program = abi::Program { program, structs, records, mappings, storage_variables, transitions };
prune_non_interface_types(&mut program);
program
}
fn convert_function_stub(function: &ast::FunctionStub, record_names: &HashSet<Symbol>) -> abi::Transition {
let name = function.identifier.name.to_string();
let is_async = function.variant.is_async();
let inputs = function.input.iter().map(|i| convert_input(i, record_names)).collect();
let outputs = function.output.iter().map(|o| convert_output(o, record_names)).collect();
abi::Transition { name, is_async, inputs, outputs }
}
fn convert_input(input: &ast::Input, record_names: &HashSet<Symbol>) -> abi::Input {
abi::Input {
name: input.identifier.name.to_string(),
ty: convert_transition_input(&input.type_, record_names),
mode: convert_mode(input.mode),
}
}
fn convert_output(output: &ast::Output, record_names: &HashSet<Symbol>) -> abi::Output {
abi::Output { ty: convert_transition_output(&output.type_, record_names), mode: convert_mode(output.mode) }
}
fn convert_transition_input(ty: &ast::Type, record_names: &HashSet<Symbol>) -> abi::TransitionInput {
if let ast::Type::Composite(comp_ty) = ty {
let name = comp_ty.path.identifier().name;
if record_names.contains(&name) {
return abi::TransitionInput::Record(abi::RecordRef {
path: comp_ty.path.segments_iter().map(|s| s.to_string()).collect(),
program: comp_ty.path.program().map(|s| s.to_string()),
});
}
}
abi::TransitionInput::Plaintext(convert_plaintext(ty))
}
fn convert_transition_output(ty: &ast::Type, record_names: &HashSet<Symbol>) -> abi::TransitionOutput {
match ty {
ast::Type::Future(_) => abi::TransitionOutput::Future,
ast::Type::Composite(comp_ty) => {
let name = comp_ty.path.identifier().name;
if record_names.contains(&name) {
return abi::TransitionOutput::Record(abi::RecordRef {
path: comp_ty.path.segments_iter().map(|s| s.to_string()).collect(),
program: comp_ty.path.program().map(|s| s.to_string()),
});
}
abi::TransitionOutput::Plaintext(convert_plaintext(ty))
}
_ => abi::TransitionOutput::Plaintext(convert_plaintext(ty)),
}
}