luaur_analysis/methods/
magic_select_infer.rs1use crate::functions::as_mutable_type_pack_alt_d::as_mutable_type_pack;
2use crate::functions::flatten_type_pack::flatten_type_pack_id;
3use crate::records::generic_error::GenericError;
4use crate::records::magic_function_call_context::MagicFunctionCallContext;
5use crate::records::type_error::TypeError;
6use crate::type_aliases::type_error_data::TypeErrorData;
7use crate::type_aliases::type_id::TypeId;
8use crate::type_aliases::type_pack_variant::TypePackVariant;
9use alloc::string::ToString;
10use alloc::vec::Vec;
11use luaur_ast::records::ast_expr_constant_number::AstExprConstantNumber;
12use luaur_ast::records::ast_expr_constant_string::AstExprConstantString;
13use luaur_ast::records::ast_node::AstNode;
14use luaur_ast::rtti::ast_node_as;
15
16pub fn magic_select_infer(context: &MagicFunctionCallContext) -> bool {
17 let solver = unsafe { context.solver.as_ref() };
18 let call_site = unsafe { context.call_site.as_ref() };
19
20 if call_site.args.size <= 0 {
21 let error = TypeError::type_error_location_type_error_data(
22 call_site.base.base.location,
23 TypeErrorData::GenericError(GenericError::new(
24 "select should take 1 or more arguments".to_string(),
25 )),
26 );
27 unsafe {
28 (*context.solver.as_ptr()).report_error_type_error(error);
29 }
30 return false;
31 }
32
33 let arg1 = unsafe { *call_site.args.data.add(0) };
34
35 let num = unsafe { ast_node_as::<AstExprConstantNumber>(arg1 as *mut AstNode) };
36 if !num.is_null() {
37 let (v, tail) = flatten_type_pack_id(context.arguments);
38
39 let offset = unsafe { (*num).value } as i32;
40 if offset > 0 {
41 let offset_usize = offset as usize;
42 if offset_usize < v.len() {
43 let res: Vec<TypeId> = v[offset_usize..].to_vec();
44 let res_type_pack = unsafe { &mut *solver.arena }
45 .add_type_pack_vector_type_id_optional_type_pack_id(res, tail);
46 let result_mut = as_mutable_type_pack(context.result);
47 unsafe {
48 (*result_mut).ty = TypePackVariant::Bound(res_type_pack);
49 }
50 } else if let Some(tail) = tail {
51 let result_mut = as_mutable_type_pack(context.result);
52 unsafe {
53 (*result_mut).ty = TypePackVariant::Bound(tail);
54 }
55 }
56
57 return true;
58 }
59
60 return false;
61 }
62
63 let str_expr = unsafe { ast_node_as::<AstExprConstantString>(arg1 as *mut AstNode) };
64 if !str_expr.is_null()
65 && unsafe { (*str_expr).value.size } == 1
66 && unsafe { *(*str_expr).value.data } == b'#' as core::ffi::c_char
67 {
68 let number_type_pack = unsafe { &mut *solver.arena }
69 .add_type_pack_initializer_list_type_id(
70 &[unsafe { &*solver.builtin_types }.numberType],
71 );
72 let result_mut = as_mutable_type_pack(context.result);
73 unsafe {
74 (*result_mut).ty = TypePackVariant::Bound(number_type_pack);
75 }
76 return true;
77 }
78
79 false
80}