cairo_lang_sierra_generator/
executables.rs1use std::collections::HashMap;
2
3use cairo_lang_diagnostics::ToOption;
4use cairo_lang_filesystem::ids::CrateId;
5use cairo_lang_lowering::ids::ConcreteFunctionWithBodyId;
6use cairo_lang_sierra::ids::FunctionId;
7use cairo_lang_sierra::program::Program;
8use cairo_lang_syntax::node::helpers::QueryAttrs;
9use cairo_lang_utils::LookupIntern;
10use smol_str::SmolStr;
11
12use crate::db::SierraGenGroup;
13
14pub fn find_executable_function_ids(
24 db: &dyn SierraGenGroup,
25 main_crate_ids: Vec<CrateId>,
26) -> HashMap<ConcreteFunctionWithBodyId, Vec<SmolStr>> {
27 let executable_attributes = db
28 .macro_plugins()
29 .iter()
30 .flat_map(|plugin| plugin.executable_attributes())
31 .map(SmolStr::new)
32 .collect::<Vec<_>>();
33 let mut executable_function_ids = HashMap::new();
34 if !executable_attributes.is_empty() {
35 for crate_id in main_crate_ids {
36 for module in db.crate_modules(crate_id).iter() {
37 if let Some(free_functions) = db.module_free_functions(*module).to_option() {
38 for (free_func_id, body) in free_functions.iter() {
39 let found_attrs = executable_attributes
40 .clone()
41 .iter()
42 .filter(|attr| body.has_attr(db.upcast(), attr.as_str()))
43 .cloned()
44 .collect::<Vec<_>>();
45 if found_attrs.is_empty() {
46 continue;
48 }
49 let function_id = ConcreteFunctionWithBodyId::from_no_generics_free(
51 db.upcast(),
52 *free_func_id,
53 );
54 if let Some(function_id) = function_id {
55 executable_function_ids.insert(function_id, found_attrs);
56 }
57 }
58 }
59 }
60 }
61 }
62 executable_function_ids
63}
64
65pub fn collect_executables(
71 db: &dyn SierraGenGroup,
72 mut executable_function_ids: HashMap<ConcreteFunctionWithBodyId, Vec<SmolStr>>,
73 sierra_program: &Program,
74) -> HashMap<SmolStr, Vec<FunctionId>> {
75 if executable_function_ids.is_empty() {
76 Default::default()
77 } else {
78 let executable_function_ids = executable_function_ids
79 .drain()
80 .filter_map(|(function_id, attrs)| {
81 let function_id = function_id
82 .function_id(db.upcast())
83 .to_option()
84 .map(|function_id| db.intern_sierra_function(function_id));
85 function_id.map(|function_id| (function_id, attrs))
86 })
87 .collect::<HashMap<FunctionId, Vec<SmolStr>>>();
88 let mut result: HashMap<SmolStr, Vec<(String, FunctionId)>> = Default::default();
89 for function in &sierra_program.funcs {
90 let Some(found_attrs) = executable_function_ids.get(&function.id) else {
91 continue;
92 };
93 let full_path = function.id.lookup_intern(db).semantic_full_path(db.upcast());
94 for attr in found_attrs {
95 result
96 .entry(attr.clone())
97 .or_default()
98 .push((full_path.clone(), function.id.clone()));
99 }
100 }
101 result
103 .drain()
104 .map(|(key, functions)| {
105 let mut functions = functions.into_iter().collect::<Vec<_>>();
106 functions.sort_by_key(|(full_path, _)| full_path.clone());
107 (key, functions.into_iter().map(|(_, function_id)| function_id).collect::<Vec<_>>())
108 })
109 .collect::<HashMap<SmolStr, Vec<FunctionId>>>()
110 }
111}