Clean slate

This commit is contained in:
Filip Tibell 2023-08-16 15:30:46 -05:00
parent d5400f370f
commit c80e504283
55 changed files with 213 additions and 83 deletions

View file

@ -5,8 +5,6 @@ use std::{
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::lua::stdio::formatting::pretty_format_luau_error;
/** /**
An opaque error type for formatted lua errors. An opaque error type for formatted lua errors.
*/ */
@ -66,11 +64,7 @@ impl From<LuaError> for LuneError {
impl Display for LuneError { impl Display for LuneError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!( write!(f, "{}", self.error) // TODO: Pretty formatting
f,
"{}",
pretty_format_luau_error(&self.error, !self.disable_colors)
)
} }
} }

View file

@ -1,12 +1,6 @@
use std::process::ExitCode; use std::process::ExitCode;
use lua::task::{TaskScheduler, TaskSchedulerResumeExt, TaskSchedulerScheduleExt};
use mlua::prelude::*; use mlua::prelude::*;
use tokio::task::LocalSet;
pub mod builtins;
pub mod importer;
pub mod lua;
mod error; mod error;
@ -37,17 +31,7 @@ impl Lune {
} }
/** /**
Runs a Lune script. Runs a Lune script inside of a new Luau VM.
This will create a new sandboxed Luau environment with the configured
globals and arguments, running inside of a [`tokio::task::LocalSet`].
Some Lune globals may spawn separate tokio tasks on other threads, but the Luau
environment itself is guaranteed to run on a single thread in the local set.
Note that this will create a static Lua instance and task scheduler that will
both live for the remainer of the program, and that this leaks memory using
[`Box::leak`] that will then get deallocated when the program exits.
*/ */
pub async fn run( pub async fn run(
&self, &self,
@ -61,47 +45,9 @@ impl Lune {
async fn run_inner( async fn run_inner(
&self, &self,
script_name: impl AsRef<str>, _script_name: impl AsRef<str>,
script_contents: impl AsRef<[u8]>, _script_contents: impl AsRef<[u8]>,
) -> Result<ExitCode, LuaError> { ) -> LuaResult<ExitCode> {
// Create our special lune-flavored Lua object with extra registry values Ok(ExitCode::SUCCESS)
let lua = lua::create_lune_lua()?.into_static();
// Create our task scheduler and all globals
// NOTE: Some globals require the task scheduler to exist on startup
let sched = TaskScheduler::new(lua)?.into_static();
lua.set_app_data(sched);
importer::create(lua, self.args.clone())?;
// Create the main thread and schedule it
let main_chunk = lua
.load(script_contents.as_ref())
.set_name(script_name.as_ref())
.into_function()?;
let main_thread = lua.create_thread(main_chunk)?;
let main_thread_args = LuaValue::Nil.into_lua_multi(lua)?;
sched.schedule_blocking(main_thread, main_thread_args)?;
// Keep running the scheduler until there are either no tasks
// left to run, or until a task requests to exit the process
let exit_code = LocalSet::new()
.run_until(async move {
let mut got_error = false;
loop {
let result = sched.resume_queue().await;
if let Some(err) = result.get_lua_error() {
eprintln!("{}", LuneError::from(err));
got_error = true;
}
if result.is_done() {
if let Some(exit_code) = result.get_exit_code() {
break exit_code;
} else if got_error {
break ExitCode::FAILURE;
} else {
break ExitCode::SUCCESS;
}
}
}
})
.await;
Ok(exit_code)
} }
} }

View file

@ -4,7 +4,7 @@ use std::path::{PathBuf, MAIN_SEPARATOR};
use mlua::prelude::*; use mlua::prelude::*;
use tokio::fs; use tokio::fs;
use crate::lune::lua::{ use crate::lune_temp::lua::{
fs::{copy, FsMetadata, FsWriteOptions}, fs::{copy, FsMetadata, FsWriteOptions},
table::TableBuilder, table::TableBuilder,
}; };

View file

@ -1,6 +1,6 @@
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::lua::{ use crate::lune_temp::lua::{
luau::{LuauCompileOptions, LuauLoadOptions}, luau::{LuauCompileOptions, LuauLoadOptions},
table::TableBuilder, table::TableBuilder,
}; };

View file

@ -9,7 +9,7 @@ use hyper::{
}; };
use tokio::{sync::mpsc, task}; use tokio::{sync::mpsc, task};
use crate::lune::lua::{ use crate::lune_temp::lua::{
net::{ net::{
NetClient, NetClientBuilder, NetLocalExec, NetService, NetWebSocket, RequestConfig, NetClient, NetClientBuilder, NetLocalExec, NetService, NetWebSocket, RequestConfig,
ServeConfig, ServeConfig,

View file

@ -11,7 +11,7 @@ use mlua::prelude::*;
use os_str_bytes::RawOsString; use os_str_bytes::RawOsString;
use tokio::process::Command; use tokio::process::Command;
use crate::lune::lua::{ use crate::lune_temp::lua::{
process::pipe_and_inherit_child_process_stdio, table::TableBuilder, task::TaskScheduler, process::pipe_and_inherit_child_process_stdio, table::TableBuilder, task::TaskScheduler,
}; };

View file

@ -10,7 +10,7 @@ use crate::roblox::{
use tokio::task; use tokio::task;
use crate::lune::lua::table::TableBuilder; use crate::lune_temp::lua::table::TableBuilder;
static REFLECTION_DATABASE: OnceCell<ReflectionDatabase> = OnceCell::new(); static REFLECTION_DATABASE: OnceCell<ReflectionDatabase> = OnceCell::new();

View file

@ -1,6 +1,6 @@
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::lua::{ use crate::lune_temp::lua::{
serde::{ serde::{
compress, decompress, CompressDecompressFormat, EncodeDecodeConfig, EncodeDecodeFormat, compress, decompress, CompressDecompressFormat, EncodeDecodeConfig, EncodeDecodeFormat,
}, },

View file

@ -5,7 +5,7 @@ use tokio::{
task, task,
}; };
use crate::lune::lua::{ use crate::lune_temp::lua::{
stdio::{ stdio::{
formatting::{ formatting::{
format_style, pretty_format_multi_value, style_from_color_str, style_from_style_str, format_style, pretty_format_multi_value, style_from_color_str, style_from_style_str,

View file

@ -1,6 +1,6 @@
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::lua::{ use crate::lune_temp::lua::{
async_ext::LuaAsyncExt, async_ext::LuaAsyncExt,
table::TableBuilder, table::TableBuilder,
task::{ task::{

View file

@ -4,7 +4,7 @@ use std::io::{self, Write as _};
#[cfg(feature = "roblox")] #[cfg(feature = "roblox")]
use crate::roblox::datatypes::extension::RobloxUserdataTypenameExt; use crate::roblox::datatypes::extension::RobloxUserdataTypenameExt;
use crate::lune::lua::{ use crate::lune_temp::lua::{
stdio::formatting::{format_label, pretty_format_multi_value}, stdio::formatting::{format_label, pretty_format_multi_value},
task::TaskReference, task::TaskReference,
}; };

83
src/old/error.rs Normal file
View file

@ -0,0 +1,83 @@
use std::{
error::Error,
fmt::{Debug, Display, Formatter, Result as FmtResult},
};
use mlua::prelude::*;
use crate::lune_temp::lua::stdio::formatting::pretty_format_luau_error;
/**
An opaque error type for formatted lua errors.
*/
#[derive(Debug, Clone)]
pub struct LuneError {
error: LuaError,
disable_colors: bool,
}
impl LuneError {
/**
Enables colorization of the error message when formatted using the [`Display`] trait.
Colorization is enabled by default.
*/
#[doc(hidden)]
pub fn enable_colors(mut self) -> Self {
self.disable_colors = false;
self
}
/**
Disables colorization of the error message when formatted using the [`Display`] trait.
Colorization is enabled by default.
*/
#[doc(hidden)]
pub fn disable_colors(mut self) -> Self {
self.disable_colors = true;
self
}
/**
Returns `true` if the error can likely be fixed by appending more input to the source code.
See [`mlua::Error::SyntaxError`] for more information.
*/
pub fn is_incomplete_input(&self) -> bool {
matches!(
self.error,
LuaError::SyntaxError {
incomplete_input: true,
..
}
)
}
}
impl From<LuaError> for LuneError {
fn from(value: LuaError) -> Self {
Self {
error: value,
disable_colors: false,
}
}
}
impl Display for LuneError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"{}",
pretty_format_luau_error(&self.error, !self.disable_colors)
)
}
}
impl Error for LuneError {
// TODO: Comment this out when we are ready to also re-export
// `mlua` as part of our public library interface in Lune
// fn cause(&self) -> Option<&dyn Error> {
// Some(&self.error)
// }
}

View file

@ -3,7 +3,7 @@ use mlua::prelude::*;
mod require; mod require;
mod require_waker; mod require_waker;
use crate::lune::builtins::{self, top_level}; use crate::lune_temp::builtins::{self, top_level};
pub fn create(lua: &'static Lua, args: Vec<String>) -> LuaResult<()> { pub fn create(lua: &'static Lua, args: Vec<String>) -> LuaResult<()> {
// Create all builtins // Create all builtins

View file

@ -10,7 +10,7 @@ use mlua::prelude::*;
use tokio::fs; use tokio::fs;
use tokio::sync::Mutex as AsyncMutex; use tokio::sync::Mutex as AsyncMutex;
use crate::lune::lua::{ use crate::lune_temp::lua::{
table::TableBuilder, table::TableBuilder,
task::{TaskScheduler, TaskSchedulerScheduleExt}, task::{TaskScheduler, TaskSchedulerScheduleExt},
}; };

View file

@ -2,7 +2,7 @@ use async_trait::async_trait;
use futures_util::Future; use futures_util::Future;
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::{lua::table::TableBuilder, lua::task::TaskScheduler}; use crate::lune_temp::{lua::table::TableBuilder, lua::task::TaskScheduler};
use super::task::TaskSchedulerAsyncExt; use super::task::TaskSchedulerAsyncExt;

View file

@ -12,7 +12,7 @@ use hyper::{Body, Request, Response};
use hyper_tungstenite::{is_upgrade_request as is_ws_upgrade_request, upgrade as ws_upgrade}; use hyper_tungstenite::{is_upgrade_request as is_ws_upgrade_request, upgrade as ws_upgrade};
use tokio::task; use tokio::task;
use crate::lune::{ use crate::lune_temp::{
lua::table::TableBuilder, lua::table::TableBuilder,
lua::task::{TaskScheduler, TaskSchedulerAsyncExt, TaskSchedulerScheduleExt}, lua::task::{TaskScheduler, TaskSchedulerAsyncExt, TaskSchedulerScheduleExt},
}; };

View file

@ -22,7 +22,7 @@ use hyper_tungstenite::{
}; };
use tokio_tungstenite::MaybeTlsStream; use tokio_tungstenite::MaybeTlsStream;
use crate::lune::lua::table::TableBuilder; use crate::lune_temp::lua::table::TableBuilder;
const WEB_SOCKET_IMPL_LUA: &str = r#" const WEB_SOCKET_IMPL_LUA: &str = r#"
return freeze(setmetatable({ return freeze(setmetatable({

View file

@ -4,7 +4,7 @@ use console::{colors_enabled, set_colors_enabled, style, Style};
use mlua::prelude::*; use mlua::prelude::*;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::lune::lua::task::TaskReference; use crate::lune_temp::lua::task::TaskReference;
const MAX_FORMAT_DEPTH: usize = 4; const MAX_FORMAT_DEPTH: usize = 4;

View file

@ -2,7 +2,7 @@ use std::future::Future;
use mlua::prelude::*; use mlua::prelude::*;
use crate::lune::lua::async_ext::LuaAsyncExt; use crate::lune_temp::lua::async_ext::LuaAsyncExt;
pub struct TableBuilder { pub struct TableBuilder {
lua: &'static Lua, lua: &'static Lua,

View file

@ -6,7 +6,7 @@ use futures_util::Future;
use mlua::prelude::*; use mlua::prelude::*;
use tokio::time::{sleep, Instant}; use tokio::time::{sleep, Instant};
use crate::lune::lua::task::TaskKind; use crate::lune_temp::lua::task::TaskKind;
use super::super::{ use super::super::{
scheduler::TaskReference, scheduler::TaskScheduler, scheduler_handle::TaskSchedulerAsyncHandle, scheduler::TaskReference, scheduler::TaskScheduler, scheduler_handle::TaskSchedulerAsyncHandle,

107
src/old/mod.rs Normal file
View file

@ -0,0 +1,107 @@
use std::process::ExitCode;
use lua::task::{TaskScheduler, TaskSchedulerResumeExt, TaskSchedulerScheduleExt};
use mlua::prelude::*;
use tokio::task::LocalSet;
pub mod builtins;
pub mod importer;
pub mod lua;
mod error;
pub use error::LuneError;
#[derive(Clone, Debug, Default)]
pub struct Lune {
args: Vec<String>,
}
impl Lune {
/**
Creates a new Lune script runner.
*/
pub fn new() -> Self {
Self::default()
}
/**
Arguments to give in `process.args` for a Lune script.
*/
pub fn with_args<V>(mut self, args: V) -> Self
where
V: Into<Vec<String>>,
{
self.args = args.into();
self
}
/**
Runs a Lune script.
This will create a new sandboxed Luau environment with the configured
globals and arguments, running inside of a [`tokio::task::LocalSet`].
Some Lune globals may spawn separate tokio tasks on other threads, but the Luau
environment itself is guaranteed to run on a single thread in the local set.
Note that this will create a static Lua instance and task scheduler that will
both live for the remainer of the program, and that this leaks memory using
[`Box::leak`] that will then get deallocated when the program exits.
*/
pub async fn run(
&self,
script_name: impl AsRef<str>,
script_contents: impl AsRef<[u8]>,
) -> Result<ExitCode, LuneError> {
self.run_inner(script_name, script_contents)
.await
.map_err(LuneError::from)
}
async fn run_inner(
&self,
script_name: impl AsRef<str>,
script_contents: impl AsRef<[u8]>,
) -> Result<ExitCode, LuaError> {
// Create our special lune-flavored Lua object with extra registry values
let lua = lua::create_lune_lua()?.into_static();
// Create our task scheduler and all globals
// NOTE: Some globals require the task scheduler to exist on startup
let sched = TaskScheduler::new(lua)?.into_static();
lua.set_app_data(sched);
importer::create(lua, self.args.clone())?;
// Create the main thread and schedule it
let main_chunk = lua
.load(script_contents.as_ref())
.set_name(script_name.as_ref())
.into_function()?;
let main_thread = lua.create_thread(main_chunk)?;
let main_thread_args = LuaValue::Nil.into_lua_multi(lua)?;
sched.schedule_blocking(main_thread, main_thread_args)?;
// Keep running the scheduler until there are either no tasks
// left to run, or until a task requests to exit the process
let exit_code = LocalSet::new()
.run_until(async move {
let mut got_error = false;
loop {
let result = sched.resume_queue().await;
if let Some(err) = result.get_lua_error() {
eprintln!("{}", LuneError::from(err));
got_error = true;
}
if result.is_done() {
if let Some(exit_code) = result.get_exit_code() {
break exit_code;
} else if got_error {
break ExitCode::FAILURE;
} else {
break ExitCode::SUCCESS;
}
}
}
})
.await;
Ok(exit_code)
}
}