Skip to main content

luaur_analysis/methods/
magic_select_handle_old_solver.rs

1use crate::functions::flatten_type_pack::flatten_type_pack_id;
2use crate::records::generic_error::GenericError;
3use crate::records::magic_select::MagicSelect;
4use crate::records::type_checker::TypeChecker;
5use crate::records::type_error::TypeError;
6use crate::records::with_predicate::WithPredicate;
7use crate::type_aliases::scope_ptr_type_infer::ScopePtr;
8use crate::type_aliases::type_error_data::TypeErrorData;
9use crate::type_aliases::type_id::TypeId;
10use crate::type_aliases::type_pack_id::TypePackId;
11use alloc::vec;
12use luaur_ast::records::ast_expr::AstExpr;
13use luaur_ast::records::ast_expr_call::AstExprCall;
14use luaur_ast::records::ast_expr_constant_number::AstExprConstantNumber;
15use luaur_ast::records::ast_expr_constant_string::AstExprConstantString;
16use luaur_ast::records::ast_node::AstNode;
17use luaur_ast::rtti::ast_node_as;
18
19pub fn magic_select_handle_old_solver(
20    typechecker: &mut TypeChecker,
21    scope: &ScopePtr,
22    expr: &AstExprCall,
23    with_predicate: WithPredicate<TypePackId>,
24) -> Option<WithPredicate<TypePackId>> {
25    let (param_pack, _predicates) = (with_predicate.r#type, with_predicate.predicates);
26
27    let _ = scope;
28
29    if expr.args.size <= 0 {
30        typechecker.report_error_type_error(&TypeError::type_error_location_type_error_data(
31            expr.base.base.location,
32            TypeErrorData::GenericError(GenericError::new(
33                "select should take 1 or more arguments".to_string(),
34            )),
35        ));
36        return None;
37    }
38
39    let arg1 = unsafe { *expr.args.data.add(0) };
40    let num = unsafe { ast_node_as::<AstExprConstantNumber>(arg1 as *mut AstNode) };
41    if !num.is_null() {
42        let (params, tail) = flatten_type_pack_id(param_pack);
43
44        let offset = unsafe { (*num).value } as i32;
45        if offset > 0 {
46            let offset_usize = offset as usize;
47            if offset_usize < params.len() {
48                let result: Vec<TypeId> = params[offset_usize..].to_vec();
49                return Some(WithPredicate::with_predicate_t(
50                    typechecker.add_type_pack_vector_type_id_optional_type_pack_id(&result, tail),
51                ));
52            } else if tail.is_some() {
53                return Some(WithPredicate::with_predicate_t(tail.unwrap()));
54            }
55        }
56
57        typechecker.report_error_type_error(&TypeError::type_error_location_type_error_data(
58            unsafe { (*num).base.base.location },
59            TypeErrorData::GenericError(GenericError::new(
60                "bad argument #1 to select (index out of range)".to_string(),
61            )),
62        ));
63    } else {
64        let str_expr = unsafe { ast_node_as::<AstExprConstantString>(arg1 as *mut AstNode) };
65        if !str_expr.is_null()
66            && unsafe { (*str_expr).value.size } == 1
67            && unsafe { *(*str_expr).value.data } == b'#' as core::ffi::c_char
68        {
69            return Some(WithPredicate::with_predicate_t(
70                typechecker.add_type_pack_initializer_list_type_id(&[typechecker.number_type]),
71            ));
72        }
73    }
74
75    None
76}