luaur_repl_cli/functions/
load.rs1use alloc::string::String;
2use core::ffi::{c_char, c_void, CStr};
3
4use luaur_ast::records::parse_options::ParseOptions;
5use luaur_bytecode::records::bytecode_encoder::BytecodeEncoder;
6use luaur_cli_lib::functions::read_file::read_file;
7use luaur_code_gen::functions::luau_codegen_compile::luau_codegen_compile;
8use luaur_compiler::functions::compile::compile;
9use luaur_vm::enums::lua_status::lua_Status;
10use luaur_vm::functions::lua_gettop::lua_gettop;
11use luaur_vm::functions::lua_isstring::lua_isstring;
12use luaur_vm::functions::lua_l_sandboxthread::lua_l_sandboxthread;
13use luaur_vm::functions::lua_mainthread::lua_mainthread;
14use luaur_vm::functions::lua_newthread::lua_newthread;
15use luaur_vm::functions::lua_remove::lua_remove;
16use luaur_vm::functions::lua_resume::lua_resume;
17use luaur_vm::functions::lua_xmove::lua_xmove;
18use luaur_vm::functions::luau_load::luau_load;
19use luaur_vm::macros::lua_l_error::luaL_error;
20use luaur_vm::macros::lua_tostring::lua_tostring;
21use luaur_vm::type_aliases::lua_state::lua_State;
22
23use crate::records::repl_requirer::ReplRequirer;
24
25pub unsafe fn load(
26 l: *mut lua_State,
27 ctx: *mut c_void,
28 _path: *const c_char,
29 chunkname: *const c_char,
30 loadname: *const c_char,
31) -> i32 {
32 let req = &*(ctx as *const ReplRequirer);
33
34 let gl = lua_mainthread(l);
37 let ml = lua_newthread(gl);
38 lua_xmove(gl, l, 1);
39
40 lua_l_sandboxthread(ml);
42
43 let loadname_str = CStr::from_ptr(loadname).to_string_lossy();
44
45 let contents = read_file(&loadname_str);
46 let had_contents = contents.is_some();
47 let mut status: i32 = lua_Status::LUA_OK as i32;
48
49 if let Some(ref source) = contents {
50 struct NoopEncoder;
52 impl BytecodeEncoder for NoopEncoder {
53 fn encode(&mut self, _data: &mut [u32]) {}
54 }
55 let options = (req.copts.unwrap())();
56 let parse_options = ParseOptions::default();
57 let mut encoder = NoopEncoder;
58 let source_owned: String = source.clone();
59 let bytecode = compile(
60 &source_owned,
61 &options,
62 &parse_options,
63 &mut encoder as *mut dyn BytecodeEncoder,
64 );
65 status = luau_load(
66 ml,
67 chunkname,
68 bytecode.as_ptr() as *const c_char,
69 bytecode.len(),
70 0,
71 );
72 }
73
74 if !had_contents {
75 luaL_error!(l, "could not read file '{}'", loadname_str);
76 }
77
78 if status == 0 {
79 if (req.codegenEnabled.unwrap())() {
80 luau_codegen_compile(ml, -1);
84 }
85
86 if (req.coverageActive.unwrap())() {
87 (req.coverageTrack.unwrap())(ml as *mut c_void, -1);
88 }
89
90 if (req.countersActive.unwrap())() {
91 (req.countersTrack.unwrap())(ml as *mut c_void, -1);
92 }
93
94 let status = lua_resume(ml, l, 0);
95
96 if status == 0 {
97 if lua_gettop(ml) != 1 {
98 luaL_error!(l, "module must return a single value");
99 }
100 } else if status == lua_Status::LUA_YIELD as i32 {
101 luaL_error!(l, "module can not yield");
102 } else if lua_isstring(ml, -1) == 0 {
103 luaL_error!(l, "unknown error while running module");
104 } else {
105 let msg = lua_tostring!(ml, -1);
106 let msg = CStr::from_ptr(msg).to_string_lossy();
107 luaL_error!(l, "error while running module: {}", msg);
108 }
109 }
110
111 lua_xmove(ml, l, 1);
113
114 lua_remove(l, -2);
116
117 1
119}