Skip to main content

luaur_analysis/methods/
constraint_generator_lookup.rs

1use crate::functions::get_def::get_def_id;
2use crate::records::blocked_type::BlockedType;
3use crate::records::cell::Cell;
4use crate::records::constraint_generator::ConstraintGenerator;
5use crate::records::phi::Phi;
6use crate::records::scope::Scope;
7use crate::records::type_ids::TypeIds;
8use crate::type_aliases::def_id_def::DefId;
9use crate::type_aliases::scope_ptr_constraint_generator::ScopePtr;
10use crate::type_aliases::type_id::TypeId;
11use luaur_ast::records::location::Location;
12
13impl ConstraintGenerator {
14    pub fn lookup(
15        &mut self,
16        scope: &ScopePtr,
17        location: Location,
18        def: DefId,
19        prototype: bool,
20    ) -> Option<TypeId> {
21        if unsafe { !get_def_id::<Cell>(def).is_null() } {
22            return scope.lookup_def_id(def);
23        }
24
25        if let Some(phi) = unsafe { get_def_id::<Phi>(def).as_ref() } {
26            if let Some(found) = scope.lookup_def_id(def) {
27                return Some(found);
28            } else if !prototype && phi.operands.len() == 1 {
29                return self.lookup(scope, location, phi.operands[0], prototype);
30            } else if !prototype {
31                return None;
32            }
33
34            let mut res = unsafe { (*self.builtin_types).neverType };
35
36            for operand in &phi.operands {
37                let mut ty = self.lookup(scope, location, *operand, /*prototype*/ false);
38                if ty.is_none() {
39                    let blocked_ty = unsafe {
40                        (*self.arena).add_type(BlockedType {
41                            index: 0,
42                            owner: core::ptr::null(),
43                        })
44                    };
45                    self.local_types.try_insert(blocked_ty, TypeIds::type_ids());
46                    unsafe {
47                        *(*self.root_scope).lvalue_types.get_or_insert(*operand) = blocked_ty;
48                    }
49                    ty = Some(blocked_ty);
50                }
51
52                res = self.make_union_scope_ptr_location_type_id_type_id(
53                    self.root_scope,
54                    location,
55                    res,
56                    ty.unwrap(),
57                );
58            }
59
60            unsafe {
61                let scope_ptr = scope.as_ref() as *const Scope as *mut Scope;
62                *(*scope_ptr).lvalue_types.get_or_insert(def) = res;
63            }
64            return Some(res);
65        }
66
67        unsafe { (*self.ice).ice_string("ConstraintGenerator::lookup is inexhaustive?") };
68        None
69    }
70}