Skip to main content

mago_analyzer/plugin/libraries/stdlib/math/
mod.rs

1mod abs;
2mod intdiv;
3mod max;
4mod min;
5
6pub use abs::AbsProvider;
7pub use intdiv::IntdivHook;
8pub use max::MaxProvider;
9pub use min::MinProvider;
10
11use mago_codex::ttype::atomic::TAtomic;
12use mago_codex::ttype::atomic::scalar::TScalar;
13use mago_codex::ttype::atomic::scalar::int::TInteger;
14use mago_codex::ttype::union::TUnion;
15
16/// Extract a `TInteger` from a union type by computing the combined bounds of all integer atomics.
17/// Returns `None` if any atomic in the union is not an integer.
18#[allow(clippy::similar_names)]
19fn get_integer_from_type(ty: &TUnion) -> Option<TInteger> {
20    let mut result_lb: Option<Option<i64>> = None;
21    let mut result_ub: Option<Option<i64>> = None;
22
23    for atomic in ty.types.iter() {
24        let TAtomic::Scalar(TScalar::Integer(integer)) = atomic else {
25            return None;
26        };
27
28        let (lb, ub) = integer.get_bounds();
29
30        result_lb = Some(match result_lb {
31            None => lb,
32            Some(prev) => match (prev, lb) {
33                (Some(a), Some(b)) => Some(std::cmp::min(a, b)),
34                _ => None,
35            },
36        });
37
38        result_ub = Some(match result_ub {
39            None => ub,
40            Some(prev) => match (prev, ub) {
41                (Some(a), Some(b)) => Some(std::cmp::max(a, b)),
42                _ => None,
43            },
44        });
45    }
46
47    Some(TInteger::from_bounds(result_lb?, result_ub?))
48}
49
50/// Collect all integer atomics from a union type. Returns `None` if any atomic is not an integer.
51fn collect_integers(ty: &TUnion) -> Option<Vec<TInteger>> {
52    let mut integers = Vec::new();
53    for atomic in ty.types.iter() {
54        match atomic {
55            TAtomic::Scalar(TScalar::Integer(integer)) => integers.push(*integer),
56            _ => return None,
57        }
58    }
59
60    Some(integers)
61}