cairo_lang_lowering/graph_algorithms/
cycles.rs

1use cairo_lang_diagnostics::Maybe;
2use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
3
4use crate::DependencyType;
5use crate::db::{LoweringGroup, get_direct_callees};
6use crate::ids::{ConcreteFunctionWithBodyId, FunctionId, FunctionWithBodyId};
7
8/// Query implementation of
9/// [crate::db::LoweringGroup::function_with_body_direct_callees].
10pub fn function_with_body_direct_callees(
11    db: &dyn LoweringGroup,
12    function_id: FunctionWithBodyId,
13    dependency_type: DependencyType,
14) -> Maybe<OrderedHashSet<FunctionId>> {
15    let (lowered, block_extra_calls) =
16        db.function_with_body_lowering_with_borrow_check(function_id)?;
17    Ok(get_direct_callees(db, &lowered, dependency_type, &block_extra_calls).into_iter().collect())
18}
19
20/// Query implementation of
21/// [crate::db::LoweringGroup::function_with_body_direct_function_with_body_callees].
22pub fn function_with_body_direct_function_with_body_callees(
23    db: &dyn LoweringGroup,
24    function_id: FunctionWithBodyId,
25    dependency_type: DependencyType,
26) -> Maybe<OrderedHashSet<FunctionWithBodyId>> {
27    Ok(db
28        .function_with_body_direct_callees(function_id, dependency_type)?
29        .into_iter()
30        .map(|function_id| function_id.body(db))
31        .collect::<Maybe<Vec<Option<_>>>>()?
32        .into_iter()
33        .flatten()
34        .map(|x| x.function_with_body_id(db))
35        .collect())
36}
37
38/// Query implementation of [LoweringGroup::final_contains_call_cycle].
39pub fn final_contains_call_cycle(
40    db: &dyn LoweringGroup,
41    function_id: ConcreteFunctionWithBodyId,
42) -> Maybe<bool> {
43    let direct_callees = db.final_concrete_function_with_body_lowered_direct_callees(
44        function_id,
45        DependencyType::Call,
46    )?;
47    for callee in direct_callees {
48        if db.final_contains_call_cycle(callee)? {
49            return Ok(true);
50        }
51    }
52
53    Ok(false)
54}
55
56/// Cycle handling for [LoweringGroup::final_contains_call_cycle].
57pub fn final_contains_call_cycle_handle_cycle(
58    _db: &dyn LoweringGroup,
59    _cycle: &salsa::Cycle,
60    _function_id: &ConcreteFunctionWithBodyId,
61) -> Maybe<bool> {
62    Ok(true)
63}
64
65/// Query implementation of [LoweringGroup::in_cycle].
66pub fn in_cycle(
67    db: &dyn LoweringGroup,
68    function_id: FunctionWithBodyId,
69    dependency_type: DependencyType,
70) -> Maybe<bool> {
71    if db
72        .function_with_body_direct_function_with_body_callees(function_id, dependency_type)?
73        .contains(&function_id)
74    {
75        return Ok(true);
76    }
77    Ok(db.function_with_body_scc(function_id, dependency_type).len() > 1)
78}