mirror of
https://github.com/lune-org/lune.git
synced 2024-12-14 06:00:42 +00:00
Async require now mostly working
This commit is contained in:
parent
6318176516
commit
0975a6180b
1 changed files with 116 additions and 114 deletions
|
@ -19,18 +19,18 @@ local source = info(1, "s")
|
||||||
if source == '[string "require"]' then
|
if source == '[string "require"]' then
|
||||||
source = info(2, "s")
|
source = info(2, "s")
|
||||||
end
|
end
|
||||||
local absolute, relative = importer:paths(source, ...)
|
local absolute, relative = paths(context, source, ...)
|
||||||
return importer:load(thread(), absolute, relative)
|
return load(context, absolute, relative)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
struct Importer<'lua> {
|
struct RequireContext<'lua> {
|
||||||
builtins: HashMap<String, LuaMultiValue<'lua>>,
|
builtins: HashMap<String, LuaMultiValue<'lua>>,
|
||||||
cached: RefCell<HashMap<String, LuaResult<LuaMultiValue<'lua>>>>,
|
cached: RefCell<HashMap<String, LuaResult<LuaMultiValue<'lua>>>>,
|
||||||
pwd: String,
|
pwd: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> Importer<'lua> {
|
impl<'lua> RequireContext<'lua> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut pwd = current_dir()
|
let mut pwd = current_dir()
|
||||||
.expect("Failed to access current working directory")
|
.expect("Failed to access current working directory")
|
||||||
|
@ -44,8 +44,15 @@ impl<'lua> Importer<'lua> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn paths(&self, require_source: String, require_path: String) -> LuaResult<(String, String)> {
|
impl<'lua> LuaUserData for RequireContext<'lua> {}
|
||||||
|
|
||||||
|
fn paths(
|
||||||
|
context: RequireContext,
|
||||||
|
require_source: String,
|
||||||
|
require_path: String,
|
||||||
|
) -> LuaResult<(String, String)> {
|
||||||
if require_path.starts_with('@') {
|
if require_path.starts_with('@') {
|
||||||
return Ok((require_path.clone(), require_path));
|
return Ok((require_path.clone(), require_path));
|
||||||
}
|
}
|
||||||
|
@ -71,12 +78,16 @@ impl<'lua> Importer<'lua> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let absolute = file_path.to_string_lossy().to_string();
|
let absolute = file_path.to_string_lossy().to_string();
|
||||||
let relative = absolute.trim_start_matches(&self.pwd).to_string();
|
let relative = absolute.trim_start_matches(&context.pwd).to_string();
|
||||||
Ok((absolute, relative))
|
Ok((absolute, relative))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_builtin(&self, module_name: &str) -> LuaResult<LuaMultiValue> {
|
fn load_builtin<'lua>(
|
||||||
match self.builtins.get(module_name) {
|
_lua: &'lua Lua,
|
||||||
|
context: RequireContext<'lua>,
|
||||||
|
module_name: String,
|
||||||
|
) -> LuaResult<LuaMultiValue<'lua>> {
|
||||||
|
match context.builtins.get(&module_name) {
|
||||||
Some(module) => Ok(module.clone()),
|
Some(module) => Ok(module.clone()),
|
||||||
None => Err(LuaError::RuntimeError(format!(
|
None => Err(LuaError::RuntimeError(format!(
|
||||||
"No builtin module exists with the name '{}'",
|
"No builtin module exists with the name '{}'",
|
||||||
|
@ -85,13 +96,13 @@ impl<'lua> Importer<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_file(
|
async fn load_file<'lua>(
|
||||||
&self,
|
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
|
context: RequireContext<'lua>,
|
||||||
absolute_path: String,
|
absolute_path: String,
|
||||||
relative_path: String,
|
relative_path: String,
|
||||||
) -> LuaResult<LuaMultiValue> {
|
) -> LuaResult<LuaMultiValue<'lua>> {
|
||||||
let cached = { self.cached.borrow().get(&absolute_path).cloned() };
|
let cached = { context.cached.borrow().get(&absolute_path).cloned() };
|
||||||
match cached {
|
match cached {
|
||||||
Some(cached) => cached,
|
Some(cached) => cached,
|
||||||
None => {
|
None => {
|
||||||
|
@ -118,60 +129,51 @@ impl<'lua> Importer<'lua> {
|
||||||
sched.set_task_result_sender(task, tx);
|
sched.set_task_result_sender(task, tx);
|
||||||
}
|
}
|
||||||
// Wait for the thread to finish running, cache + return our result
|
// Wait for the thread to finish running, cache + return our result
|
||||||
|
// FIXME: This waits indefinitely for nested requires for some reason
|
||||||
let rets = rx.await.expect("Sender was dropped during require");
|
let rets = rx.await.expect("Sender was dropped during require");
|
||||||
self.cached.borrow_mut().insert(absolute_path, rets.clone());
|
context
|
||||||
|
.cached
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(absolute_path, rets.clone());
|
||||||
rets
|
rets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(
|
async fn load<'lua>(
|
||||||
&self,
|
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
|
context: RequireContext<'lua>,
|
||||||
absolute_path: String,
|
absolute_path: String,
|
||||||
relative_path: String,
|
relative_path: String,
|
||||||
) -> LuaResult<LuaMultiValue> {
|
) -> LuaResult<LuaMultiValue<'lua>> {
|
||||||
if absolute_path == relative_path && absolute_path.starts_with('@') {
|
if absolute_path == relative_path && absolute_path.starts_with('@') {
|
||||||
if let Some(module_name) = absolute_path.strip_prefix("@lune/") {
|
if let Some(module_name) = absolute_path.strip_prefix("@lune/") {
|
||||||
self.load_builtin(module_name)
|
load_builtin(lua, context, module_name.to_string())
|
||||||
} else {
|
} else {
|
||||||
Err(LuaError::RuntimeError(
|
Err(LuaError::RuntimeError(
|
||||||
"Require paths prefixed by '@' are not yet supported".to_string(),
|
"Require paths prefixed by '@' are not yet supported".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.load_file(lua, absolute_path, relative_path).await
|
load_file(lua, context, absolute_path, relative_path).await
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'i> LuaUserData for Importer<'i> {
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
|
||||||
methods.add_method(
|
|
||||||
"paths",
|
|
||||||
|_, this, (require_source, require_path): (String, String)| {
|
|
||||||
this.paths(require_source, require_path)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
methods.add_method(
|
|
||||||
"load",
|
|
||||||
|lua, this, (thread, absolute_path, relative_path): (LuaThread, String, String)| {
|
|
||||||
// TODO: Make this work
|
|
||||||
// this.load(lua, absolute_path, relative_path)
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
|
pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
|
||||||
let require_importer = Importer::new();
|
let require_context = RequireContext::new();
|
||||||
let require_thread: LuaFunction = lua.named_registry_value("co.thread")?;
|
let require_print: LuaFunction = lua.named_registry_value("print")?;
|
||||||
let require_info: LuaFunction = lua.named_registry_value("dbg.info")?;
|
let require_info: LuaFunction = lua.named_registry_value("dbg.info")?;
|
||||||
|
|
||||||
let require_env = TableBuilder::new(lua)?
|
let require_env = TableBuilder::new(lua)?
|
||||||
.with_value("importer", require_importer)?
|
.with_value("context", require_context)?
|
||||||
.with_value("thread", require_thread)?
|
.with_value("print", require_print)?
|
||||||
.with_value("info", require_info)?
|
.with_value("info", require_info)?
|
||||||
|
.with_function("paths", |_, (context, require_source, require_path)| {
|
||||||
|
paths(context, require_source, require_path)
|
||||||
|
})?
|
||||||
|
.with_async_function("load", |lua, (context, require_source, require_path)| {
|
||||||
|
load(lua, context, require_source, require_path)
|
||||||
|
})?
|
||||||
.build_readonly()?;
|
.build_readonly()?;
|
||||||
|
|
||||||
let require_fn_lua = lua
|
let require_fn_lua = lua
|
||||||
|
|
Loading…
Reference in a new issue