Skip to main content

luaur_analysis/functions/
check_result_for_error.rs

1use alloc::string::String;
2use core::ffi::c_int;
3use luaur_common::functions::format::format;
4use luaur_common::records::variant::Variant5;
5use luaur_vm::functions::lua_gettop::lua_gettop;
6use luaur_vm::functions::lua_isstring::lua_isstring;
7use luaur_vm::functions::lua_typename::lua_typename;
8use luaur_vm::macros::lua_tostring::lua_tostring;
9
10use crate::records::runtime_error::RuntimeError;
11use crate::records::type_function_error::TypeFunctionError;
12use crate::type_aliases::lua_state::lua_State;
13use luaur_ast::records::location::Location;
14
15pub fn check_result_for_error(
16    L: *mut lua_State,
17    type_function_name: &str,
18    lua_result: c_int,
19) -> Option<TypeFunctionError> {
20    match lua_result {
21        0 => None, // LUA_OK
22        1 | 3 => Some(
23            TypeFunctionError::type_function_error_location_type_function_error_data(
24                Location::new(Default::default(), Default::default()),
25                Variant5::V2(RuntimeError::new(format(format_args!(
26                    "'{}' type function errored: unexpected yield or break",
27                    type_function_name
28                )))),
29            ),
30        ), // LUA_YIELD, LUA_BREAK
31        _ => {
32            if unsafe { lua_gettop(L as *mut luaur_vm::records::lua_state::lua_State) } == 0 {
33                Some(
34                    TypeFunctionError::type_function_error_location_type_function_error_data(
35                        Location::new(Default::default(), Default::default()),
36                        Variant5::V2(RuntimeError::new(format(format_args!(
37                            "'{}' type function errored unexpectedly",
38                            type_function_name
39                        )))),
40                    ),
41                )
42            } else if unsafe { lua_isstring(L as *mut luaur_vm::records::lua_state::lua_State, -1) }
43                != 0
44            {
45                let err_str =
46                    unsafe { lua_tostring!(L as *mut luaur_vm::records::lua_state::lua_State, -1) };
47                let err_str = unsafe { core::ffi::CStr::from_ptr(err_str).to_string_lossy() };
48                Some(
49                    TypeFunctionError::type_function_error_location_type_function_error_data(
50                        Location::new(Default::default(), Default::default()),
51                        Variant5::V2(RuntimeError::new(format(format_args!(
52                            "'{}' type function errored at runtime: {}",
53                            type_function_name, err_str
54                        )))),
55                    ),
56                )
57            } else {
58                let err_type =
59                    unsafe { lua_typename(L as *mut luaur_vm::records::lua_state::lua_State, -1) };
60                let err_type = unsafe { core::ffi::CStr::from_ptr(err_type).to_string_lossy() };
61                Some(
62                    TypeFunctionError::type_function_error_location_type_function_error_data(
63                        Location::new(Default::default(), Default::default()),
64                        Variant5::V2(RuntimeError::new(format(format_args!(
65                            "'{}' type function errored at runtime: raised an error of type {}",
66                            type_function_name, err_type
67                        )))),
68                    ),
69                )
70            }
71        }
72    }
73}