From 308613d5fc48cfec6a40ea5b1b7632ab753f45f0 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 8 Mar 2023 21:27:29 +0100 Subject: [PATCH] feat(dtmt): Improve error messages when compiling Lua Fixes #58. --- crates/dtmm/src/controller/game.rs | 5 +---- crates/dtmt/src/cmd/build.rs | 27 +++++++++---------------- lib/sdk/src/bundle/file.rs | 8 ++------ lib/sdk/src/filetype/lua.rs | 32 +++++++++++++++++++++++------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/crates/dtmm/src/controller/game.rs b/crates/dtmm/src/controller/game.rs index 62502c4..9a95be6 100644 --- a/crates/dtmm/src/controller/game.rs +++ b/crates/dtmm/src/controller/game.rs @@ -1,4 +1,3 @@ -use std::ffi::CString; use std::io::{Cursor, ErrorKind}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -216,7 +215,6 @@ async fn build_bundles(state: Arc) -> Result> { let _enter = span.enter(); let lua = build_mod_data_lua(state.clone()); - let lua = CString::new(lua).wrap_err("Failed to build CString from mod data Lua string")?; let file = lua::compile(MOD_DATA_SCRIPT, &lua).wrap_err("Failed to compile mod data Lua file")?; @@ -437,9 +435,8 @@ async fn patch_boot_bundle(state: Arc) -> Result> { let _enter = span.enter(); let lua = include_str!("../../assets/mod_main.lua"); - let lua = CString::new(lua).wrap_err("Failed to build CString from mod main Lua string")?; let file = - lua::compile(MOD_BOOT_SCRIPT, &lua).wrap_err("Failed to compile mod main Lua file")?; + lua::compile(MOD_BOOT_SCRIPT, lua).wrap_err("Failed to compile mod main Lua file")?; boot_bundle.add_file(file); } diff --git a/crates/dtmt/src/cmd/build.rs b/crates/dtmt/src/cmd/build.rs index e47d1ea..523dccd 100644 --- a/crates/dtmt/src/cmd/build.rs +++ b/crates/dtmt/src/cmd/build.rs @@ -151,17 +151,6 @@ where results.into_iter().collect() } -#[tracing::instrument(skip_all, fields(files = files.len()))] -fn compile_bundle(name: String, files: Vec) -> Result { - let mut bundle = Bundle::new(name); - - for file in files { - bundle.add_file(file); - } - - Ok(bundle) -} - #[tracing::instrument] async fn build_package(package: P1, root: P2) -> Result where @@ -182,18 +171,20 @@ where .await .wrap_err_with(|| format!("Invalid package file {}", &pkg_name))?; - compile_package_files(&pkg, root) - .await - .wrap_err("Failed to compile package") - .and_then(|files| compile_bundle(pkg_name, files)) - .wrap_err("Failed to build bundle") + let files = compile_package_files(&pkg, root).await?; + let mut bundle = Bundle::new(pkg_name); + for file in files { + bundle.add_file(file); + } + + Ok(bundle) } fn normalize_file_path>(path: P) -> Result { let path = path.as_ref(); if path.is_absolute() || path.has_root() { - let err = eyre::eyre!("path is absolute: {}", path.display()); + let err = eyre::eyre!("Path is absolute: {}", path.display()); return Err(err).with_suggestion(|| "Specify a relative file path.".to_string()); } @@ -302,7 +293,7 @@ pub(crate) async fn run(_ctx: sdk::Context, matches: &ArgMatches) -> Result<()> let bundle = build_package(path, &cfg.dir).await.wrap_err_with(|| { format!( - "failed to build package {} in {}", + "Failed to build package '{}' at '{}'", path.display(), cfg.dir.display() ) diff --git a/lib/sdk/src/bundle/file.rs b/lib/sdk/src/bundle/file.rs index 9881660..ab59884 100644 --- a/lib/sdk/src/bundle/file.rs +++ b/lib/sdk/src/bundle/file.rs @@ -1,4 +1,3 @@ -use std::ffi::CString; use std::io::{Cursor, Read, Seek, Write}; use std::path::Path; @@ -660,11 +659,8 @@ impl BundleFile { S: AsRef, { match file_type { - BundleFileType::Lua => { - let sjson = - CString::new(sjson.as_ref()).wrap_err("Failed to build CString from SJSON")?; - lua::compile(name, sjson) - } + BundleFileType::Lua => lua::compile(name.clone(), sjson) + .wrap_err_with(|| format!("Failed to compile Lua file '{}'", name)), BundleFileType::Unknown(_) => { eyre::bail!("Unknown file type. Cannot compile from SJSON"); } diff --git a/lib/sdk/src/filetype/lua.rs b/lib/sdk/src/filetype/lua.rs index 720988f..9c53a1c 100644 --- a/lib/sdk/src/filetype/lua.rs +++ b/lib/sdk/src/filetype/lua.rs @@ -25,7 +25,7 @@ where pub fn compile(name: S, code: C) -> Result where S: Into, - C: AsRef, + C: AsRef, { let name = name.into(); let code = code.as_ref(); @@ -34,15 +34,33 @@ where let state = lua::luaL_newstate(); lua::luaL_openlibs(state); - lua::lua_pushstring(state, code.as_ptr() as _); - lua::lua_setglobal(state, b"code\0".as_ptr() as _); - let name = CString::new(name.as_bytes()) .wrap_err_with(|| format!("Cannot convert name into CString: {}", name))?; - lua::lua_pushstring(state, name.as_ptr() as _); - lua::lua_setglobal(state, b"name\0".as_ptr() as _); + match lua::luaL_loadbuffer( + state, + code.as_ptr() as _, + code.len() as _, + name.as_ptr() as _, + ) as u32 + { + lua::LUA_OK => {} + lua::LUA_ERRSYNTAX => { + let err = lua::lua_tostring(state, -1); + let err = CStr::from_ptr(err).to_string_lossy().to_string(); - let run = b"return string.dump(loadstring(code, \"@\" .. name), false)\0"; + lua::lua_close(state); + + eyre::bail!("Invalid syntax: {}", err); + } + lua::LUA_ERRMEM => { + lua::lua_close(state); + eyre::bail!("Failed to allocate sufficient memory to compile LuaJIT bytecode") + } + _ => unreachable!(), + } + lua::lua_setglobal(state, b"fn\0".as_ptr() as _); + + let run = b"return string.dump(fn, false)\0"; match lua::luaL_loadstring(state, run.as_ptr() as _) as u32 { lua::LUA_OK => {} lua::LUA_ERRSYNTAX => { -- 2.45.3