Skip to main content

luaur_analysis/records/
refinement_arena_control_flow_graph.rs

1//! Source: `Analysis/src/ControlFlowGraph.cpp:18-54` (hand-ported)
2use crate::records::conjunction_control_flow_graph::Conjunction;
3use crate::records::disjunction_control_flow_graph::Disjunction;
4use crate::records::negation_control_flow_graph::Negation;
5use crate::records::proposition_control_flow_graph::Proposition;
6use crate::records::typed_allocator::TypedAllocator;
7use crate::type_aliases::def_id_control_flow_graph::DefId;
8use crate::type_aliases::refinement_control_flow_graph::{Refinement, RefinementMember};
9use crate::type_aliases::refinement_id_control_flow_graph::RefinementId;
10use alloc::string::String;
11use luaur_common::macros::luau_assert::LUAU_ASSERT;
12
13#[derive(Debug)]
14pub struct RefinementArena {
15    pub(crate) allocator: TypedAllocator<Refinement>,
16}
17
18impl RefinementArena {
19    // RefinementId RefinementArena::proposition(DefId def, bool sense)
20    pub fn proposition(&mut self, def: DefId, sense: bool) -> RefinementId {
21        // return NotNull{allocator.allocate(Proposition{def, std::nullopt, /*isTypeof*/ false, sense})};
22        self.allocator
23            .allocate(Refinement::Proposition(Proposition {
24                ptr: def,
25                r#type: None,
26                is_typeof: false,
27                sense,
28            }))
29    }
30
31    // RefinementId RefinementArena::typeProposition(DefId def, std::optional<std::string> type, bool isTypeof, bool sense)
32    pub fn type_proposition(
33        &mut self,
34        def: DefId,
35        r#type: Option<String>,
36        is_typeof: bool,
37        sense: bool,
38    ) -> RefinementId {
39        // return NotNull{allocator.allocate(Proposition{def, std::move(type), isTypeof, sense})};
40        self.allocator
41            .allocate(Refinement::Proposition(Proposition {
42                ptr: def,
43                r#type,
44                is_typeof,
45                sense,
46            }))
47    }
48
49    // RefinementId RefinementArena::conjunction(RefinementId lhs, RefinementId rhs)
50    pub fn conjunction(&mut self, lhs: RefinementId, rhs: RefinementId) -> RefinementId {
51        // return NotNull{allocator.allocate(Conjunction{lhs, rhs})};
52        self.allocator
53            .allocate(Refinement::Conjunction(Conjunction { lhs, rhs }))
54    }
55
56    // RefinementId RefinementArena::disjunction(RefinementId lhs, RefinementId rhs)
57    pub fn disjunction(&mut self, lhs: RefinementId, rhs: RefinementId) -> RefinementId {
58        // return NotNull{allocator.allocate(Disjunction{lhs, rhs})};
59        self.allocator
60            .allocate(Refinement::Disjunction(Disjunction { lhs, rhs }))
61    }
62
63    // RefinementId RefinementArena::negation(RefinementId r)
64    pub fn negation(&mut self, r: RefinementId) -> RefinementId {
65        // `get<T>(r)` is `get_if<T>(r.get())` over r's variant.
66        // if (auto* conj = get<Conjunction>(r))
67        //     return disjunction(negation(conj->lhs), negation(conj->rhs));
68        if let Some((lhs, rhs)) = unsafe { Conjunction::get_if(&*r) }.map(|c| (c.lhs, c.rhs)) {
69            let nl = self.negation(lhs);
70            let nr = self.negation(rhs);
71            return self.disjunction(nl, nr);
72        }
73        // if (auto* disj = get<Disjunction>(r))
74        //     return conjunction(negation(disj->lhs), negation(disj->rhs));
75        if let Some((lhs, rhs)) = unsafe { Disjunction::get_if(&*r) }.map(|d| (d.lhs, d.rhs)) {
76            let nl = self.negation(lhs);
77            let nr = self.negation(rhs);
78            return self.conjunction(nl, nr);
79        }
80        // if (auto* neg = get<Negation>(r))
81        //     return neg->refinement;
82        if let Some(refinement) = unsafe { Negation::get_if(&*r) }.map(|n| n.refinement) {
83            return refinement;
84        }
85
86        // LUAU_ASSERT(get<Proposition>(r));
87        LUAU_ASSERT!(unsafe { Proposition::get_if(&*r) }.is_some());
88        // return NotNull{allocator.allocate(Negation{r})};
89        self.allocator
90            .allocate(Refinement::Negation(Negation { refinement: r }))
91    }
92
93    // void RefinementArena::freeze()
94    pub fn freeze(&mut self) {
95        // allocator.freeze();
96        self.allocator.freeze();
97    }
98}