Skip to main content

luaur_analysis/methods/
constraint_generator_create_generics.rs

1use crate::enums::polarity::Polarity;
2use crate::records::blocked_type::BlockedType;
3use crate::records::constraint_generator::ConstraintGenerator;
4use crate::records::generic_type::GenericType;
5use crate::records::generic_type_definition::GenericTypeDefinition;
6use crate::records::scope::Scope;
7use crate::records::type_fun::TypeFun;
8use crate::type_aliases::name_type::Name;
9use crate::type_aliases::scope_ptr_type::ScopePtr;
10use crate::type_aliases::type_id::TypeId;
11use alloc::vec::Vec;
12use luaur_ast::records::ast_array::AstArray;
13use luaur_ast::records::ast_generic_type::AstGenericType;
14
15impl ConstraintGenerator {
16    pub fn create_generics(
17        &mut self,
18        scope: &ScopePtr,
19        generics: AstArray<*mut AstGenericType>,
20        use_cache: bool,
21        add_types: bool,
22    ) -> Vec<(Name, GenericTypeDefinition)> {
23        let mut result: Vec<(Name, GenericTypeDefinition)> = Vec::new();
24
25        let parent_scope = scope.parent.as_ref().unwrap();
26        let parent_scope_ptr = parent_scope.as_ref() as *const Scope as *mut Scope;
27        let scope_ptr = scope.as_ref() as *const Scope as *mut Scope;
28
29        for i in 0..generics.size {
30            let generic = unsafe { *generics.data.add(i) };
31
32            let generic_name_ptr = unsafe { (*generic).name.value };
33            let generic_name = unsafe { core::ffi::CStr::from_ptr(generic_name_ptr) }
34                .to_string_lossy()
35                .into_owned();
36
37            let generic_ty: TypeId;
38
39            if use_cache {
40                if let Some(ty) = parent_scope
41                    .type_alias_type_parameters
42                    .get(generic_name.as_str())
43                {
44                    generic_ty = *ty;
45                } else {
46                    generic_ty = unsafe {
47                        (*self.arena).add_type(GenericType::generic_type_scope_name_polarity(
48                            scope_ptr,
49                            generic_name.clone(),
50                            Polarity::None,
51                        ))
52                    };
53                    unsafe {
54                        (*parent_scope_ptr)
55                            .type_alias_type_parameters
56                            .insert(generic_name.clone(), generic_ty);
57                    }
58                }
59            } else {
60                generic_ty = unsafe {
61                    (*self.arena).add_type(GenericType::generic_type_scope_name_polarity(
62                        scope_ptr,
63                        generic_name.clone(),
64                        Polarity::None,
65                    ))
66                };
67                unsafe {
68                    (*parent_scope_ptr)
69                        .type_alias_type_parameters
70                        .insert(generic_name.clone(), generic_ty);
71                }
72            }
73
74            let default_ty: Option<TypeId> = if unsafe { (*generic).default_value }.is_null() {
75                None
76            } else {
77                unsafe { (*self.arena).add_type(BlockedType::default()) }.into()
78            };
79
80            if add_types {
81                unsafe {
82                    (*scope_ptr)
83                        .private_type_bindings
84                        .insert(generic_name.clone(), TypeFun::type_fun_type_id(generic_ty));
85                }
86            }
87
88            result.push((
89                generic_name,
90                GenericTypeDefinition {
91                    ty: generic_ty,
92                    defaultValue: default_ty,
93                },
94            ));
95        }
96
97        result
98    }
99}