1use leo_ast::{Composite, FunctionStub, Identifier, Mapping, ProgramId, Stub};
18use leo_errors::UtilError;
19use leo_span::Symbol;
20
21use snarkvm::{
22 prelude::{Itertools, Network},
23 synthesizer::program::{CommandTrait, InstructionTrait, Program, ProgramCore},
24};
25
26use std::{fmt, str::FromStr};
27
28pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
29 program: ProgramCore<N, Instruction, Command>,
30) -> Stub {
31 let program_id = ProgramId::from(program.id());
32 Stub {
33 imports: program.imports().into_iter().map(|(id, _)| ProgramId::from(id)).collect(),
34 stub_id: program_id,
35 consts: Vec::new(),
36 structs: [
37 program
38 .structs()
39 .iter()
40 .map(|(id, s)| (Identifier::from(id).name, Composite::from_snarkvm(s)))
41 .collect_vec(),
42 program
43 .records()
44 .iter()
45 .map(|(id, s)| (Identifier::from(id).name, Composite::from_external_record(s, program_id.name.name)))
46 .collect_vec(),
47 ]
48 .concat(),
49 mappings: program
50 .mappings()
51 .into_iter()
52 .map(|(id, m)| (Identifier::from(id).name, Mapping::from_snarkvm(m)))
53 .collect(),
54 functions: [
55 program
56 .closures()
57 .iter()
58 .map(|(id, closure)| {
59 (Identifier::from(id).name, FunctionStub::from_closure(closure, program_id.name.name))
60 })
61 .collect_vec(),
62 program
63 .functions()
64 .iter()
65 .map(|(id, function)| {
66 (Identifier::from(id).name, FunctionStub::from_function_core(function, program_id.name.name))
67 })
68 .collect_vec(),
69 program
70 .functions()
71 .iter()
72 .filter_map(|(id, function)| match function.finalize_logic() {
73 Some(_f) => {
74 let key_name = Symbol::intern(&format!(
75 "finalize/{}",
76 Symbol::intern(&Identifier::from(id).name.to_string())
77 ));
78 Some((key_name, FunctionStub::from_finalize(function, key_name, program_id.name.name)))
79 }
80 None => None,
81 })
82 .collect_vec(),
83 ]
84 .concat(),
85 span: Default::default(),
86 }
87}
88
89pub fn disassemble_from_str<N: Network>(name: impl fmt::Display, program: &str) -> Result<Stub, UtilError> {
90 match Program::<N>::from_str(program) {
91 Ok(p) => Ok(disassemble(p)),
92 Err(_) => Err(UtilError::snarkvm_parsing_error(name)),
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use leo_span::create_session_if_not_set_then;
100 use snarkvm::synthesizer::program::Program;
101 use std::fs;
102
103 type CurrentNetwork = snarkvm::prelude::MainnetV0;
104
105 #[test]
106 #[ignore]
107 fn credits_test() {
108 create_session_if_not_set_then(|_| {
109 let program = Program::<CurrentNetwork>::credits();
110 match program {
111 Ok(p) => {
112 let disassembled = disassemble(p);
113 println!("{}", disassembled);
114 }
115 Err(e) => {
116 println!("{}", e);
117 }
118 }
119 });
120 }
121 #[test]
122 #[ignore]
123 fn array_test() {
124 create_session_if_not_set_then(|_| {
125 let program_from_file =
126 fs::read_to_string("../tmp/.aleo/registry/mainnet/zk_bitwise_stack_v0_0_2.aleo").unwrap();
127 let _program =
128 disassemble_from_str::<CurrentNetwork>("zk_bitwise_stack_v0_0_2", &program_from_file).unwrap();
129 });
130 }
131}