cairo_lang_sierra_generator/
executables.rsuse std::collections::HashMap;
use cairo_lang_diagnostics::ToOption;
use cairo_lang_filesystem::ids::CrateId;
use cairo_lang_lowering::ids::ConcreteFunctionWithBodyId;
use cairo_lang_sierra::ids::FunctionId;
use cairo_lang_sierra::program::Program;
use cairo_lang_syntax::node::helpers::QueryAttrs;
use cairo_lang_utils::LookupIntern;
use smol_str::SmolStr;
use crate::db::SierraGenGroup;
pub fn find_executable_function_ids(
db: &dyn SierraGenGroup,
main_crate_ids: Vec<CrateId>,
) -> HashMap<ConcreteFunctionWithBodyId, Vec<SmolStr>> {
let executable_attributes = db
.macro_plugins()
.iter()
.flat_map(|plugin| plugin.executable_attributes())
.map(SmolStr::new)
.collect::<Vec<_>>();
let mut executable_function_ids = HashMap::new();
if !executable_attributes.is_empty() {
for crate_id in main_crate_ids {
for module in db.crate_modules(crate_id).iter() {
if let Some(free_functions) = db.module_free_functions(*module).to_option() {
for (free_func_id, body) in free_functions.iter() {
let found_attrs = executable_attributes
.clone()
.iter()
.filter(|attr| body.has_attr(db.upcast(), attr.as_str()))
.cloned()
.collect::<Vec<_>>();
if found_attrs.is_empty() {
continue;
}
let function_id = ConcreteFunctionWithBodyId::from_no_generics_free(
db.upcast(),
*free_func_id,
);
if let Some(function_id) = function_id {
executable_function_ids.insert(function_id, found_attrs);
}
}
}
}
}
}
executable_function_ids
}
pub fn collect_executables(
db: &dyn SierraGenGroup,
mut executable_function_ids: HashMap<ConcreteFunctionWithBodyId, Vec<SmolStr>>,
sierra_program: &Program,
) -> HashMap<SmolStr, Vec<FunctionId>> {
if executable_function_ids.is_empty() {
Default::default()
} else {
let executable_function_ids = executable_function_ids
.drain()
.filter_map(|(function_id, attrs)| {
let function_id = function_id
.function_id(db.upcast())
.to_option()
.map(|function_id| db.intern_sierra_function(function_id));
function_id.map(|function_id| (function_id, attrs))
})
.collect::<HashMap<FunctionId, Vec<SmolStr>>>();
let mut result: HashMap<SmolStr, Vec<(String, FunctionId)>> = Default::default();
for function in &sierra_program.funcs {
let Some(found_attrs) = executable_function_ids.get(&function.id) else {
continue;
};
let full_path = function.id.lookup_intern(db).semantic_full_path(db.upcast());
for attr in found_attrs {
result
.entry(attr.clone())
.or_default()
.push((full_path.clone(), function.id.clone()));
}
}
result
.drain()
.map(|(key, functions)| {
let mut functions = functions.into_iter().collect::<Vec<_>>();
functions.sort_by_key(|(full_path, _)| full_path.clone());
(key, functions.into_iter().map(|(_, function_id)| function_id).collect::<Vec<_>>())
})
.collect::<HashMap<SmolStr, Vec<FunctionId>>>()
}
}