mlua/mlua-sys/src/luau/lstate.rs

217 lines
5.5 KiB
Rust

use std::ffi::{c_void, c_int, c_ushort, c_uint};
use std::mem::ManuallyDrop;
use std::ptr::{addr_of_mut, NonNull};
use crate::{Closure, GCheader, Proto, StkId, Table, TString, TValue, Udata, UpVal};
opaque! {
pub type global_State;
pub type Instruction;
}
extern "C" {
pub static luaO_nilobject_: TValue;
}
#[inline(always)]
pub fn luaO_nilobject() -> NonNull<TValue> {
unsafe { NonNull::new_unchecked(std::ptr::addr_of!(luaO_nilobject_).cast_mut()) }
}
/// Union of all collectible objects
#[repr(C)]
pub union GCObject
{
pub gch: ManuallyDrop<GCheader>,
pub ts: ManuallyDrop<TString>,
pub u: ManuallyDrop<Udata>,
pub cl: ManuallyDrop<Closure>,
pub h: ManuallyDrop<Table>,
pub p: ManuallyDrop<Proto>,
pub uv: ManuallyDrop<UpVal>,
/// thread
pub th: ManuallyDrop<lua_State>,
}
impl std::fmt::Debug for GCObject {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "GCObject({:?})", unsafe { self.gch })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct GCObjectPtr(pub *mut GCObject);
impl GCObjectPtr {
pub fn hdr(self) -> *mut GCheader {
unsafe { addr_of_mut!(*(*self.0).gch) }
}
}
impl From<GCObjectPtr> for *mut GCObject {
#[inline(always)]
fn from(value: GCObjectPtr) -> Self {
value.0
}
}
impl From<*mut GCObject> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut GCObject) -> Self {
Self(value)
}
}
impl From<*mut GCheader> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut GCheader) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut TString> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut TString) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut Udata> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut Udata) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut Closure> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut Closure) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut Table> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut Table) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut Proto> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut Proto) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut UpVal> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut UpVal) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
impl From<*mut lua_State> for GCObjectPtr {
#[inline(always)]
fn from(value: *mut lua_State) -> Self {
unsafe { GCObjectPtr(std::mem::transmute(value)) }
}
}
/// See docs at <https://github.com/Roblox/luau/blob/a02eb78c96f695a4287e7dd1beaccab3642c35f3/VM/src/lstate.h#L29-L29>
#[derive(Debug)]
#[repr(C)]
pub struct CallInfo {
/// base for this function.
pub base: StkId,
/// function index in the stack
pub func: StkId,
/// top for this function
///
/// Seems to indicate the allocated stack size, not used.
pub top: StkId,
pub saved_pc: *const Instruction,
/// expected number of results from this function
pub n_results: c_int,
/// call frame flags, see LUA_CALLINFO_*
pub flags: c_uint,
}
/// should the interpreter return after returning from this callinfo? first frame must have this set
pub const LUA_CALLINFO_RETURN: c_uint = 1 << 0;
/// should the error thrown during execution get handled by continuation from this callinfo? func must be C
pub const LUA_CALLINFO_HANDLE: c_uint = 1 << 1;
/// should this function be executed using execution callback for native code
pub const LUA_CALLINFO_NATIVE: c_uint = 1 << 2;
/// A raw Lua state associated with a thread.
#[derive(Debug)]
#[repr(C)]
pub struct lua_State {
pub tt: u8,
pub marked: u8,
pub memcat: u8,
pub status: u8,
/// memory category that is used for new GC object allocations
pub active_memcat: u8,
/// thread is currently executing, stack may be mutated without barriers
pub is_active: bool,
/// call debugstep hook after each instruction
pub single_step: bool,
/// first free slot in the stack
pub top: StkId,
/// base of current function
pub base: StkId,
pub global: *mut global_State,
/// call info for current function
pub ci: *mut CallInfo,
/// last free slot in the stack
pub stack_last: StkId,
/// stack base
pub stack: StkId,
/// points after end of ci array
pub end_ci: *mut CallInfo,
/// array of [`CallInfo`]s
pub base_ci: *mut CallInfo,
/// The current allocated size of the entire thread stack.
pub stack_size: c_int,
/// size of array [`base_ci']
pub size_ci: c_int,
/// number of nested C calls
pub n_c_calls: c_ushort,
/// nested C calls when resuming coroutine
pub base_c_calls: c_ushort,
/// when table operations or `INDEX`/`NEWINDEX` is invoked from Luau, what is the expected slot for lookup?
pub cached_slot: c_int,
/// table of globals
pub globals: *mut Table,
/// list of open upvalues in this stack
pub open_upval: *mut UpVal,
pub gc_list: *mut GCObject,
/// when invoked from Luau using `NAMECALL`, what method do we need to invoke?
pub namecall: *mut TString,
pub userdata: *mut c_void,
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}