luaur_analysis/functions/
get_generics.rs1use crate::functions::allocate_type_function_type_pack::allocate_type_function_type_pack;
6use crate::functions::get_type_function_runtime_alt_o::get_type_function_type_id;
7use crate::functions::get_type_user_data::get_type_user_data;
8use crate::records::type_function_generic_type::TypeFunctionGenericType;
9use crate::records::type_function_generic_type_pack::TypeFunctionGenericTypePack;
10use crate::type_aliases::lua_state::lua_State;
11use crate::type_aliases::type_function_type_id::TypeFunctionTypeId;
12use crate::type_aliases::type_function_type_pack_id::TypeFunctionTypePackId;
13use crate::type_aliases::type_function_type_pack_variant::TypeFunctionTypePackVariant;
14use alloc::vec::Vec;
15use luaur_vm::functions::lua_gettable::lua_gettable;
16use luaur_vm::functions::lua_l_error_l::lua_l_error_l;
17use luaur_vm::functions::lua_l_typeerror_l::lua_l_typeerror_l;
18use luaur_vm::functions::lua_objlen::lua_objlen;
19use luaur_vm::functions::lua_pushinteger::lua_pushinteger;
20use luaur_vm::functions::lua_pushvalue::lua_pushvalue;
21use luaur_vm::macros::lua_isnil::lua_isnil;
22use luaur_vm::macros::lua_isnoneornil::lua_isnoneornil;
23use luaur_vm::macros::lua_istable::lua_istable;
24use luaur_vm::macros::lua_pop::lua_pop;
25
26pub unsafe fn get_generics(
27 l: *mut lua_State,
28 idx: i32,
29 fname: &str,
30) -> (Vec<TypeFunctionTypeId>, Vec<TypeFunctionTypePackId>) {
31 let vm_l = l as *mut luaur_vm::records::lua_state::lua_State;
32
33 let mut types: Vec<TypeFunctionTypeId> = Vec::new();
34 let mut packs: Vec<TypeFunctionTypePackId> = Vec::new();
35
36 if lua_istable!(vm_l, idx) {
37 lua_pushvalue(vm_l, idx);
38
39 let mut i: core::ffi::c_int = 1;
40 while i <= lua_objlen(vm_l, -1) {
41 lua_pushinteger(vm_l, i);
42 lua_gettable(vm_l, -2);
43
44 if lua_isnil!(vm_l, -1) {
45 lua_pop(vm_l, 1);
46 break;
47 }
48
49 let ty = get_type_user_data(l, -1);
51
52 let gty = get_type_function_type_id::<TypeFunctionGenericType>(ty);
54 if !gty.is_null() {
55 if (*gty).is_pack {
56 packs.push(allocate_type_function_type_pack(
57 l,
58 TypeFunctionTypePackVariant::V2(TypeFunctionGenericTypePack {
59 is_named: (*gty).is_named,
60 name: (*gty).name.clone(),
61 }),
62 ));
63 } else {
64 if !packs.is_empty() {
65 lua_l_error_l(
66 vm_l,
67 c"%s".as_ptr(),
68 core::format_args!(
69 "{}: generic type cannot follow a generic pack",
70 fname
71 ),
72 );
73 }
74
75 types.push(ty);
76 }
77 } else {
78 lua_l_error_l(
79 vm_l,
80 c"%s".as_ptr(),
81 core::format_args!("{}: table member was not a generic type", fname),
82 );
83 }
84
85 lua_pop(vm_l, 1);
86 i += 1;
87 }
88
89 lua_pop(vm_l, 1);
90 } else if !lua_isnoneornil!(vm_l, idx) {
91 lua_l_typeerror_l(vm_l, idx, "table");
92 }
93
94 (types, packs)
95}