Working commit
This commit is contained in:
parent
94e1cf2eb0
commit
06d3eebaa1
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "luajit"]
|
[submodule "luajit"]
|
||||||
path = crates/luajit/src
|
path = crates/luajit-sys/src
|
||||||
url = https://github.com/LuaJIT/LuaJIT.git
|
url = https://github.com/LuaJIT/LuaJIT.git
|
||||||
|
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -838,12 +838,19 @@ dependencies = [
|
|||||||
name = "luajit"
|
name = "luajit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen",
|
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"bstr",
|
"bstr",
|
||||||
"cc",
|
|
||||||
"luaffi",
|
"luaffi",
|
||||||
|
"luajit-sys",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "luajit-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bindgen",
|
||||||
|
"cc",
|
||||||
"which",
|
"which",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5,8 +5,13 @@ members = [
|
|||||||
"crates/luaffi_impl",
|
"crates/luaffi_impl",
|
||||||
"crates/luaify",
|
"crates/luaify",
|
||||||
"crates/luajit",
|
"crates/luajit",
|
||||||
|
"crates/luajit-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[profile]
|
||||||
|
dev.panic = "abort"
|
||||||
|
release.panic = "abort"
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "luby"
|
name = "luby"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1,29 +1,28 @@
|
|||||||
use luaffi::{cdef, metatype};
|
use luaffi::{cdef, metatype};
|
||||||
use luajit::State;
|
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use std::{cell::RefCell, fmt, process};
|
use std::{cell::RefCell, fmt, process};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GlobalState(State);
|
pub struct GlobalState(luajit::State);
|
||||||
|
|
||||||
impl GlobalState {
|
impl GlobalState {
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static STATE: RefCell<Option<GlobalState>> = RefCell::new(None);
|
static STATE: RefCell<Option<GlobalState>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(state: State) -> Option<State> {
|
pub fn set(state: luajit::State) -> Option<luajit::State> {
|
||||||
Self::STATE.with_borrow_mut(|s| s.replace(Self(state)).map(|s| s.0))
|
Self::STATE.with_borrow_mut(|s| s.replace(Self(state)).map(|s| s.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_current<T>(f: impl FnOnce(&State) -> T) -> T {
|
pub fn with_current<T>(f: impl FnOnce(&luajit::State) -> T) -> T {
|
||||||
Self::STATE.with_borrow(|s| f(&s.as_ref().expect("lua state not initialised").0))
|
Self::STATE.with_borrow(|s| f(&s.as_ref().expect("lua state not initialised").0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_current_mut<T>(f: impl FnOnce(&mut State) -> T) -> T {
|
pub fn with_current_mut<T>(f: impl FnOnce(&mut luajit::State) -> T) -> T {
|
||||||
Self::STATE.with_borrow_mut(|s| f(&mut s.as_mut().expect("lua state not initialised").0))
|
Self::STATE.with_borrow_mut(|s| f(&mut s.as_mut().expect("lua state not initialised").0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_thread() -> State {
|
pub fn new_thread() -> luajit::State {
|
||||||
Self::with_current(|s| s.new_thread())
|
Self::with_current(|s| s.new_thread())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,11 @@ impl Registry {
|
|||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn preload<T: Type>(&mut self, _name: impl Display) -> &mut Self {
|
||||||
|
self.include::<T>();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn include<T: Type>(&mut self) -> &mut Self {
|
pub fn include<T: Type>(&mut self) -> &mut Self {
|
||||||
self.types
|
self.types
|
||||||
.insert(T::name().to_string())
|
.insert(T::name().to_string())
|
||||||
@ -150,11 +155,6 @@ impl Registry {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preload<T: Type>(&mut self, name: impl Display) -> &mut Self {
|
|
||||||
self.include::<T>();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn done(&self) -> String {
|
pub fn done(&self) -> String {
|
||||||
self.to_string()
|
self.to_string()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::utils::{ffi_crate, syn_assert, syn_error};
|
|||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{spanned::*, *};
|
use syn::*;
|
||||||
|
|
||||||
#[derive(Debug, FromMeta)]
|
#[derive(Debug, FromMeta)]
|
||||||
pub struct Args {}
|
pub struct Args {}
|
||||||
|
@ -5,8 +5,16 @@ use syn::parse_macro_input;
|
|||||||
|
|
||||||
mod cdef;
|
mod cdef;
|
||||||
mod metatype;
|
mod metatype;
|
||||||
|
mod module;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn module(_args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
||||||
|
module::transform(parse_macro_input!(input))
|
||||||
|
.unwrap_or_else(|err| err.into_compile_error().into_token_stream())
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn cdef(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
pub fn cdef(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
||||||
NestedMeta::parse_meta_list(args.into())
|
NestedMeta::parse_meta_list(args.into())
|
||||||
@ -17,7 +25,7 @@ pub fn cdef(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn metatype(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
pub fn metatype(_args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
||||||
metatype::transform(parse_macro_input!(input))
|
metatype::transform(parse_macro_input!(input))
|
||||||
.unwrap_or_else(|err| err.into_compile_error().into_token_stream())
|
.unwrap_or_else(|err| err.into_compile_error().into_token_stream())
|
||||||
.into()
|
.into()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::utils::{ffi_crate, is_primitive, is_unit, pat_ident, syn_assert, syn_error, ty_name};
|
use crate::utils::{ffi_crate, is_primitive, is_unit, pat_ident, syn_assert, ty_name};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{spanned::*, *};
|
use syn::*;
|
||||||
|
|
||||||
pub fn transform(mut imp: ItemImpl) -> Result<TokenStream> {
|
pub fn transform(mut imp: ItemImpl) -> Result<TokenStream> {
|
||||||
syn_assert!(
|
syn_assert!(
|
||||||
@ -146,7 +146,7 @@ enum FfiArgType {
|
|||||||
Default,
|
Default,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ffi_arg_type(ty: &Type) -> FfiArgType {
|
fn get_ffi_arg_type(_ty: &Type) -> FfiArgType {
|
||||||
FfiArgType::Default
|
FfiArgType::Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
crates/luaffi_impl/src/module.rs
Normal file
26
crates/luaffi_impl/src/module.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use crate::utils::syn_assert;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::*;
|
||||||
|
|
||||||
|
pub fn transform(func: ItemFn) -> Result<TokenStream> {
|
||||||
|
syn_assert!(
|
||||||
|
func.sig.generics.params.is_empty(),
|
||||||
|
func.sig.generics,
|
||||||
|
"cannot be generic (not yet implemented)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// let impls = generate_impls(&mut imp)?;
|
||||||
|
// let mod_name = format_ident!("__metatype__{}", ty_name(&imp.self_ty)?);
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#func
|
||||||
|
|
||||||
|
// #[doc(hidden)]
|
||||||
|
// #[allow(unused, non_snake_case)]
|
||||||
|
// mod #mod_name {
|
||||||
|
// use super::*;
|
||||||
|
// #impls
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use syn::{spanned::*, *};
|
use syn::*;
|
||||||
|
|
||||||
macro_rules! syn_error {
|
macro_rules! syn_error {
|
||||||
($src:expr, $($fmt:expr),+) => {{
|
($src:expr, $($fmt:expr),+) => {{
|
||||||
|
use syn::spanned::*;
|
||||||
return Err(syn::Error::new($src.span(), format!($($fmt),*)));
|
return Err(syn::Error::new($src.span(), format!($($fmt),*)));
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -10,7 +11,7 @@ macro_rules! syn_error {
|
|||||||
macro_rules! syn_assert {
|
macro_rules! syn_assert {
|
||||||
($cond:expr, $src:expr, $($fmt:expr),+) => {{
|
($cond:expr, $src:expr, $($fmt:expr),+) => {{
|
||||||
if !$cond {
|
if !$cond {
|
||||||
syn_error!($src, $($fmt),+);
|
crate::utils::syn_error!($src, $($fmt),+);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
23
crates/luajit-sys/Cargo.toml
Normal file
23
crates/luajit-sys/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "luajit-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["jit", "ffi", "lua52"]
|
||||||
|
runtime = []
|
||||||
|
jit = []
|
||||||
|
ffi = []
|
||||||
|
unwind = []
|
||||||
|
bundled-alloc = []
|
||||||
|
lua52 = []
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bindgen = "0.71.1"
|
||||||
|
cc = "1.2.26"
|
||||||
|
which = "8.0.0"
|
@ -7,23 +7,28 @@ use std::{
|
|||||||
};
|
};
|
||||||
use which::which;
|
use which::which;
|
||||||
|
|
||||||
|
/// Unwraps a Result and panics in a way that prints a nicer error message to the user.
|
||||||
macro_rules! panic_err {
|
macro_rules! panic_err {
|
||||||
($value:expr) => { $value.unwrap_or_else(|err| panic!("{err}")) };
|
($value:expr) => {{ $value.unwrap_or_else(|err| panic!("{err}")) }};
|
||||||
($value:expr, $($arg:expr)+) => { $value.unwrap_or_else(|err| panic!("{}: {err}", format_args!($($arg),+))) };
|
($value:expr, $($arg:expr)+) => {{ $value.unwrap_or_else(|err| panic!("{}: {err}", format_args!($($arg),+))) }};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Formats arguments in a way that is intended to address environment variables.
|
||||||
macro_rules! env_name {
|
macro_rules! env_name {
|
||||||
($($arg:expr),+) => { format!($($arg),+).replace("-", "_").to_uppercase() };
|
($($arg:expr),+) => {{ format!($($arg),+).replace("-", "_").to_uppercase() }};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands to the value of an environment variable.
|
||||||
macro_rules! env {
|
macro_rules! env {
|
||||||
($($arg:expr),+) => { panic_err!(env::var(env_name!($($arg),+))) };
|
($($arg:expr),+) => { panic_err!(env::var(env_name!($($arg),+))) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands to the value of a cargo configuration environment variable.
|
||||||
macro_rules! cfg {
|
macro_rules! cfg {
|
||||||
($($arg:expr),+) => { env!("CARGO_CFG_{}", format_args!($($arg),+)) };
|
($($arg:expr),+) => { env!("CARGO_CFG_{}", format_args!($($arg),+)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether a cargo feature is enabled.
|
||||||
macro_rules! feature {
|
macro_rules! feature {
|
||||||
($($arg:expr),+) => { env::var_os(env_name!("CARGO_FEATURE_{}", format_args!($($arg),+))).is_some() };
|
($($arg:expr),+) => { env::var_os(env_name!("CARGO_FEATURE_{}", format_args!($($arg),+))).is_some() };
|
||||||
}
|
}
|
||||||
@ -38,8 +43,9 @@ fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
panic_err!(write(out_path.join(".relver"), get_relver()));
|
panic_err!(write(out_path.join(".relver"), get_relver()));
|
||||||
println!("cargo::rerun-if-changed={}", src_path.display());
|
println!("cargo::rerun-if-changed={}", src_path.display()); // rerun if luajit source changed
|
||||||
|
|
||||||
|
// NOTE: we cannot build bindings without building luajit first (luajit generates some headers)
|
||||||
build_runtime(&out_path.join("src"));
|
build_runtime(&out_path.join("src"));
|
||||||
build_bindings(&out_path.join("src"));
|
build_bindings(&out_path.join("src"));
|
||||||
}
|
}
|
||||||
@ -49,7 +55,7 @@ fn get_relver() -> String {
|
|||||||
Command::new("git")
|
Command::new("git")
|
||||||
.args(["show", "-s", "--format=%ct"])
|
.args(["show", "-s", "--format=%ct"])
|
||||||
.output(),
|
.output(),
|
||||||
"failed to obtain release version (is the Git command available?)"
|
"failed to obtain luajit release version (is the Git command available?)"
|
||||||
);
|
);
|
||||||
|
|
||||||
String::from_utf8_lossy(&out.stdout).into()
|
String::from_utf8_lossy(&out.stdout).into()
|
||||||
@ -76,6 +82,7 @@ fn copy_recursive(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_make() -> Command {
|
fn find_make() -> Command {
|
||||||
|
// always use gnu make on bsds
|
||||||
let name = match parse_target(&env!("HOST")) {
|
let name = match parse_target(&env!("HOST")) {
|
||||||
(_, _, "freebsd" | "openbsd" | "netbsd" | "dragonfly", _) => "gmake",
|
(_, _, "freebsd" | "openbsd" | "netbsd" | "dragonfly", _) => "gmake",
|
||||||
_ => "make",
|
_ => "make",
|
||||||
@ -100,24 +107,16 @@ fn parse_target(target: &str) -> (&str, &str, &str, Option<&str>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_runtime(src_path: &Path) {
|
fn build_runtime(src_path: &Path) {
|
||||||
let mut make = find_make();
|
let host = env!("HOST"); // host triplet
|
||||||
let opt_level = env!("OPT_LEVEL");
|
|
||||||
let debug = opt_level == "0";
|
|
||||||
|
|
||||||
let host = env!("HOST");
|
|
||||||
let host_cc = find_cc(&host).to_str().unwrap().to_owned();
|
let host_cc = find_cc(&host).to_str().unwrap().to_owned();
|
||||||
let host_ptr_width = 8 * mem::size_of::<usize>();
|
let host_ptr_width = 8 * mem::size_of::<usize>();
|
||||||
|
|
||||||
let target = env!("TARGET");
|
let target = env!("TARGET"); // target triplet
|
||||||
let target_cc = find_cc(&target).to_str().unwrap().to_owned();
|
let target_cc = find_cc(&target).to_str().unwrap().to_owned();
|
||||||
// let target_features: HashSet<&str> = HashSet::from_iter(cfg!("target_feature").split(","));
|
// let target_features: HashSet<&str> = HashSet::from_iter(cfg!("target_feature").split(","));
|
||||||
let target_ptr_width: usize = cfg!("target_pointer_width").parse().unwrap();
|
let target_ptr_width: usize = cfg!("target_pointer_width").parse().unwrap();
|
||||||
|
|
||||||
if target == host {
|
let mut make = find_make();
|
||||||
println!("--- begin compile for {target}:");
|
|
||||||
} else {
|
|
||||||
println!("--- begin cross-compile on {host} for {target}:");
|
|
||||||
}
|
|
||||||
|
|
||||||
make.current_dir(&src_path)
|
make.current_dir(&src_path)
|
||||||
.env_clear()
|
.env_clear()
|
||||||
@ -126,28 +125,39 @@ fn build_runtime(src_path: &Path) {
|
|||||||
.env("MAKEFLAGS", env!("CARGO_MAKEFLAGS"))
|
.env("MAKEFLAGS", env!("CARGO_MAKEFLAGS"))
|
||||||
.env("BUILDMODE", "static");
|
.env("BUILDMODE", "static");
|
||||||
|
|
||||||
let ccopt = vec![format!("-O{opt_level} -fomit-frame-pointer")];
|
let ccopt = vec![format!("-O{} -fomit-frame-pointer", env!("OPT_LEVEL"))]; // propagate opt_level
|
||||||
|
let mut ccdebug = vec![];
|
||||||
|
let mut xcflags = vec![];
|
||||||
|
|
||||||
let mut xcflags = vec![
|
if env!("OPT_LEVEL") == "0" {
|
||||||
"-DLUAJIT_ENABLE_LUA52COMPAT", // lua 5.2 compatibility
|
ccdebug.push("-g"); // generate debug information
|
||||||
"-DLUAJIT_USE_SYSMALLOC", // disable bundled allocator
|
|
||||||
"-DLUAJIT_UNWIND_EXTERNAL -funwind-tables", // use external frame unwinding
|
|
||||||
];
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
make.env("CCDEBUG", "-g"); // generate debug information
|
|
||||||
xcflags.push("-DLUAJIT_USE_GDBJIT"); // gdb support
|
xcflags.push("-DLUAJIT_USE_GDBJIT"); // gdb support
|
||||||
xcflags.push("-DLUA_USE_APICHECK -DLUA_USE_ASSERT"); // enable assertions
|
xcflags.push("-DLUA_USE_APICHECK -DLUA_USE_ASSERT"); // enable assertions
|
||||||
}
|
}
|
||||||
|
|
||||||
if !feature!("enable-jit") {
|
xcflags.push(if feature!("unwind") {
|
||||||
|
"-DLUAJIT_UNWIND_EXTERNAL -funwind-tables" // external frame unwinding (C++ exceptions)
|
||||||
|
} else {
|
||||||
|
"-DLUAJIT_UNWIND_INTERNAL" // internal frame unwinding (setjmp/longjmp)
|
||||||
|
});
|
||||||
|
|
||||||
|
if !feature!("jit") {
|
||||||
xcflags.push("-DLUAJIT_DISABLE_JIT");
|
xcflags.push("-DLUAJIT_DISABLE_JIT");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !feature!("enable-ffi") {
|
if !feature!("ffi") {
|
||||||
xcflags.push("-DLUAJIT_DISABLE_FFI");
|
xcflags.push("-DLUAJIT_DISABLE_FFI");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !feature!("bundled-alloc") {
|
||||||
|
xcflags.push("-DLUAJIT_USE_SYSMALLOC"); // using system malloc disables the bundled allocator
|
||||||
|
}
|
||||||
|
|
||||||
|
if feature!("lua52") {
|
||||||
|
xcflags.push("-DLUAJIT_ENABLE_LUA52COMPAT");
|
||||||
|
}
|
||||||
|
|
||||||
|
// host toolchain config
|
||||||
match (host_ptr_width, target_ptr_width) {
|
match (host_ptr_width, target_ptr_width) {
|
||||||
(64, 64) | (32, 32) => make.env("HOST_CC", &host_cc),
|
(64, 64) | (32, 32) => make.env("HOST_CC", &host_cc),
|
||||||
(64, 32) => make.env("HOST_CC", format!("{} -m32", host_cc)),
|
(64, 32) => make.env("HOST_CC", format!("{} -m32", host_cc)),
|
||||||
@ -155,6 +165,7 @@ fn build_runtime(src_path: &Path) {
|
|||||||
(n, _) => panic!("unsupported {n}-bit architecture"),
|
(n, _) => panic!("unsupported {n}-bit architecture"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// target system config
|
||||||
match cfg!("target_os").as_str() {
|
match cfg!("target_os").as_str() {
|
||||||
"linux" | "android" => make.env("TARGET_SYS", "Linux"),
|
"linux" | "android" => make.env("TARGET_SYS", "Linux"),
|
||||||
"windows" => make.env("TARGET_SYS", "Windows"),
|
"windows" => make.env("TARGET_SYS", "Windows"),
|
||||||
@ -173,6 +184,7 @@ fn build_runtime(src_path: &Path) {
|
|||||||
_ => make.env("TARGET_SYS", "Other"),
|
_ => make.env("TARGET_SYS", "Other"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// target toolchain config
|
||||||
if let Some(cross) = target_cc.strip_suffix("gcc") {
|
if let Some(cross) = target_cc.strip_suffix("gcc") {
|
||||||
make.env("CC", "gcc").env("CROSS", cross);
|
make.env("CC", "gcc").env("CROSS", cross);
|
||||||
} else if let Some(cross) = target_cc.strip_suffix("clang") {
|
} else if let Some(cross) = target_cc.strip_suffix("clang") {
|
||||||
@ -183,13 +195,22 @@ fn build_runtime(src_path: &Path) {
|
|||||||
.env("CROSS", format!("{}/", path.parent().unwrap().display()));
|
.env("CROSS", format!("{}/", path.parent().unwrap().display()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// propagate linker config
|
||||||
if let Some(path) = env::var("RUSTC_LINKER").ok() {
|
if let Some(path) = env::var("RUSTC_LINKER").ok() {
|
||||||
make.env("TARGET_LD", panic_err!(which(path), "failed to find ld"));
|
make.env("TARGET_LD", panic_err!(which(path), "failed to find ld"));
|
||||||
}
|
}
|
||||||
|
|
||||||
make.env("CCOPT", ccopt.join(" "))
|
make.env("CCOPT", ccopt.join(" "))
|
||||||
|
.env("CCDEBUG", ccdebug.join(" "))
|
||||||
.env("XCFLAGS", xcflags.join(" "));
|
.env("XCFLAGS", xcflags.join(" "));
|
||||||
|
|
||||||
|
if target == host {
|
||||||
|
println!("--- begin compile for {target}:");
|
||||||
|
} else {
|
||||||
|
println!("--- begin cross-compile on {host} for {target}:");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{make:?}");
|
||||||
let status = panic_err!(make.status(), "failed to execute make");
|
let status = panic_err!(make.status(), "failed to execute make");
|
||||||
(!status.success()).then(|| panic!("failed to compile luajit: {status}: {make:?}"));
|
(!status.success()).then(|| panic!("failed to compile luajit: {status}: {make:?}"));
|
||||||
|
|
||||||
@ -200,12 +221,22 @@ fn build_runtime(src_path: &Path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_bindings(src_path: &Path) {
|
fn build_bindings(src_path: &Path) {
|
||||||
|
let mut clang_args = vec![format!("--target={}", env!("TARGET"))];
|
||||||
|
let abi = if feature!("unwind") {
|
||||||
|
clang_args.push("-fexceptions".into());
|
||||||
|
bindgen::Abi::CUnwind
|
||||||
|
} else {
|
||||||
|
clang_args.push("-fno-exceptions".into());
|
||||||
|
bindgen::Abi::C
|
||||||
|
};
|
||||||
|
|
||||||
let mut bindgen = bindgen::builder()
|
let mut bindgen = bindgen::builder()
|
||||||
.clang_arg(format!("--target={}", env!("TARGET")))
|
.clang_args(clang_args)
|
||||||
.allowlist_item(r"^(lua|LUA).*_.+$")
|
.allowlist_item(r"^(lua|LUA).*_.+$")
|
||||||
.formatter(bindgen::Formatter::None)
|
.formatter(bindgen::Formatter::None)
|
||||||
.default_macro_constant_type(bindgen::MacroTypeVariation::Signed)
|
.default_macro_constant_type(bindgen::MacroTypeVariation::Signed)
|
||||||
.generate_cstr(true);
|
.generate_cstr(true)
|
||||||
|
.override_abi(abi, ".*");
|
||||||
|
|
||||||
for header in ["lua.h", "lualib.h", "lauxlib.h", "luaconf.h", "luajit.h"] {
|
for header in ["lua.h", "lualib.h", "lauxlib.h", "luaconf.h", "luajit.h"] {
|
||||||
bindgen = bindgen.header(src_path.join(header).to_str().unwrap());
|
bindgen = bindgen.header(src_path.join(header).to_str().unwrap());
|
||||||
@ -213,5 +244,5 @@ fn build_bindings(src_path: &Path) {
|
|||||||
|
|
||||||
let path = src_path.join("bindgen.rs");
|
let path = src_path.join("bindgen.rs");
|
||||||
panic_err!(panic_err!(bindgen.generate(), "failed to generate bindings").write_to_file(&path));
|
panic_err!(panic_err!(bindgen.generate(), "failed to generate bindings").write_to_file(&path));
|
||||||
println!("cargo::rustc-env=LJ_BINDINGS={}", path.display());
|
println!("cargo::rustc-env=LUAJIT_SYS_BINDGEN={}", path.display());
|
||||||
}
|
}
|
99
crates/luajit-sys/lib.rs
Normal file
99
crates/luajit-sys/lib.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#![allow(nonstandard_style)]
|
||||||
|
use std::{ffi::*, ptr};
|
||||||
|
|
||||||
|
include!(env!("LUAJIT_SYS_BINDGEN"));
|
||||||
|
|
||||||
|
// #[cfg(all(panic = "abort", feature = "unwind"))]
|
||||||
|
// compile_error!(r#"feature "unwind" cannot be enabled if panic = "abort""#);
|
||||||
|
|
||||||
|
// #[cfg(all(panic = "unwind", not(feature = "unwind")))]
|
||||||
|
// compile_error!(r#"feature "unwind" must be enabled if panic = "unwind""#);
|
||||||
|
|
||||||
|
// constants not exposed by lua.h
|
||||||
|
pub const LUA_TPROTO: c_int = LUA_TTHREAD + 1;
|
||||||
|
pub const LUA_TCDATA: c_int = LUA_TTHREAD + 2;
|
||||||
|
|
||||||
|
// macros not translated by bindgen
|
||||||
|
pub unsafe fn lua_upvalueindex(i: c_int) -> c_int {
|
||||||
|
LUA_GLOBALSINDEX - i
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_pop(L: *mut lua_State, n: c_int) {
|
||||||
|
unsafe { lua_settop(L, -n - 1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_newtable(L: *mut lua_State) {
|
||||||
|
unsafe { lua_createtable(L, 0, 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_register(L: *mut lua_State, n: *const c_char, f: lua_CFunction) {
|
||||||
|
unsafe { (lua_pushcfunction(L, f), lua_setglobal(L, n)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
|
||||||
|
unsafe { lua_pushcclosure(L, f, 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_strlen(L: *mut lua_State, i: c_int) -> usize {
|
||||||
|
unsafe { lua_objlen(L, i) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isfunction(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TFUNCTION) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_istable(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TTABLE) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_islightuserdata(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TLIGHTUSERDATA) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isnil(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TNIL) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isboolean(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TBOOLEAN) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isthread(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TTHREAD) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isnone(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) == LUA_TNONE) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_isnoneornil(L: *mut lua_State, n: c_int) -> c_int {
|
||||||
|
unsafe { (lua_type(L, n) <= LUA_TNIL) as c_int }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: impl AsRef<[u8]>) {
|
||||||
|
unsafe { lua_pushlstring(L, s.as_ref().as_ptr().cast(), s.as_ref().len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_setglobal(L: *mut lua_State, s: *const c_char) {
|
||||||
|
unsafe { lua_setfield(L, LUA_GLOBALSINDEX, s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_getglobal(L: *mut lua_State, s: *const c_char) {
|
||||||
|
unsafe { lua_getfield(L, LUA_GLOBALSINDEX, s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||||
|
unsafe { lua_tolstring(L, i, ptr::null_mut()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_open() -> *mut lua_State {
|
||||||
|
unsafe { luaL_newstate() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_getregistry(L: *mut lua_State) {
|
||||||
|
unsafe { lua_pushvalue(L, LUA_REGISTRYINDEX) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lua_getgccount(L: *mut lua_State) -> c_int {
|
||||||
|
unsafe { lua_gc(L, LUA_GCCOUNT, 0) }
|
||||||
|
}
|
@ -3,22 +3,13 @@ name = "luajit"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "lib.rs"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["enable-jit", "enable-ffi"]
|
runtime = ["luajit-sys/runtime"]
|
||||||
runtime = []
|
unwind = ["luajit-sys/unwind"]
|
||||||
enable-jit = []
|
|
||||||
enable-ffi = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = { version = "2.9.1", features = ["std"] }
|
bitflags = { version = "2.9.1", features = ["std"] }
|
||||||
bstr = "1.12.0"
|
bstr = "1.12.0"
|
||||||
luaffi = { version = "0.1.0", path = "../luaffi" }
|
luaffi = { version = "0.1.0", path = "../luaffi" }
|
||||||
|
luajit-sys = { version = "0.1.0", path = "../luajit-sys" }
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
bindgen = "0.71.1"
|
|
||||||
cc = "1.2.26"
|
|
||||||
which = "8.0.0"
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use bstr::{BStr, BString, ByteSlice};
|
use bstr::{BStr, BString, ByteSlice};
|
||||||
use luaffi::future::lua_pollable;
|
use luaffi::future::lua_pollable;
|
||||||
|
use luajit_sys::*;
|
||||||
use std::{
|
use std::{
|
||||||
alloc::{Layout, alloc, dealloc, realloc},
|
alloc::{Layout, alloc, dealloc, realloc},
|
||||||
ffi::{CString, NulError},
|
ffi::{CString, NulError},
|
||||||
@ -16,131 +17,79 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
include!(env!("LJ_BINDINGS"));
|
/// LuaJIT error.
|
||||||
|
|
||||||
// constants not exposed by lua.h
|
|
||||||
pub const LUA_TPROTO: c_int = LUA_TTHREAD + 1;
|
|
||||||
pub const LUA_TCDATA: c_int = LUA_TTHREAD + 2;
|
|
||||||
|
|
||||||
// macros not translated by bindgen
|
|
||||||
pub unsafe fn lua_upvalueindex(i: c_int) -> c_int {
|
|
||||||
LUA_GLOBALSINDEX - i
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_pop(L: *mut lua_State, n: c_int) {
|
|
||||||
unsafe { lua_settop(L, -n - 1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_newtable(L: *mut lua_State) {
|
|
||||||
unsafe { lua_createtable(L, 0, 0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_register(L: *mut lua_State, n: *const c_char, f: lua_CFunction) {
|
|
||||||
unsafe { (lua_pushcfunction(L, f), lua_setglobal(L, n)) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
|
|
||||||
unsafe { lua_pushcclosure(L, f, 0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_strlen(L: *mut lua_State, i: c_int) -> usize {
|
|
||||||
unsafe { lua_objlen(L, i) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isfunction(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TFUNCTION) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_istable(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TTABLE) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_islightuserdata(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TLIGHTUSERDATA) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isnil(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TNIL) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isboolean(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TBOOLEAN) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isthread(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TTHREAD) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isnone(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) == LUA_TNONE) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_isnoneornil(L: *mut lua_State, n: c_int) -> c_int {
|
|
||||||
unsafe { (lua_type(L, n) <= LUA_TNIL) as c_int }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: impl AsRef<[u8]>) {
|
|
||||||
unsafe { lua_pushlstring(L, s.as_ref().as_ptr().cast(), s.as_ref().len()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_setglobal(L: *mut lua_State, s: *const c_char) {
|
|
||||||
unsafe { lua_setfield(L, LUA_GLOBALSINDEX, s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_getglobal(L: *mut lua_State, s: *const c_char) {
|
|
||||||
unsafe { lua_getfield(L, LUA_GLOBALSINDEX, s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
|
||||||
unsafe { lua_tolstring(L, i, ptr::null_mut()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_open() -> *mut lua_State {
|
|
||||||
unsafe { luaL_newstate() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_getregistry(L: *mut lua_State) {
|
|
||||||
unsafe { lua_pushvalue(L, LUA_REGISTRYINDEX) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn lua_getgccount(L: *mut lua_State) -> c_int {
|
|
||||||
unsafe { lua_gc(L, LUA_GCCOUNT, 0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Out of memory error.
|
||||||
#[error("out of memory")]
|
#[error("out of memory")]
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
|
/// Lua syntax error returned by [`Stack::load`].
|
||||||
#[error("{msg}")]
|
#[error("{msg}")]
|
||||||
Syntax { chunk: BString, msg: BString },
|
Syntax {
|
||||||
|
/// Content of the chunk which had errors.
|
||||||
|
chunk: BString,
|
||||||
|
/// Lua error message.
|
||||||
|
msg: BString,
|
||||||
|
},
|
||||||
|
/// Lua chunk name error returned by [`Stack::load`].
|
||||||
#[error("bad chunk name: {0}")]
|
#[error("bad chunk name: {0}")]
|
||||||
BadChunkName(NulError),
|
BadChunkName(NulError),
|
||||||
|
/// Lua error returned by [`Stack::call`].
|
||||||
#[error("{msg}")]
|
#[error("{msg}")]
|
||||||
Call { msg: BString },
|
Call {
|
||||||
|
/// Lua error message.
|
||||||
|
msg: BString,
|
||||||
|
},
|
||||||
|
/// Lua error returned by [`Stack::resume`].
|
||||||
#[error("{msg}")]
|
#[error("{msg}")]
|
||||||
Resume { msg: BString, trace: BString },
|
Resume {
|
||||||
|
/// Lua error message.
|
||||||
|
msg: BString,
|
||||||
|
/// Lua stack trace.
|
||||||
|
trace: BString,
|
||||||
|
},
|
||||||
|
/// Type mismatch type error.
|
||||||
#[error("{0} expected, got {1}")]
|
#[error("{0} expected, got {1}")]
|
||||||
InvalidType(&'static str, &'static str),
|
InvalidType(
|
||||||
|
/// The expected type.
|
||||||
|
&'static str,
|
||||||
|
/// The actual type.
|
||||||
|
&'static str,
|
||||||
|
),
|
||||||
|
/// Invalid UTF-8 string error.
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
InvalidUtf8(#[from] Utf8Error),
|
InvalidUtf8(#[from] Utf8Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lua type.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
|
/// `nil` type.
|
||||||
#[default]
|
#[default]
|
||||||
Nil,
|
Nil,
|
||||||
|
/// `boolean` type.
|
||||||
Boolean,
|
Boolean,
|
||||||
|
/// `lightuserdata` type.
|
||||||
Lightuserdata,
|
Lightuserdata,
|
||||||
|
/// `number` type.
|
||||||
Number,
|
Number,
|
||||||
|
/// `string` type.
|
||||||
String,
|
String,
|
||||||
|
/// `table` type.
|
||||||
Table,
|
Table,
|
||||||
|
/// `function` type.
|
||||||
Function,
|
Function,
|
||||||
|
/// `userdata` type.
|
||||||
Userdata,
|
Userdata,
|
||||||
|
/// `thread` type.
|
||||||
Thread,
|
Thread,
|
||||||
|
/// `cdata` type.
|
||||||
Cdata,
|
Cdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
/// Converts a raw Lua type code to [`Type`], returning [`None`] if the value is invalid.
|
||||||
pub fn from_code(code: c_int) -> Option<Self> {
|
pub fn from_code(code: c_int) -> Option<Self> {
|
||||||
Some(match code {
|
Some(match code {
|
||||||
LUA_TNIL => Self::Nil,
|
LUA_TNIL => Self::Nil,
|
||||||
@ -157,6 +106,7 @@ impl Type {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Name of this type, like `"nil"` or `"string"`.
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Nil => "nil",
|
Self::Nil => "nil",
|
||||||
@ -179,15 +129,20 @@ impl fmt::Display for Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lua thread status.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
|
/// Thread is alive (currently running or can run a function).
|
||||||
#[default]
|
#[default]
|
||||||
Normal,
|
Normal,
|
||||||
|
/// Thread terminated with an error and cannot be resumed.
|
||||||
Dead,
|
Dead,
|
||||||
|
/// Thread suspended with `coroutine.yield(...)` and is awaiting resume.
|
||||||
Suspended,
|
Suspended,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Status {
|
impl Status {
|
||||||
|
/// Converts a raw Lua status code to [`Status`], returning [`None`] if the value is invalid.
|
||||||
pub fn from_code(code: c_int) -> Option<Self> {
|
pub fn from_code(code: c_int) -> Option<Self> {
|
||||||
Some(match code {
|
Some(match code {
|
||||||
LUA_OK => Self::Normal,
|
LUA_OK => Self::Normal,
|
||||||
@ -197,6 +152,7 @@ impl Status {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Name of this status, like `"normal"` or `"dead"`.
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Status::Normal => "normal",
|
Status::Normal => "normal",
|
||||||
@ -212,14 +168,18 @@ impl fmt::Display for Status {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Result of [`Stack::resume`].
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum ResumeStatus {
|
pub enum ResumeStatus {
|
||||||
|
/// Thread returned successfully and can run another function.
|
||||||
#[default]
|
#[default]
|
||||||
Ok,
|
Ok,
|
||||||
|
/// Thread suspended with `coroutine.yield(...)` and is awaiting resume.
|
||||||
Suspended,
|
Suspended,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResumeStatus {
|
impl ResumeStatus {
|
||||||
|
/// Name of this status, like `"ok"` or `"suspended"`.
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
ResumeStatus::Ok => "ok",
|
ResumeStatus::Ok => "ok",
|
||||||
@ -722,7 +682,10 @@ impl Stack {
|
|||||||
let value = self.index(1);
|
let value = self.index(1);
|
||||||
let ptr = value.cdata::<lua_pollable>().cast_mut();
|
let ptr = value.cdata::<lua_pollable>().cast_mut();
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(Error::InvalidType("cdata", value.type_of().name()));
|
return Err(Error::InvalidType(
|
||||||
|
"cdata<struct lua_pollable>",
|
||||||
|
value.type_of().name(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
unsafe { (&mut *ptr).await }
|
unsafe { (&mut *ptr).await }
|
||||||
narg = 1;
|
narg = 1;
|
2
scripts/build.sh
Executable file
2
scripts/build.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cargo build "$@"
|
2
scripts/doc.sh
Executable file
2
scripts/doc.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cargo doc --all --no-deps "$@"
|
Loading…
x
Reference in New Issue
Block a user