Compare commits

..

4 Commits

15 changed files with 111 additions and 132 deletions

24
Cargo.lock generated
View File

@ -534,6 +534,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "displaydoc"
version = "0.2.5"
@ -1028,7 +1034,6 @@ dependencies = [
"camino",
"derive_more",
"luaffi",
"luaify",
"luajit",
"sysexits",
"thiserror",
@ -1139,6 +1144,7 @@ dependencies = [
name = "luaify"
version = "0.0.1"
dependencies = [
"pretty_assertions",
"proc-macro2",
"quote",
"syn",
@ -1411,6 +1417,16 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "prettyplease"
version = "0.2.35"
@ -2347,6 +2363,12 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yoke"
version = "0.8.0"

View File

@ -16,7 +16,3 @@ sysexits = "0.9.0"
thiserror = "2.0.12"
tokio = { version = "1.45.1", features = ["rt", "time", "fs", "net", "process", "signal", "tracing"] }
tracing = "0.1.41"
[dev-dependencies]
luaify = { path = "../luaify" }
tokio = { version = "1.45.1", features = ["full"] }

View File

@ -1,5 +0,0 @@
local task = require("lb:task")
function spawn(f, ...)
return task:spawn(f, ...)
end

View File

@ -1,4 +1,3 @@
use crate::{chan::lb_chanlib, fs::lb_fslib, net::lb_netlib, task::lb_tasklib};
use derive_more::{Deref, DerefMut};
use luaffi::{Registry, Type};
use luajit::{Chunk, State};
@ -15,15 +14,13 @@ pub struct Builder {
impl Builder {
pub fn new() -> Self {
let mut registry = Registry::new();
Self {
registry: Registry::new(),
}
}
registry
.preload::<lb_tasklib>("lb:task")
.preload::<lb_chanlib>("lb:channel")
.preload::<lb_fslib>("lb:fs")
.preload::<lb_netlib>("lb:net");
Self { registry }
pub fn registry(&self) -> &Registry {
&self.registry
}
pub fn module<T: Type>(&mut self, name: impl Display) -> &mut Self {
@ -31,18 +28,11 @@ impl Builder {
self
}
pub fn registry(&self) -> &Registry {
&self.registry
}
pub fn build(&self) -> luajit::Result<Runtime> {
Ok(Runtime {
state: {
let mut s = State::new()?;
let mut chunk = Chunk::new(self.registry.done());
chunk.extend(include_bytes!("./runtime.lua"));
// println!("{chunk}");
s.eval(chunk.path("[luby]"), 0, 0)?;
s.eval(Chunk::new(self.registry.build()).path("[luby]"), 0, 0)?;
s
},
tasks: LocalSet::new(),
@ -73,6 +63,9 @@ impl Runtime {
}
pub fn spawn<T: 'static>(f: impl AsyncFnOnce(&mut State) -> T + 'static) -> JoinHandle<T> {
// SAFETY: `new_thread` must be called inside `spawn_local` because this free-standing spawn
// function may be called via ffi from lua, and it is not safe to access the lua state within
// ffi calls.
spawn_local(async move { f(&mut STATE.with(|s| s.new_thread())).await })
}

View File

@ -1,32 +0,0 @@
use lb::runtime;
use luaify::luaify;
use luajit::{Chunk, LoadMode};
use tokio::test;
async fn run_lua(s: &'static str) {
let rt = runtime::Builder::new().build().unwrap();
let task = rt.spawn(async move |state| {
println!("executing test chunk: {s}");
state
.load(Chunk::new(s).mode(LoadMode::TEXT))
.unwrap_or_else(|err| panic!("{err}"));
state
.call_async(0, 0)
.await
.unwrap_or_else(|err| panic!("{err}"));
});
rt.await;
task.await.unwrap_or_else(|err| panic!("{err}"));
}
#[test]
async fn ipaddr() {
run_lua(luaify!({
let net = require("lb:net");
print(net.ipaddr("127.0.0.1"));
}))
.await
}

View File

@ -1,35 +0,0 @@
use lb::runtime;
use luaify::luaify;
use luajit::{Chunk, LoadMode};
use tokio::test;
async fn run_lua(s: &'static str) {
let rt = runtime::Builder::new().build().unwrap();
let task = rt.spawn(async move |state| {
println!("executing test chunk: {s}");
state
.load(Chunk::new(s).mode(LoadMode::TEXT))
.unwrap_or_else(|err| panic!("{err}"));
state
.call_async(0, 0)
.await
.unwrap_or_else(|err| panic!("{err}"));
});
rt.await;
task.await.unwrap_or_else(|err| panic!("{err}"));
}
#[test]
async fn task_test() {
run_lua(luaify!({
let thing = spawn(|| {
print("spawn callback!!!!!!!!!!!!!");
});
print("thing is", thing);
//
}))
.await
}

View File

@ -171,7 +171,7 @@ impl Registry {
self
}
pub fn done(&self) -> String {
pub fn build(&self) -> String {
self.to_string()
}
}

View File

@ -14,3 +14,6 @@ proc-macro = true
proc-macro2 = "1.0.95"
quote = "1.0.40"
syn = { version = "2.0.103", features = ["full", "visit-mut"] }
[dev-dependencies]
pretty_assertions = "1.4.1"

View File

@ -14,6 +14,12 @@ pub fn generate(expr: &Expr) -> Result<TokenStream> {
Ok(f.done())
}
pub fn generate_chunk(block: &Block) -> Result<TokenStream> {
let mut f = Formatter::default();
generate_block(&mut f, &block, Context::stmt(false))?;
Ok(f.done())
}
#[derive(Default)]
struct Formatter {
buf: String,

View File

@ -1,4 +1,7 @@
use crate::{generate::generate, transform::transform};
use crate::{
generate::{generate, generate_chunk},
transform::{transform, transform_chunk},
};
use proc_macro::TokenStream as TokenStream1;
use quote::ToTokens;
use syn::parse_macro_input;
@ -16,3 +19,13 @@ pub fn luaify(input: TokenStream1) -> TokenStream1 {
}
.into()
}
#[proc_macro]
pub fn luaify_chunk(input: TokenStream1) -> TokenStream1 {
let mut block = parse_macro_input!(input);
match transform_chunk(&mut block).and_then(|()| generate_chunk(&block)) {
Ok(s) => s,
Err(err) => err.into_compile_error().into_token_stream(),
}
.into()
}

View File

@ -9,6 +9,12 @@ pub fn transform(expr: &mut Expr) -> Result<()> {
visitor.result
}
pub fn transform_chunk(block: &mut Block) -> Result<()> {
let mut visitor = Visitor::new();
visitor.visit_block_mut(block);
visitor.result
}
#[derive(Debug)]
struct Visitor {
result: Result<()>,

View File

@ -1,4 +1,5 @@
use luaify::luaify;
use luaify::{luaify, luaify_chunk};
use pretty_assertions::assert_eq;
#[test]
fn raw_ident() {
@ -402,3 +403,19 @@ fn length() {
r#"local a,b,c=#a,#b,#c;"#
);
}
#[test]
fn chunk() {
assert_eq!(
luaify_chunk!({
if a == b {
c()
} else if b == c {
a()
} else {
d()
}
}),
"if a==b then c();elseif b==c then a();else d();end;"
);
}

View File

@ -1 +1,14 @@
pub use lb::*;
pub use lb::chan;
pub use lb::fs;
pub use lb::net;
pub use lb::task;
#[doc(hidden)]
pub fn load_modules(runtime: &mut lb::runtime::Builder) {
// core modules
runtime
.module::<task::lb_tasklib>("lb:task")
.module::<chan::lb_chanlib>("lb:channel")
.module::<fs::lb_fslib>("lb:fs")
.module::<net::lb_netlib>("lb:net");
}

View File

@ -121,13 +121,6 @@ impl Args {
}
}
fn exit_err<T, E: Display>(code: ExitCode) -> impl FnOnce(E) -> T {
move |err| {
eprintln!("{}", err.red().bold());
code.exit()
}
}
fn main() {
panic::set_hook(Box::new(panic_cb));
@ -160,6 +153,13 @@ fn print_version() {
);
}
fn unwrap_exit<T, E: Display>(code: ExitCode) -> impl FnOnce(E) -> T {
move |err| {
eprintln!("{}", err.red().bold());
code.exit()
}
}
fn init_logger(args: &Args) {
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{Layer, util::*};
@ -202,17 +202,18 @@ fn init_tokio(args: &Args) -> tokio::runtime::Runtime {
.thread_name("luby")
.max_blocking_threads(args.blocking_threads.get())
.build()
.unwrap_or_else(exit_err(ExitCode::OsErr))
.unwrap_or_else(unwrap_exit(ExitCode::OsErr))
}
fn init_lua(args: &Args) -> lb::runtime::Runtime {
let rt = lb::runtime::Builder::new();
let mut rt = lb::runtime::Builder::new();
luby::load_modules(&mut rt);
if args.dump.iter().find(|s| *s == "cdef").is_some() {
print!("{}", rt.registry());
}
let mut rt = rt.build().unwrap_or_else(exit_err(ExitCode::Software));
let mut rt = rt.build().unwrap();
for arg in args.jit.iter() {
let mut s = rt.guard();
@ -235,7 +236,7 @@ fn init_lua(args: &Args) -> lb::runtime::Runtime {
}
}
}
.unwrap_or_else(exit_err(ExitCode::Usage));
.unwrap_or_else(unwrap_exit(ExitCode::Usage));
}
rt
@ -243,9 +244,9 @@ fn init_lua(args: &Args) -> lb::runtime::Runtime {
fn parse_jitlib_cmd(s: &str) -> Option<(&str, &str)> {
match s {
"p" => Some(("p", "Flspv10")),
"v" => Some(("v", "-")),
"dump" => Some(("dump", "tirs")),
"p" => Some(("p", "Flspv10")), // default -jp flags
"v" => Some(("v", "-")), // default -jv flags
"dump" => Some(("dump", "tirs")), // default -jdump flags
_ => s.split_once('='),
}
}
@ -262,7 +263,7 @@ async fn main_async(args: Args, state: &mut luajit::State) {
};
s.load(&luajit::Chunk::new(chunk).path(path))
.unwrap_or_else(exit_err(ExitCode::NoInput));
.unwrap_or_else(unwrap_exit(ExitCode::NoInput));
if let Err(err) = s.call_async(0, 0).await {
match err.trace() {

View File

@ -1,19 +0,0 @@
local fs = require("lb:fs")
-- do
-- local start = os.clock()
-- for i = 1, 50000 do
-- fs:read("crates/luaffi_impl/src/metatype.rs")
-- end
-- local finish = os.clock()
-- print("finish in " .. (finish - start))
-- end
do
local start = os.clock()
for i = 1, 30000 do
fs:read_sync("bacon.toml")
end
local finish = os.clock()
print("finish in " .. (finish - start))
end