luaur_repl_cli/functions/
run_file.rs1use alloc::string::String;
2use core::ffi::{c_char, CStr};
3
4use luaur_ast::records::parse_options::ParseOptions;
5use luaur_bytecode::records::bytecode_encoder::BytecodeEncoder;
6use luaur_cli_lib::functions::normalize_path::normalize_path;
7use luaur_cli_lib::functions::read_file::read_file;
8use luaur_code_gen::functions::luau_codegen_compile::luau_codegen_compile;
9use luaur_compiler::functions::compile::compile;
10use luaur_vm::enums::lua_status::lua_Status;
11use luaur_vm::functions::lua_debugtrace::lua_debugtrace;
12use luaur_vm::functions::lua_l_sandboxthread::lua_l_sandboxthread;
13use luaur_vm::functions::lua_newthread::lua_newthread;
14use luaur_vm::functions::lua_resume::lua_resume;
15use luaur_vm::functions::luau_load::luau_load;
16use luaur_vm::macros::lua_pop::lua_pop;
17use luaur_vm::macros::lua_tostring::lua_tostring;
18use luaur_vm::type_aliases::lua_state::lua_State;
19
20use crate::functions::copts::copts;
21use crate::functions::counters_active::counters_active;
22use crate::functions::counters_track::counters_track;
23use crate::functions::coverage_active::coverage_active;
24use crate::functions::coverage_track::coverage_track;
25use crate::functions::repl_main::{program_argc, program_argv, repl_codegen_enabled};
26use crate::functions::run_repl_impl::run_repl_impl;
27use crate::functions::setup_arguments::setup_arguments;
28
29pub unsafe fn run_file(name: &str, gl: *mut lua_State, repl: bool) -> bool {
31 let source = read_file(name);
32 let source = match source {
33 Some(s) => s,
34 None => {
35 eprintln!("Error opening {}", name);
36 return false;
37 }
38 };
39
40 let l = lua_newthread(gl);
42
43 lua_l_sandboxthread(l);
45
46 let chunkname = String::from("@") + &normalize_path(name) + "\0";
47
48 struct NoopEncoder;
49 impl BytecodeEncoder for NoopEncoder {
50 fn encode(&mut self, _data: &mut [u32]) {}
51 }
52 let options = copts();
53 let parse_options = ParseOptions::default();
54 let mut encoder = NoopEncoder;
55 let bytecode = compile(
56 &source,
57 &options,
58 &parse_options,
59 &mut encoder as *mut dyn BytecodeEncoder,
60 );
61
62 let status: i32 = if luau_load(
63 l,
64 chunkname.as_ptr() as *const c_char,
65 bytecode.as_ptr() as *const c_char,
66 bytecode.len(),
67 0,
68 ) == 0
69 {
70 if repl_codegen_enabled() {
71 luau_codegen_compile(l, -1);
74 }
75
76 if coverage_active() {
77 coverage_track(l, -1);
78 }
79
80 if counters_active() {
81 counters_track(l, -1);
82 }
83
84 setup_arguments(l, program_argc(), program_argv());
85 lua_resume(l, core::ptr::null_mut(), program_argc())
86 } else {
87 lua_Status::LUA_ERRSYNTAX as i32
88 };
89
90 if status != 0 {
91 let mut error: String;
92
93 if status == lua_Status::LUA_YIELD as i32 {
94 error = "thread yielded unexpectedly".into();
95 } else {
96 let str_ptr = lua_tostring!(l, -1);
97 if !str_ptr.is_null() {
98 error = CStr::from_ptr(str_ptr).to_string_lossy().into_owned();
99 } else {
100 error = String::new();
101 }
102 }
103
104 error.push_str("\nstacktrace:\n");
105 let trace = lua_debugtrace(l);
106 if !trace.is_null() {
107 error.push_str(&CStr::from_ptr(trace).to_string_lossy());
108 }
109
110 eprint!("{}", error);
111 }
112
113 if repl {
114 run_repl_impl(l);
115 }
116 lua_pop(gl, 1);
117 status == 0
118}