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 functions = aleo
.functions
.iter()
.filter(|(_, f)| f.variant.is_entry())
.map(|(_, f)| convert_function_stub(f, &record_names))
.collect();
let mut program = abi::Program { program, structs, records, mappings, storage_variables, functions };
prune_non_interface_types(&mut program);
program
}
fn convert_function_stub(function: &ast::FunctionStub, record_names: &HashSet<Symbol>) -> abi::Function {
let name = function.identifier.name.to_string();
let is_final = function.has_final_output();
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::Function { name, is_final, inputs, outputs }
}
fn convert_input(input: &ast::Input, record_names: &HashSet<Symbol>) -> abi::Input {
abi::Input {
name: input.identifier.name.to_string(),
ty: convert_function_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_function_output(&output.type_, record_names), mode: convert_mode(output.mode) }
}
fn convert_function_input(ty: &ast::Type, record_names: &HashSet<Symbol>) -> abi::FunctionInput {
if let ast::Type::DynRecord = ty {
return abi::FunctionInput::DynamicRecord;
}
if let ast::Type::Composite(comp_ty) = ty {
let name = comp_ty.path.identifier().name;
if record_names.contains(&name) {
return abi::FunctionInput::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::FunctionInput::Plaintext(convert_plaintext(ty))
}
fn convert_function_output(ty: &ast::Type, record_names: &HashSet<Symbol>) -> abi::FunctionOutput {
match ty {
ast::Type::Future(_) => abi::FunctionOutput::Final,
ast::Type::DynRecord => abi::FunctionOutput::DynamicRecord,
ast::Type::Composite(comp_ty) => {
let name = comp_ty.path.identifier().name;
if record_names.contains(&name) {
return abi::FunctionOutput::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::FunctionOutput::Plaintext(convert_plaintext(ty))
}
_ => abi::FunctionOutput::Plaintext(convert_plaintext(ty)),
}
}