use crate::functions::flatten_type_pack::flatten_type_pack_id;
use crate::functions::parse_pattern_string::parse_pattern_string;
use crate::records::type_checker::TypeChecker;
use crate::records::type_pack::TypePack;
use crate::records::union_type::UnionType;
use crate::records::with_predicate::WithPredicate;
use crate::type_aliases::scope_ptr_type_infer::ScopePtr;
use crate::type_aliases::type_pack_id::TypePackId;
use alloc::sync::Arc;
use alloc::vec;
use luaur_ast::records::ast_expr_call::AstExprCall;
use luaur_ast::records::ast_expr_constant_string::AstExprConstantString;
use luaur_ast::records::ast_node::AstNode;
use luaur_ast::rtti::ast_node_as;
pub fn magic_match_handle_old_solver(
typechecker: &mut TypeChecker,
scope: &ScopePtr,
expr: &AstExprCall,
with_predicate: WithPredicate<TypePackId>,
) -> Option<WithPredicate<TypePackId>> {
let param_pack = with_predicate.r#type;
let (params, _tail) = flatten_type_pack_id(param_pack);
if params.len() < 2 || params.len() > 3 {
return None;
}
let module = typechecker.current_module.as_ref()?;
let arena = unsafe {
&mut (*(Arc::as_ptr(module) as *mut crate::records::module::Module)).internal_types
};
let pattern_index = if expr.self_ { 0 } else { 1 };
let pattern = if expr.args.size > pattern_index {
let arg = unsafe { *expr.args.data.add(pattern_index) };
unsafe { ast_node_as::<AstExprConstantString>(arg as *mut AstNode) }
} else {
core::ptr::null_mut()
};
if pattern.is_null() {
return None;
}
let return_types = unsafe {
parse_pattern_string(
core::ptr::NonNull::new_unchecked(typechecker.builtin_types),
(*pattern).value.data,
(*pattern).value.size,
)
};
if return_types.is_empty() {
return None;
}
let first_location = unsafe { &(*(*expr.args.data.add(0))).base.location };
typechecker.unify_type_id_type_id_scope_ptr_location(
params[0],
typechecker.string_type,
scope,
first_location,
);
let optional_number = arena.add_type(UnionType {
options: vec![typechecker.nil_type, typechecker.number_type],
});
let init_index = if expr.self_ { 1 } else { 2 };
if params.len() == 3 && expr.args.size > init_index {
let location = unsafe { &(*(*expr.args.data.add(init_index))).base.location };
typechecker.unify_type_id_type_id_scope_ptr_location(
params[2],
optional_number,
scope,
location,
);
}
let return_list = arena.add_type_pack_t(TypePack {
head: return_types,
tail: None,
});
Some(WithPredicate::with_predicate_t(return_list))
}