Skip to main content

luaur_repl_cli/functions/
create_cli_require_context.rs

1use core::ffi::{c_int, c_void};
2
3use luaur_vm::functions::lua_insert::lua_insert;
4use luaur_vm::functions::lua_newuserdatadtor::lua_newuserdatadtor;
5use luaur_vm::functions::lua_settable::lua_settable;
6use luaur_vm::macros::lua_l_error::luaL_error;
7use luaur_vm::macros::lua_pushlightuserdata::lua_pushlightuserdata;
8use luaur_vm::macros::lua_registryindex::LUA_REGISTRYINDEX;
9use luaur_vm::type_aliases::lua_state::lua_State;
10
11use crate::functions::copts::copts;
12use crate::functions::counters_active::counters_active;
13use crate::functions::counters_track::counters_track;
14use crate::functions::coverage_active::coverage_active;
15use crate::functions::coverage_track::coverage_track;
16use crate::functions::repl_main::repl_codegen_enabled;
17use crate::methods::repl_requirer_repl_requirer::repl_requirer_repl_requirer;
18use crate::records::repl_requirer::ReplRequirer;
19
20// Destructor passed to lua_newuserdatadtor, mirroring the C++ lambda that runs
21// `static_cast<ReplRequirer*>(ptr)->~ReplRequirer()`.
22unsafe extern "C" fn repl_requirer_dtor(ptr: *mut c_void) {
23    core::ptr::drop_in_place(ptr as *mut ReplRequirer);
24}
25
26// `coverageActive` adapter: ReplRequirer expects an `extern "C" fn() -> bool`.
27unsafe extern "C" fn coverage_active_cb() -> bool {
28    coverage_active()
29}
30
31// `codegenEnabled`: the C++ lambda `[]() { return codegen; }`.
32unsafe extern "C" fn codegen_enabled_cb() -> bool {
33    repl_codegen_enabled()
34}
35
36// `countersActive` adapter.
37unsafe extern "C" fn counters_active_cb() -> bool {
38    counters_active()
39}
40
41// `coverageTrack` adapter: ReplRequirer expects `extern "C" fn(*mut c_void, c_int)`.
42unsafe extern "C" fn coverage_track_cb(l: *mut c_void, funcindex: c_int) {
43    coverage_track(l as *mut lua_State, funcindex);
44}
45
46// `countersTrack` adapter.
47unsafe extern "C" fn counters_track_cb(l: *mut c_void, funcindex: c_int) {
48    counters_track(l as *mut lua_State, funcindex);
49}
50
51pub unsafe fn create_cli_require_context(l: *mut lua_State) -> *mut c_void {
52    let ctx = lua_newuserdatadtor(
53        l,
54        core::mem::size_of::<ReplRequirer>(),
55        Some(repl_requirer_dtor),
56    );
57
58    if ctx.is_null() {
59        luaL_error!(l, "unable to allocate ReplRequirer");
60    }
61
62    // placement-construct the ReplRequirer into the userdata buffer
63    core::ptr::write(
64        ctx as *mut ReplRequirer,
65        repl_requirer_repl_requirer(
66            Some(copts as fn() -> luaur_compiler::records::compile_options::CompileOptions),
67            Some(coverage_active_cb),
68            Some(codegen_enabled_cb),
69            Some(coverage_track_cb),
70            Some(counters_active_cb),
71            Some(counters_track_cb),
72        ),
73    );
74
75    // Store ReplRequirer in the registry to keep it alive for the lifetime of
76    // this lua_State. Memory address is used as a key to avoid collisions.
77    lua_pushlightuserdata(l as *mut c_void, ctx);
78    lua_insert(l, -2);
79    lua_settable(l, LUA_REGISTRYINDEX);
80
81    ctx
82}