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