///|
/// The type of floats in Lua.
pub type Number = Double
///|
/// The type of integers in Lua.
pub type Integer = Int64
///|
pub const VersionNum : Int = 504
///|
pub const VersionReleaseNum : Int = VersionNum * 100 + 8
///|
pub const VersionMajor : Bytes = "5"
///|
pub const VersionMinor : Bytes = "4"
///|
pub const VersionRelease : Bytes = "8"
///|
pub const Version : Bytes = "Lua 5.4"
///|
pub const Release : Bytes = "Lua 5.4.8"
///|
pub const Copyright : Bytes = "Lua 5.4.8 Copyright (C) 1994-2025 Lua.org, PUC-Rio"
///|
pub const Authors : Bytes = "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
///|
/// No errors.
pub const Ok : Int = 0
///|
/// The thread (coroutine) yields.
pub const Yield : Int = 1
///|
/// A runtime error.
pub const ErrRun : Int = 2
///|
/// Syntax error during precompilation.
pub const ErrSyntax : Int = 3
///|
/// Memory allocation error. For such errors, Lua does not call the message handler.
pub const ErrMem : Int = 4
///|
/// Error while running the message handler.
pub const ErrErr : Int = 5
///|
pub const Signature : Bytes = "\x1bLua"
///|
pub const MultRet : Int = -1
///|
extern "c" fn lua_registry_index() -> Int = "moonbit_lua_registry_index"
///|
/// Returns the pseudo-index that represents the i-th upvalue of the running
/// function (see [§4.2](https://www.lua.org/manual/5.4/manual.html#4.2)). i
/// must be in the range [1,256].
pub extern "c" fn upvalue_index(i : Int) -> Int = "moonbit_lua_upvalueindex"
///|
pub let registry_index : Int = lua_registry_index()
///|
pub(all) struct State(@c.Pointer[Unit])
///|
pub fn State::of_pointer(ptr : @c.Pointer[Unit]) -> State {
State(ptr.cast())
}
///|
pub fn State::to_pointer(self : State) -> @c.Pointer[Unit] {
self.0.cast()
}
///|
pub(all) enum Type {
Nil = 0
Boolean = 1
LightUserdata = 2
Number = 3
String = 4
Table = 5
Function = 6
Userdata = 7
Thread = 8
} derive(Show, Eq)
///|
pub const TypeNil : Int = 0
///|
pub const TypeBoolean : Int = 1
///|
pub const TypeLightUserdata : Int = 2
///|
pub const TypeNumber : Int = 3
///|
pub const TypeString : Int = 4
///|
pub const TypeTable : Int = 5
///|
pub const TypeFunction : Int = 6
///|
pub const TypeUserdata : Int = 7
///|
pub const TypeThread : Int = 8
///|
fn Type::from_int(value : Int) -> Type? {
match value {
0 => Some(Nil)
1 => Some(Boolean)
2 => Some(LightUserdata)
3 => Some(Number)
4 => Some(String)
5 => Some(Table)
6 => Some(Function)
7 => Some(Userdata)
8 => Some(Thread)
_ => None
}
}
///|
fn Type::to_int(self : Type?) -> Int {
match self {
None => -1
Some(Nil) => 0
Some(Boolean) => 1
Some(LightUserdata) => 2
Some(Number) => 3
Some(String) => 4
Some(Table) => 5
Some(Function) => 6
Some(Userdata) => 7
Some(Thread) => 8
}
}
///|
pub const MinStack : Int = 20
///|
pub const RidxMainThread : Int = 1
///|
pub const RidxGlobals : Int = 2
///|
/// Type for C functions.
///
/// In order to communicate properly with Lua, a C function must use the
/// following protocol, which defines the way parameters and results are passed:
/// a C function receives its arguments from Lua in its stack in direct order
/// (the first argument is pushed first). So, when the function starts,
/// [`@lua.get_top()`](#get_top) returns the number of arguments received by the
/// function. The first argument (if any) is at index 1 and its last argument is
/// at index [`@lua.get_top()`](#get_top). To return values to Lua, a C function
/// just pushes them onto the stack, in direct order (the first result is pushed
/// first), and returns in C the number of results. Any other value in the stack
/// below the results will be properly discarded by Lua. Like a Lua function, a
/// C function called by Lua can also return many results.
///
/// As an example, the following function receives a variable number of numeric
/// arguments and returns their average and their sum:
///
/// ```moonbit
/// fn foo(l : @lua.State) -> Int {
/// let n = @lua.get_top(l) // number of arguments
/// let mut sum = 0.0
/// for i = 1; i <= n; i = i + 1 {
/// if !@lua.is_number(l, i) {
/// @lua.push_string(l, b"incorrect argument")
/// @lua.error(l)
/// }
/// sum += @lua.to_number(l, i)
/// }
/// @lua.push_number(l, sum / n) // first result
/// @lua.push_number(l, sum) // second result
/// return 2 // number of results
/// }
/// ```
#external
type CFunction
///|
#as_free_fn(c_function)
pub fn CFunction::new(f : FuncRef[(State) -> Int]) -> CFunction = "%identity"
///|
pub fn CFunction::to_funcref(state : CFunction) -> FuncRef[(State) -> Int] = "%identity"
///|
extern "c" fn lua_invoke_cfunction(state : State, f : CFunction) -> Int = "moonbit_lua_call_cfunction"
///|
pub fn CFunction::invoke(self : CFunction, state : State) -> Int {
lua_invoke_cfunction(state, self)
}
///|
/// The reader function used by [`@lua.load`](#load). Every time
/// [`@lua.load`](#load) needs another piece of the chunk, it calls the reader,
/// passing along its data parameter. The reader must return a pointer to a
/// block of memory with a new piece of the chunk and set size to the block
/// size. The block must exist until the reader function is called again. To
/// signal the end of the chunk, the reader must return `@c.Pointer::null()` or
/// set size to zero. The reader function may return pieces of any size greater
/// than zero.
pub(all) struct Reader((State, @c.Pointer[UInt64]) -> @c.Pointer[Byte])
///|
/// The type of the writer function used by [`@lua.dump`](#dump). Every time
/// [`@lua.dump`](#dump) produces another piece of chunk, it calls the writer,
/// passing along the buffer to be written (p) and its size (sz) supplied to
/// [`@lua.dump`](#dump).
///
/// The writer returns an error code: 0 means no errors; any other value means
/// an error and stops [`@lua.dump`](#dump) from calling the writer again.
pub(all) struct Writer((State, @c.Pointer[Unit], UInt64) -> Int)
///|
/// The type of the memory-allocation function used by Lua states. The allocator
/// function must provide a functionality similar to realloc, but not exactly
/// the same. Its arguments are `ptr`, a pointer to the block being
/// allocated/reallocated/freed; `osize`, the original size of the block or some
/// code about what is being allocated; and `nsize`, the new size of the block.
///
/// When `ptr` is not `NULL`, `osize` is the size of the block pointed by `ptr`,
/// that is, the size given when it was allocated or reallocated.
///
/// When `ptr` is `NULL`, `osize` encodes the kind of object that Lua is
/// allocating. `osize` is any of [`@lua.TypeString`](#TypeString),
/// [`@lua.TypeTable`](#TypeTable), [`@lua.TypeFunction`](#TypeFunction),
/// [`@lua.TypeUserdata`](#TypeUserdata), or [`@lua.TypeThread`](#TypeThread)
/// when (and only when) Lua is creating a new object of that type. When `osize`
/// is some other value, Lua is allocating memory for something else.
///
/// Lua assumes the following behavior from the allocator function:
///
/// When `nsize` is zero, the allocator must behave like `free` and then return
/// `NULL`.
///
/// When `nsize` is not zero, the allocator must behave like `realloc`. In
/// particular, the allocator returns `NULL` if and only if it cannot fulfill
/// the request.
///
/// Here is a simple implementation for the allocator function. It is used in
/// the auxiliary library by `@aux.new_state`.
///
/// ```moonbit
/// fn l_alloc(
/// ptr : @c.Pointer[Unit],
/// osize : UInt64,
/// nsize : UInt64,
/// ) -> @c.Pointer[Unit] {
/// ignore(osize)
/// if nsize == 0 {
/// @memory.free(ptr)
/// return @c.Pointer::null()
/// } else {
/// return @memory.realloc(ptr, nsize)
/// }
/// }
/// ```
///
/// Note that ISO C ensures that `free(NULL)` has no effect and that
/// `realloc(NULL, size)` is equivalent to `malloc(size)`.
pub(all) struct Alloc((@c.Pointer[Unit], UInt64, UInt64) -> @c.Pointer[Unit])
///|
/// The type of warning functions, called by Lua to emit warnings. The first
/// parameter is an opaque pointer set by [`@lua.set_warn_f`](#set_warn_f). The
/// second parameter is the warning message. The third parameter is a boolean
/// that indicates whether the message is to be continued by the message in the
/// next call.
///
/// See [`warn`](https://www.lua.org/manual/5.4/manual.html#pdf-warn) for more
/// details about warnings.
pub(all) struct WarnFunction((Bytes, Bool) -> Unit)
///|
extern "c" fn lua_newstate(
f : FuncRef[(Alloc, @c.Pointer[Unit], UInt64, UInt64) -> @c.Pointer[Unit]],
ud : Alloc,
) -> State = "lua_newstate"
///|
/// Creates a new independent state and returns its main thread. Returns `None`
/// if it cannot create the state (due to lack of memory). The argument `f` is
/// the allocator function; Lua will do all memory allocation for this state
/// through this function (see [`@lua.Alloc`](#Alloc)).
pub fn new_state(alloc : Alloc) -> State? {
let state = lua_newstate(
(ud, ptr, osize, nsize) => ud(ptr, osize, nsize),
alloc,
)
if state.0.is_null() {
None
} else {
Some(state)
}
}
///|
/// Close all active to-be-closed variables in the main thread, release all
/// objects in the given Lua state (calling the corresponding garbage-collection
/// metamethods, if any), and frees all dynamic memory used by this state.
///
/// On several platforms, you may not need to call this function, because all
/// resources are naturally released when the host program ends. On the other
/// hand, long-running programs that create multiple states, such as daemons or
/// web servers, will probably need to close states as soon as they are not
/// needed.
pub extern "c" fn close(state : State) = "lua_close"
///|
extern "c" fn lua_newthread(state : State) -> State = "lua_newthread"
///|
/// Creates a new thread, pushes it on the stack, and returns a pointer to a
/// `State` that represents this new thread. The new thread returned by this
/// function shares with the original thread its global environment, but has an
/// independent execution stack.
///
/// Threads are subject to garbage collection, like any Lua object.
pub fn new_thread(state : State) -> State? {
let state = lua_newthread(state.0)
if state.0.is_null() {
None
} else {
Some(state)
}
}
///|
extern "c" fn lua_closethread(state : State, from : State) -> Int = "lua_closethread"
///|
/// Resets a thread, cleaning its call stack and closing all pending
/// to-be-closed variables. Returns a status code: [`@lua.Ok`](#Ok) for no
/// errors in the thread (either the original error that stopped the thread or
/// errors in closing methods), or an error status otherwise. In case of error,
/// leaves the error object on the top of the stack.
///
/// The parameter `from` represents the coroutine that is resetting `state`. If
/// there is no such coroutine, this parameter can be `None`.
///
/// (This function was introduced in release 5.4.6.)
pub fn close_thread(state : State, from? : State) -> Int {
if from is Some(from) {
lua_closethread(state, from)
} else {
lua_closethread(state, @c.Pointer::null())
}
}
///|
/// This function is deprecated; it is equivalent to
/// [`@lua.close_thread`](#close_thread) with `from` being `None`.
#deprecated("Use @lua.close_thread with from being None instead.")
pub extern "c" fn reset_thread(state : State, from : State) -> Int = "lua_resetthread"
///|
extern "c" fn lua_atpanic(state : State, panic_fn : CFunction) -> CFunction = "lua_atpanic"
///|
/// Sets a new panic function and returns the old one (see
/// [§4.4](https://www.lua.org/manual/5.4/manual.html#4.4)).
pub fn at_panic(state : State, panic_fn : FuncRef[(State) -> Int]) -> CFunction {
lua_atpanic(state, c_function(panic_fn))
}
///|
/// Returns the version number of this core.
pub extern "c" fn version(state : State) -> Double = "lua_version"
///|
/// Converts the acceptable index idx into an equivalent absolute index
/// (that is, one that does not depend on the stack size).
pub extern "c" fn abs_index(state : State, index : Int) -> Int = "lua_absindex"
///|
/// Returns the index of the top element in the stack. Because indices start at
/// 1, this result is equal to the number of elements in the stack; in
/// particular, 0 means an empty stack.
pub extern "c" fn get_top(state : State) -> Int = "lua_gettop"
///|
/// Accepts any index, or 0, and sets the stack top to this index. If the new
/// top is greater than the old one, then the new elements are filled with nil.
/// If index is 0, then all stack elements are removed.
///
/// This function can run arbitrary code when removing an index marked as
/// to-be-closed from the stack.
pub extern "c" fn set_top(state : State, index : Int) = "lua_settop"
///|
/// Pops n elements from the stack.
pub fn pop(state : State, n : Int) -> Unit {
set_top(state, -n - 1)
}
///|
/// Pushes a copy of the element at the given index onto the stack.
pub extern "c" fn push_value(state : State, index : Int) = "lua_pushvalue"
///|
/// Rotates the stack elements between the valid index idx and the top of the
/// stack. The elements are rotated n positions in the direction of the top, for
/// a positive n, or -n positions in the direction of the bottom, for a negative
/// n. The absolute value of n must not be greater than the size of the slice
/// being rotated. This function cannot be called with a pseudo-index, because a
/// pseudo-index is not an actual stack position.
pub extern "c" fn rotate(state : State, index : Int, n : Int) = "lua_rotate"
///|
/// Copies the element at index from_index into the valid index to_index,
/// replacing the value at that position. Values at other positions are not
/// affected.
pub extern "c" fn copy(state : State, from_index : Int, to_index : Int) = "lua_copy"
///|
/// Ensures that the stack has space for at least n extra elements, that is,
/// that you can safely push up to n values into it. It returns false if it
/// cannot fulfill the request, either because it would cause the stack to be
/// greater than a fixed maximum size (typically at least several thousand
/// elements) or because it cannot allocate memory for the extra space. This
/// function never shrinks the stack; if the stack already has space for the
/// extra elements, it is left unchanged.
pub extern "c" fn check_stack(state : State, extra : Int) -> Bool = "lua_checkstack"
///|
/// Exchange values between different threads of the same state.
///
/// This function pops `n` values from the stack `from`, and pushes them onto
/// the stack `to`.
pub extern "c" fn xmove(from : State, to : State, n : Int) = "lua_xmove"
///|
/// Returns true if the value at the given index is a number or a string
/// convertible to a number, and false otherwise.
pub extern "c" fn is_number(state : State, index : Int) -> Bool = "lua_isnumber"
///|
/// Returns true if the value at the given index is a string or a number (which
/// is always convertible to a string), and false otherwise.
pub extern "c" fn is_string(state : State, index : Int) -> Bool = "lua_isstring"
///|
/// Returns true if the value at the given index is a C function, and false
/// otherwise.
pub extern "c" fn is_c_function(state : State, index : Int) -> Bool = "lua_iscfunction"
///|
/// Returns true if the value at the given index is an integer (that is, the
/// value is a number and is represented as an integer), and false otherwise.
pub extern "c" fn is_integer(state : State, index : Int) -> Bool = "lua_isinteger"
///|
/// Returns true if the value at the given index is a userdata (either full or
/// light), and false otherwise.
pub extern "c" fn is_userdata(state : State, index : Int) -> Bool = "lua_isuserdata"
///|
extern "c" fn lua_type(state : State, index : Int) -> Int = "lua_type"
///|
/// Returns the type of the value in the given valid index, or `None` for a
/// non-valid but acceptable index. The types returned by [`@lua.type_`](#type_)
/// are coded by the following enum variants: `Nil`, `Number`, `Boolean`,
/// `String`, `Table`, `Function`, `Userdata`, `Thread`, and `LightUserdata`.
pub fn type_(state : State, index : Int) -> Type? {
lua_type(state, index) |> Type::from_int()
}
///|
/// Returns true if the value at the given index is a function (either C or
/// Lua), and false otherwise.
pub fn is_function(state : State, index : Int) -> Bool {
type_(state, index) is Some(Function)
}
///|
/// Returns true if the value at the given index is a table, and false
/// otherwise.
pub fn is_table(state : State, index : Int) -> Bool {
type_(state, index) is Some(Table)
}
///|
/// Returns true if the value at the given index is a light userdata, and false
/// otherwise.
pub fn is_light_userdata(state : State, index : Int) -> Bool {
type_(state, index) is Some(LightUserdata)
}
///|
/// Returns true if the value at the given index is **nil**, and false otherwise.
pub fn is_nil(state : State, index : Int) -> Bool {
type_(state, index) is Some(Nil)
}
///|
/// Returns true if the value at the given index is a boolean, and false
/// otherwise.
pub fn is_boolean(state : State, index : Int) -> Bool {
type_(state, index) is Some(Boolean)
}
///|
/// Returns true if the value at the given index is a thread, and false
/// otherwise.
pub fn is_thread(state : State, index : Int) -> Bool {
type_(state, index) is Some(Thread)
}
///|
/// Returns true if the given index is not valid, and false otherwise.
pub fn is_none(state : State, index : Int) -> Bool {
type_(state, index) is None
}
///|
/// Returns true if the given index is not valid or if the value at this index
/// is **nil**, and false otherwise.
pub fn is_none_or_nil(state : State, index : Int) -> Bool {
type_(state, index) is (None | Some(Nil))
}
///|
extern "c" fn lua_typename(state : State, type_ : Int) -> @c.Pointer[Byte] = "lua_typename"
///|
/// Returns the name of the type encoded by the value tp, which must be one the
/// values returned by [`@lua.type_`](#type_).
pub fn type_name(state : State, type_ : Type?) -> Bytes {
let s = lua_typename(state.0, Type::to_int(type_))
let b = @buffer.new()
for i = 0; s[i.to_uint64()] != 0; i = i + 1 {
b.write_byte(s[i.to_uint64()])
}
b.contents()
}
///|
/// Converts the Lua value at the given index to the C type
/// [`@lua.Number`](#Number) (see [`@lua.Number`](#Number)). The Lua value must
/// be a number or a string convertible to a number (see
/// [§3.4.3](https://www.lua.org/manual/5.4/manual.html#3.4.3)); otherwise,
/// [`@lua.to_number_x`](#to_number_x) returns 0.
///
/// `is_num` is assigned a boolean value that indicates whether the operation
/// succeeded.
#borrow(is_num)
pub extern "c" fn to_number_x(
state : State,
idx : Int,
is_num : Ref[Bool],
) -> Double = "lua_tonumberx"
///|
extern "c" fn lua_tonumber(
state : State,
idx : Int,
is_num : @c.Pointer[Bool],
) -> Double = "lua_tonumberx"
///|
/// Equivalent to [`@lua.to_number_x`](#to_number_x) with `is_num` ignored.
pub fn to_number(state : State, index : Int) -> Double {
lua_tonumber(state, index, @c.Pointer::null())
}
///|
/// Converts the Lua value at the given index to the signed integral type
/// `Integer`. The Lua value must be an integer, or a number or string
/// convertible to an integer (see
/// [§3.4.3](https://www.lua.org/manual/5.4/manual.html#3.4.3)); otherwise,
/// [`@lua.to_integer_x`](#to_integer_x) returns 0.
///
/// `is_num` is assigned a boolean value that indicates whether the operation
/// succeeded.
#borrow(is_num)
pub extern "c" fn to_integer_x(
state : State,
index : Int,
is_num : Ref[Bool],
) -> Int64 = "lua_tointegerx"
///|
extern "c" fn lua_tointeger(
state : State,
idx : Int,
is_num : @c.Pointer[Bool],
) -> Int64 = "lua_tointegerx"
///|
/// Equivalent to [`@lua.to_integer_x`](#to_integer_x) with `is_num` is not
/// used.
pub fn to_integer(state : State, index : Int) -> Int64 {
lua_tointeger(state, index, @c.Pointer::null())
}
///|
/// Converts the Lua value at the given index to a C boolean value (false or
/// true). Like all tests in Lua, [`@lua.to_boolean`](#boolean) returns true for
/// any Lua value different from **false** and **nil**; otherwise it returns
/// **false**. (If you want to accept only actual boolean values, use
/// [`@lua.is_boolean`](#is_boolean) to test the value's type.)
pub extern "c" fn to_boolean(state : State, index : Int) -> Bool = "lua_toboolean"
///|
#borrow(len)
extern "c" fn lua_tolstring(
state : State,
idx : Int,
len : Ref[Int],
) -> @c.Pointer[Byte] = "lua_tolstring"
///|
/// Converts the Lua value at the given index to a C string. The Lua value must
/// be a string or a number; otherwise, the function returns `None`. If the
/// value is a number, then [`@lua.to_string`](#to_string) also changes the
/// actual value in the stack to a string. (This change confuses `next` when
/// [`@lua.to_string`](#to_string) is applied to keys during a table traversal.)
///
/// [`@lua.to_string`](#to_string) returns a pointer to a string inside the Lua
/// state (see [§4.1.3](https://www.lua.org/manual/5.4/manual.html#4.1.3)). This
/// string always has a zero ('\0') after its last character (as in C), but can
/// contain other zeros in its body.
///
/// This function can raise memory errors only when converting a number to a
/// string (as then it may create a new string).
pub fn to_string(state : State, index : Int) -> Bytes? {
let length : Ref[Int] = Ref::new(0)
let string = lua_tolstring(state.0, index, length)
if string.is_null() {
return None
}
let buffer = @buffer.new()
for i in 0.. UInt64 = "lua_rawlen"
///|
extern "c" fn lua_to_c_function(state : State, idx : Int) -> CFunction = "lua_tocfunction"
///|
fn CFunction::is_null(state : CFunction, null : @c.Null) -> Bool = "%refeq"
///|
/// Converts a value at the given index to a C function. That value must be a C
/// function; otherwise, returns `None`.
pub fn to_c_function(state : State, index : Int) -> CFunction? {
let f = lua_to_c_function(state, index)
if f.is_null(@c.null) {
Some(f)
} else {
None
}
}
///|
extern "c" fn lua_touserdata(state : State, idx : Int) -> @c.Pointer[Unit] = "lua_touserdata"
///|
/// If the value at the given index is a full userdata, returns its memory-block
/// address. If the value is a light userdata, returns its value (a pointer).
/// Otherwise, returns NULL.
pub fn[T] to_userdata(state : State, index : Int) -> @c.Pointer[T] {
let p = lua_touserdata(state.0, index)
p.cast()
}
///|
extern "c" fn lua_tothread(state : State, idx : Int) -> State = "lua_tothread"
///|
/// Converts the value at the given index to a Lua thread (represented as
/// `State`). This value must be a thread; otherwise, the function returns
/// `None`.
pub fn to_thread(state : State, index : Int) -> State? {
let thread = lua_tothread(state.0, index)
if thread.0.is_null() {
None
} else {
Some(thread)
}
}
///|
/// Converts the value at the given index to a generic C pointer
/// (`@c.Pointer[Unit]`). The value can be a userdata, a table, a thread, a
/// string, or a function; otherwise, lua_topointer returns NULL. Different
/// objects will give different pointers. There is no way to convert the pointer
/// back to its original value.
///
/// Typically this function is used only for hashing and debug information.
pub extern "c" fn to_pointer(state : State, idx : Int) -> @c.Pointer[Unit] = "lua_topointer"
///|
pub(all) enum ArithOp {
/// performs addition (+)
Add = 0
/// performs subtraction (-)
Sub = 1
/// performs multiplication (*)
Mul = 2
/// performs modulo (%)
Mod = 3
/// performs exponentiation (^)
Pow = 4
/// performs float division (/)
Div = 5
/// performs floor division (//)
IDiv = 6
/// performs bitwise AND (&)
BAnd = 7
/// performs bitwise OR (|)
BOr = 8
/// performs bitwise exclusive OR (~)
BXor = 9
/// performs left shift (<<)
Shl = 10
/// performs right shift (>>)
Shr = 11
/// performs mathematical negation (unary -)
Unm = 12
/// performs bitwise NOT (~)
BNot = 13
}
///|
/// Performs an arithmetic or bitwise operation over the two values (or one, in
/// the case of negations) at the top of the stack, with the value on the top
/// being the second operand, pops these values, and pushes the result of the
/// operation. The function follows the semantics of the corresponding Lua
/// operator (that is, it may call metamethods).
pub extern "c" fn arith(state : State, op : ArithOp) = "lua_arith"
///|
pub(all) enum CompareOp {
/// Compares for equality (==)
Eq = 0
/// Compares for less than (<)
Lt = 1
/// Compares for less than or equal (<=)
Le = 2
}
///|
/// Returns true if the two values in indices index1 and index2 are primitively
/// equal (that is, equal without calling the `__eq` metamethod). Otherwise
/// returns false. Also returns false if any of the indices are not valid.
pub extern "c" fn raw_equal(state : State, idx1 : Int, idx2 : Int) -> Bool = "lua_rawequal"
///|
/// Compares two Lua values. Returns true if the value at index index1 satisfies
/// op when compared with the value at index index2, following the semantics of
/// the corresponding Lua operator (that is, it may call metamethods). Otherwise
/// returns false. Also returns false if any of the indices is not valid.
///
/// The value of `op` must be one of [`@lua.CompareOp`](#CompareOp):
///
/// - `CompareOp::Eq`: compares for equality (==)
/// - `CompareOp::Lt`: compares for less than (<)
/// - `CompareOp::Le`: compares for less than or equal (<=)
pub extern "c" fn compare(
state : State,
idx1 : Int,
idx2 : Int,
op : CompareOp,
) -> Bool = "lua_compare"
///|
/// Pushes a nil value onto the stack.
pub extern "c" fn push_nil(state : State) = "lua_pushnil"
///|
/// Pushes a float with value n onto the stack.
pub extern "c" fn push_number(state : State, n : Double) = "lua_pushnumber"
///|
/// Pushes an integer with value `n` onto the stack.
pub extern "c" fn push_integer(state : State, n : Int64) = "lua_pushinteger"
///|
#borrow(buf)
extern "c" fn lua_pushlstring(
state : State,
buf : Bytes,
off : Int,
len : Int,
) -> @c.Pointer[Byte] = "moonbit_lua_pushlstring"
///|
/// Pushes the `BytesView` pointed to by `s` onto the stack. Lua will make or
/// reuse an internal copy of the given string, so the memory at `s` can be
/// freed or reused immediately after the function returns. The `BytesView` can
/// contain any binary data, including embedded zeros.
///
/// Returns a pointer to the internal copy of the string (see §4.1.3).
pub fn push_string(state : State, s : BytesView) -> @c.Pointer[Byte] {
lua_pushlstring(state, s.data(), s.start_offset(), s.length())
}
///|
/// Pushes a new C closure onto the stack. This function receives a pointer to a
/// C function and pushes onto the stack a Lua value of type function that, when
/// called, invokes the corresponding C function. The parameter `n` tells how
/// many upvalues this function will have (see
/// [§4.2](https://www.lua.org/manual/5.4/manual.html#4.2)).
///
/// Any function to be callable by Lua must follow the correct protocol to
/// receive its parameters and return its results (see
/// [`@lua.CFunction`](#CFunction)).
///
/// When a C function is created, it is possible to associate some values with
/// it, the so called upvalues; these upvalues are then accessible to the
/// function whenever it is called. This association is called a C closure (see
/// [§4.2](https://www.lua.org/manual/5.4/manual.html#4.2)). To create a C
/// closure, first the initial values for its upvalues must be pushed onto the
/// stack. (When there are multiple upvalues, the first value is pushed first.)
/// Then [`@lua.push_c_closure`](#push_c_closure) is called to create and push
/// the C function onto the stack, with the argument `n` telling how many values
/// will be associated with the function.
/// [`@lua.push_c_closure`](#push_c_closure) also pops these values from the
/// stack.
///
/// The maximum value for `n` is 255.
///
/// When `n` is zero, this function creates a light C function, which is just a
/// pointer to the C function. In that case, it never raises a memory error.
pub extern "c" fn push_c_closure(state : State, f : CFunction, n : Int) = "lua_pushcclosure"
///|
/// Pushes a C function onto the stack. This function is equivalent to
/// [`@lua.push_c_closure`](#push_c_closure) with no upvalues.
pub fn push_c_function(state : State, f : CFunction) -> Unit {
push_c_closure(state, f, 0)
}
///|
/// Sets the C function `f` as the new value of global name.
pub fn register(state : State, name : Bytes, f : CFunction) -> Unit {
push_c_function(state, f)
set_global(state, name)
}
///|
/// Pushes a boolean value with value `b` onto the stack.
pub extern "c" fn push_boolean(state : State, b : Bool) = "lua_pushboolean"
///|
extern "c" fn lua_pushlightuserdata(state : State, p : @c.Pointer[Unit]) = "lua_pushlightuserdata"
///|
/// Pushes a light userdata onto the stack.
///
/// Userdata represent C values in Lua. A _light userdata_ represents a pointer,
/// a `void *`. It is a value (like a number): you do not create it, it has no
/// individual metatable, and it is not collected (as it was never created). A
/// light userdata is equal to "any" light userdata with the same C address.
pub fn[T] push_light_userdata(state : State, p : @c.Pointer[T]) -> Unit {
lua_pushlightuserdata(state, p.cast())
}
///|
/// Pushes the thread represented by `thread` onto the stack. Returns true if
/// this thread is the main thread of its state.
pub extern "c" fn push_thread(state : State, thread : State) -> Bool = "lua_pushthread"
///|
/// Pushes onto the stack the value of the global name. Returns the type of that
/// value.
#borrow(name)
pub extern "c" fn get_global(state : State, name : Bytes) -> Type = "lua_getglobal"
///|
/// Pushes onto the stack the value `t[k]`, where `t` is the value at the given
/// index and `k` is the value at the top of the stack.
///
/// This function pops the key from the stack, pushing the resulting value in
/// its place. As in Lua, this function may trigger a metamethod for the "index"
/// event (see [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
///
/// Returns the type of the pushed value.
pub extern "c" fn get_table(state : State, index : Int) -> Type = "lua_gettable"
///|
/// Pushes onto the stack the value `t[k]`, where `t` is the value at the given
/// index. As in Lua, this function may trigger a metamethod for the "index"
/// event (see [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
///
/// Returns the type of the pushed value.
#borrow(k)
pub extern "c" fn get_field(state : State, index : Int, k : Bytes) -> Type = "lua_getfield"
///|
/// Pushes onto the stack the value t[i], where t is the value at the given
/// index. As in Lua, this function may trigger a metamethod for the "index"
/// event (see [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
///
/// Returns the type of the pushed value.
pub extern "c" fn get_i(state : State, index : Int, n : Int64) -> Type = "lua_geti"
///|
/// Similar to [`@lua.get_table`](#get_table), but does a raw access (i.e.,
/// without metamethods). The value at `index` must be a table.
pub extern "c" fn raw_get(state : State, index : Int) -> Type = "lua_rawget"
///|
/// Pushes onto the stack the value `t[n]`, where `t` is the table at the given
/// index. The access is raw, that is, it does not use the `__index` metavalue.
///
/// Returns the type of the pushed value.
pub extern "c" fn raw_get_i(state : State, index : Int, n : Int64) -> Type = "lua_rawgeti"
///|
/// Pushes onto the stack the value `t[k]`, where `t` is the table at the given
/// index and `k` is the pointer `p` represented as a light userdata. The access
/// is raw; that is, it does not use the `__index` metavalue.
///
/// Returns the type of the pushed value.
pub extern "c" fn raw_get_p(
state : State,
index : Int,
p : @c.Pointer[Unit],
) -> Type = "lua_rawgetp"
///|
/// Creates a new empty table and pushes it onto the stack. Parameter narr is a
/// hint for how many elements the table will have as a sequence; parameter nrec
/// is a hint for how many other elements the table will have. Lua may use these
/// hints to preallocate memory for the new table. This preallocation is useful
/// for performance when you know in advance how many elements the table will
/// have. Otherwise you can use the function [`@lua.new_table`](#new_table).
pub extern "c" fn create_table(state : State, narr : Int, nrec : Int) = "lua_createtable"
///|
/// Creates a new empty table and pushes it onto the stack. It is equivalent to
/// `@lua.create_table(lua, 0, 0)`.
pub fn new_table(state : State) -> Unit {
create_table(state, 0, 0)
}
///|
/// This function creates and pushes on the stack a new full userdata, with
/// `nuvalue` associated Lua values, called user values, plus an associated
/// block of raw memory with size bytes. (The user values can be set and read
/// with the functions [`@lua.set_i_user_value`](#set_i_user_value) and
/// [`@lua.get_i_user_value`](#get_i_user_value).)
///
/// The function returns the address of the block of memory. Lua ensures that
/// this address is valid as long as the corresponding userdata is alive (see
/// [§2.5](https://www.lua.org/manual/5.4/manual.html#2.5)). Moreover, if the
/// userdata is marked for finalization (see
/// [§2.5.3](https://www.lua.org/manual/5.4/manual.html#2.5.3)), its address is
/// valid at least until the call to its finalizer.
pub extern "c" fn new_userdata_uv(
state : State,
size : UInt64,
nuvalue : Int,
) -> @c.Pointer[Unit] = "lua_newuserdatauv"
///|
/// If the value at the given index has a metatable, the function pushes that
/// metatable onto the stack and returns true. Otherwise, the function returns
/// false and pushes nothing on the stack.
pub extern "c" fn get_metatable(state : State, objindex : Int) -> Bool = "lua_getmetatable"
///|
extern "c" fn lua_getiuservalue(state : State, idx : Int, n : Int) -> Int = "lua_getiuservalue"
///|
/// Pushes onto the stack the n-th user value associated with the full userdata
/// at the given index and returns the type of the pushed value.
///
/// If the userdata does not have that value, pushes nil and returns `None`.
pub fn get_i_user_value(state : State, idx : Int, n : Int) -> Type? {
lua_getiuservalue(state, idx, n) |> Type::from_int()
}
///|
/// Pops a value from the stack and sets it as the new value of global name.
#borrow(name)
pub extern "c" fn set_global(state : State, name : Bytes) = "lua_setglobal"
///|
/// Does the equivalent to `t[k] = v`, where `t` is the value at the given
/// index, `v` is the value on the top of the stack, and `k` is the value just
/// below the top.
///
/// This function pops both the key and the value from the stack. As in Lua,
/// this function may trigger a metamethod for the "newindex" event (see
/// [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
pub extern "c" fn set_table(state : State, index : Int) = "lua_settable"
///|
/// Does the equivalent to `t[k] = v`, where `t` is the value at the given
/// index and `v` is the value on the top of the stack.
///
/// This function pops the value from the stack. As in Lua, this function may
/// trigger a metamethod for the "newindex" event (see
/// [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
#borrow(k)
pub extern "c" fn set_field(state : State, index : Int, k : Bytes) = "lua_setfield"
///|
/// Does the equivalent to `t[n] = v`, where `t` is the value at the given index
/// and `v` is the value on the top of the stack.
///
/// This function pops the value from the stack. As in Lua, this function may
/// trigger a metamethod for the "newindex" event (see
/// [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)).
pub extern "c" fn set_i(state : State, index : Int, n : Int64) = "lua_seti"
///|
/// Similar to [`@lua.set_table`](#set_table), but does a raw assignment (i.e.,
/// without metamethods). The value at index must be a table.
pub extern "c" fn raw_set(state : State, index : Int) = "lua_rawset"
///|
/// Does the equivalent of `t[i] = v`, where `t` is the table at the given index
/// and `v` is the value on the top of the stack.
///
/// This function pops the value from the stack. The assignment is raw, that is,
/// it does not use the `__newindex` metavalue.
pub extern "c" fn raw_set_i(state : State, index : Int, n : Int64) = "lua_rawseti"
///|
/// Does the equivalent of `t[p] = v`, where `t` is the table at the given
/// index, `p` is encoded as a light userdata, and `v` is the value on the top
/// of the stack.
///
/// This function pops the value from the stack. The assignment is raw, that is,
/// it does not use the `__newindex` metavalue.
pub extern "c" fn raw_set_p(state : State, index : Int, p : @c.Pointer[Unit]) = "lua_rawsetp"
///|
/// Pops a table or **nil** from the stack and sets that value as the new
/// metatable for the value at the given index. (**nil** means no metatable.)
pub extern "c" fn set_metatable(state : State, objindex : Int) = "lua_setmetatable"
///|
/// Pops a value from the stack and sets it as the new n-th user value
/// associated to the full userdata at the given index. Returns false if the
/// userdata does not have that value.
pub extern "c" fn set_i_user_value(state : State, idx : Int, n : Int) -> Bool = "lua_setiuservalue"
///|
extern "c" fn lua_callk(
state : State,
nargs : Int,
nresults : Int,
ctx : (State, Int) -> Int,
k : FuncRef[(State, Int, (State, Int) -> Int) -> Int],
) = "lua_callk"
///|
/// This function behaves exactly like [`@lua.call`](#call), but allows the
/// called function to yield (see
/// [§4.5](https://www.lua.org/manual/5.4/manual.html#4.5)).
pub fn callk(
state : State,
nargs : Int,
nresults : Int,
k : (State, Int) -> Int,
) -> Unit {
lua_callk(state, nargs, nresults, k, (l, status, ctx) => ctx(l, status))
}
///|
extern "c" fn lua_call(
state : State,
nargs : Int,
nresults : Int,
ctx : @c.Pointer[Unit],
k : @c.Pointer[Unit],
) = "lua_callk"
///|
/// Calls a function. Like regular Lua calls, [`@lua.call`](#call) respects the
/// `__call` metamethod. So, here the word "function" means any callable value.
///
/// To do a call you must use the following protocol: first, the function to be
/// called is pushed onto the stack; then, the arguments to the call are pushed
/// in direct order; that is, the first argument is pushed first. Finally you
/// call [`@lua.call`](#call); nargs is the number of arguments that you pushed
/// onto the stack. When the function returns, all arguments and the function
/// value are popped and the call results are pushed onto the stack. The number
/// of results is adjusted to `nresults`, unless `nresults` is
/// [`@lua.MultRet`](#MultRet). In this case, all results from the function are
/// pushed; Lua takes care that the returned values fit into the stack space,
/// but it does not ensure any extra space in the stack. The function results
/// are pushed onto the stack in direct order (the first result is pushed
/// first), so that after the call the last result is on the top of the stack.
///
/// Any error while calling and running the function is propagated upwards (with
/// a `longjmp`).
///
/// The following example shows how the host program can do the equivalent to
/// this Lua code:
///
/// a = f("how", t.x, 14)
///
/// Here it is in MoonBit:
///
/// ```moonbit
/// @lua.get_global(lua, "f"); // function to be called
/// @lua.push_literal(lua, "how"); // 1st argument
/// @lua.get_global(lua, "t"); // table to be indexed
/// @lua.get_field(lua, -1, "x"); // push result of t.x (2nd arg)
/// @lua.remove(lua, -2); // remove 't' from the stack
/// @lua.push_integer(lua, 14); // 3rd argument
/// @lua.call(lua, 3, 1); // call 'f' with 3 arguments and 1 result
/// @lua.set_global(lua, "a"); // set global 'a'
/// ```
///
/// Note that the code above is _balanced_: at its end, the stack is back to its
/// original configuration. This is considered good programming practice.
pub fn call(state : State, nargs : Int, nresults : Int) -> Unit {
lua_call(state, nargs, nresults, @c.Pointer::null(), @c.Pointer::null())
}
///|
extern "c" fn lua_pcallk(
state : State,
nargs : Int,
nresults : Int,
errfunc : Int,
ctx : (State, Int) -> Int,
k : FuncRef[(State, Int, (State, Int) -> Int) -> Int],
) -> Int = "lua_pcallk"
///|
/// This function behaves exactly like lua_pcall, except that it allows the
/// called function to yield (see
/// [§4.5](https://www.lua.org/manual/5.4/manual.html#4.5)).
pub fn pcallk(
state : State,
nargs : Int,
nresults : Int,
errfunc : Int,
k : (State, Int) -> Int,
) -> Int {
lua_pcallk(state, nargs, nresults, errfunc, k, (l, status, ctx) => ctx(
l, status,
))
}
///|
extern "c" fn lua_pcall(
state : State,
nargs : Int,
nresults : Int,
errfunc : Int,
ctx : @c.Pointer[Unit],
k : @c.Pointer[Unit],
) -> Int = "lua_pcallk"
///|
/// Calls a function (or a callable object) in protected mode.
///
/// Both `nargs` and `nresults` have the same meaning as in
/// [`@lua.call`](#call). If there are no errors during the call,
/// [`@lua.pcall`](#pcall) behaves exactly like [`@lua.call`](#call). However,
/// if there is any error, [`@lua.pcall`](#pcall) catches it, pushes a single
/// value on the stack (the error object), and returns an error code. Like
/// [`@lua.call`](#call), [`@lua.pcall`](#pcall) always removes the function and
/// its arguments from the stack.
///
/// If `msgh` is 0, then the error object returned on the stack is exactly the
/// original error object. Otherwise, `msgh` is the stack index of a message
/// handler. (This index cannot be a pseudo-index.) In case of runtime errors,
/// this handler will be called with the error object and its return value will
/// be the object returned on the stack by [`@lua.pcall`](#pcall).
///
/// Typically, the message handler is used to add more debug information to the
/// error object, such as a stack traceback. Such information cannot be gathered
/// after the return of [`@lua.pcall`](#pcall), since by then the stack has
/// unwound.
///
/// The [`@lua.pcall`](#pcall) function returns one of the following status codes:
/// [`@lua.Ok`](#Ok), [`@lua.ErrRun`](#ErrRun), [`@lua.ErrMem`](#ErrMem), or
/// [`@lua.ErrErr`](#ErrErr).
pub fn pcall(state : State, nargs : Int, nresults : Int, msgh : Int) -> Int {
lua_pcall(
state,
nargs,
nresults,
msgh,
@c.Pointer::null(),
@c.Pointer::null(),
)
}
///|
#borrow(chunkname, mode)
extern "c" fn lua_load(
state : State,
reader : FuncRef[(State, Reader, @c.Pointer[UInt64]) -> @c.Pointer[Byte]],
data : Reader,
chunkname : Bytes,
mode : Bytes,
) -> Int = "lua_load"
///|
/// Loads a Lua chunk without running it. If there are no errors,
/// [`@lua.load`](#load) pushes the compiled chunk as a Lua function on top of
/// the stack. Otherwise, it pushes an error message.
///
/// The [`@lua.load`](#load) function uses a user-supplied reader function to
/// read the chunk (see [`@lua.Reader`](#Reader)). The data argument is an
/// opaque value passed to the reader function.
///
/// The `chunkname` argument gives a name to the chunk, which is used for error
/// messages and in debug information (see
/// [§4.7](https://www.lua.org/manual/5.4/manual.html#4.7)).
///
/// [`@lua.load`](#load) automatically detects whether the chunk is text or
/// binary and loads it accordingly (see program `luac`). The string mode works
/// as in function load, with the addition that a `None` value is equivalent to
/// the string `"bt"`.
///
/// [`@lua.load`](#load) uses the stack internally, so the reader function must
/// always leave the stack unmodified when returning.
///
/// [`@lua.load`](#load) can return [`@lua.Ok`](#Ok),
/// [`@lua.ErrSyntax`](#ErrSyntax), or [`@lua.ErrMem`](#ErrMem). The function
/// may also return other values corresponding to errors raised by the read
/// function (see [§4.4.1](https://www.lua.org/manual/5.4/manual.html#4.4.1)).
///
/// If the resulting function has upvalues, its first upvalue is set to the
/// value of the global environment stored at index
/// [`@lua.RidxGlobals`](#RidxGlobals) in the registry
/// (see [§4.3](https://www.lua.org/manual/5.4/manual.html#4.3)). When
/// loading main chunks, this upvalue will be the `_ENV` variable (see
/// [§2.2](https://www.lua.org/manual/5.4/manual.html#2.2)). Other upvalues are
/// initialized with **nil**.
pub fn load(
state : State,
reader : Reader,
chunkname : Bytes,
mode? : Bytes = "bt",
) -> Int {
lua_load(state, (l, r, size) => r(l, size), reader, chunkname, mode)
}
///|
extern "c" fn lua_dump(
state : State,
writer : FuncRef[(State, @c.Pointer[Unit], UInt64, Writer) -> Int],
data : Writer,
strip : Bool,
) -> Int = "lua_dump"
///|
/// Dumps a function as a binary chunk. Receives a Lua function on the top of
/// the stack and produces a binary chunk that, if loaded again, results in a
/// function equivalent to the one dumped. As it produces parts of the chunk,
/// [`@lua.dump`](#dump) calls function writer (see [`@lua.Writer`](#Writer))
/// with the given data to write them.
///
/// If `strip` is true, the binary representation may not include all debug
/// information about the function, to save space.
///
/// The value returned is the error code returned by the last call to the
/// writer; 0 means no errors.
///
/// This function does not pop the Lua function from the stack.
pub fn dump(state : State, writer : Writer, strip : Bool) -> Int {
lua_dump(state, (l, p, sz, w) => w(l, p, sz), writer, strip)
}
///|
extern "c" fn lua_yieldk(
state : State,
nresults : Int,
ctx : (State, Int) -> Int,
k : FuncRef[(State, Int, (State, Int) -> Int) -> Int],
) -> Int = "lua_yieldk"
///|
/// Yields a coroutine (thread).
///
/// When a C function calls [`@lua.yieldk`](#yieldk), the running coroutine
/// suspends its execution, and the call to [`@lua.resume_`](#resume_) that
/// started this coroutine returns. The parameter `nresults` is the number of
/// values from the stack that will be passed as results to
/// [`@lua.resume_`](#resume_).
///
/// When the coroutine is resumed again, Lua calls the given continuation
/// function `k` to continue the execution of the C function that yielded (see
/// [§4.5](https://www.lua.org/manual/5.4/manual.html#4.5)). This continuation
/// function receives the same stack from the previous function, with the `n`
/// results removed and replaced by the arguments passed to
/// [`@lua.resume_`](#resume_).
///
/// Usually, this function does not return; when the coroutine eventually
/// resumes, it continues executing the continuation function. However, there is
/// one special case, which is when this function is called from inside a line
/// or a count hook (see
/// [§4.7](https://www.lua.org/manual/5.4/manual.html#4.7)). In that case,
/// [`@lua.yieldk`](#yieldk) should be called with no continuation (probably in
/// the form of [`@lua.yield`](#yield_)) and no results, and the hook should
/// return immediately after the call. Lua will yield and, when the coroutine
/// resumes again, it will continue the normal execution of the (Lua) function
/// that triggered the hook.
///
/// This function can raise an error if it is called from a thread with a
/// pending C call with no continuation function
/// (what is called a C-call boundary), or it is called from a thread that is
/// not running inside a resume (typically the main thread).
pub fn yieldk(state : State, nresults : Int, k : (State, Int) -> Int) -> Int {
lua_yieldk(state, nresults, k, (l, status, ctx) => ctx(l, status))
}
///|
extern "c" fn lua_yield(
state : State,
nresults : Int,
ctx : @c.Pointer[Unit],
k : @c.Pointer[Unit],
) -> Int = "lua_yieldk"
///|
/// This function is equivalent to [`@lua.yieldk`](#yieldk), but it has no
/// continuation (see [§4.5](https://www.lua.org/manual/5.4/manual.html#4.5)).
/// Therefore, when the thread resumes, it continues the function that called
/// the function calling [`@lua.yield_`](#yield_). To avoid surprises, this
/// function should be called only in a tail call.
pub fn yield_(state : State, nresults : Int) -> Int {
lua_yield(state, nresults, @c.Pointer::null(), @c.Pointer::null())
}
///|
#borrow(nresults)
extern "c" fn lua_resume(
state : State,
from : State,
narg : Int,
nresults : Ref[Int],
) -> Int = "lua_resume"
///|
/// Starts and resumes a coroutine in the given thread `state`.
///
/// To start a coroutine, you push the main function plus any arguments onto the
/// empty stack of the thread. then you call [`@lua.resume_`](#resume_), with
/// `nargs` being the number of arguments. This call returns when the coroutine
/// suspends or finishes its execution. When it returns, `*nresults` is updated
/// and the top of the stack contains the `*nresults` values passed to
/// [`@lua.yield`](#yield_) or returned by the body function.
/// [`@lua.resume_`](#resume_) returns [`@lua.Yield`](#Yield) if the coroutine
/// yields, [`@lua.Ok`](#Ok) if the coroutine finishes its execution without
/// errors, or an error code in case of errors (see
/// [§4.4.1](https://www.lua.org/manual/5.4/manual.html#4.4.1)). In case of
/// errors, the error object is on the top of the stack.
///
/// To resume a coroutine, you remove the `*nresults` yielded values from its
/// stack, push the values to be passed as results from yield, and then call
/// [`@lua.resume_`](#resume_).
///
/// The parameter `from` represents the coroutine that is resuming `state`. If
/// there is no such coroutine, this parameter can be `None`.
pub fn resume_(
state : State,
from? : State,
nargs : Int,
nresults : Ref[Int],
) -> Int {
if from is Some(from) {
lua_resume(state, from, nargs, nresults)
} else {
lua_resume(state, @c.Pointer::null(), nargs, nresults)
}
}
///|
/// Returns the status of the thread L.
///
/// The status can be [`@lua.Ok`](#Ok) for a normal thread, an error code if the
/// thread finished the execution of a [`@lua.resume_`](#resume_) with an error,
/// or [`@lua.Yield`](#Yield) if the thread is suspended.
///
/// You can call functions only in threads with status [`@lua.Ok`](#Ok). You can
/// resume threads with status [`@lua.Ok`](#Ok) (to start a new coroutine) or
/// [`@lua.Yield`](#Yield) (to resume a coroutine).
pub extern "c" fn status(state : State) -> Int = "lua_status"
///|
/// Returns true if the given coroutine can yield, and false otherwise.
pub extern "c" fn is_yieldable(state : State) -> Bool = "lua_isyieldable"
///|
extern "c" fn lua_setwarnf(
state : State,
f : FuncRef[(WarnFunction, @c.Pointer[Byte], Bool) -> Unit],
ud : WarnFunction,
) = "lua_setwarnf"
///|
/// Sets the warning function to be used by Lua to emit warnings (see
/// [`@lua.WarnFunction`](#WarnFunction)).
pub fn set_warn_f(state : State, f : WarnFunction) -> Unit {
lua_setwarnf(
state,
(ud, msg, to_cont) => {
let len = @string.strlen(msg)
let buf = FixedArray::make(len.to_int(), b'\x00')
@memory.memcpy(buf, msg, len)
ud(buf.unsafe_reinterpret_as_bytes(), to_cont)
},
f,
)
}
///|
/// Emits a warning with the given message. A message in a call with to_cont
/// true should be continued in another call to this function.
///
/// See [warn](https://www.lua.org/manual/5.4/manual.html#pdf-warn) for more
/// details about warnings.
#borrow(msg)
pub extern "c" fn warning(state : State, msg : Bytes, to_cont~ : Bool) = "lua_warning"
///|
/// Performs a full garbage-collection cycle.
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_collect(state : State) = "moonbit_lua_gccollect"
///|
/// Stops the garbage collector.
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_stop(state : State) = "moonbit_lua_gcstop"
///|
/// Restarts the garbage collector.
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_restart(state : State) = "moonbit_lua_gcrestart"
///|
/// Returns the current amount of memory (in Kbytes) in use by Lua.
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_count(state : State) -> Int = "moonbit_lua_gccount"
///|
extern "c" fn lua_gccountb(state : State) -> Int = "moonbit_lua_gccountb"
///|
/// Returns the remainder of dividing the current amount of bytes of memory in
/// use by Lua by 1024.
///
/// This function should not be called by a finalizer.
pub fn gc_count_b(state : State) -> Int {
lua_gccountb(state)
}
///|
/// Performs an incremental step of garbage collection, corresponding to the
/// allocation of `step_size` Kbytes.
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_step(state : State, step_size : Int) = "moonbit_lua_gcstep"
///|
/// Returns a boolean that tells whether the collector is running (i.e., not stopped).
///
/// This function should not be called by a finalizer.
pub extern "c" fn gc_is_running(state : State) -> Bool = "moonbit_lua_gcisrunning"
///|
pub enum GcMode {
Gen = 10
Inc = 11
}
///|
const GcGen = 10
///|
const GcInc = 11
///|
extern "c" fn lua_gcinc(
state : State,
pause : Int,
step_mul : Int,
step_size : Int,
) -> Int = "moonbit_lua_gcinc"
///|
/// Changes the collector to incremental mode with the given parameters (see
/// [§2.5.1](https://www.lua.org/manual/5.4/manual.html#2.5.1)).
///
/// Returns the previous mode (`GcMode::Gen` or `GcMode::Inc`).
///
/// This function should not be called by a finalizer.
pub fn gc_inc(
state : State,
pause : Int,
step_mul : Int,
step_size : Int,
) -> GcMode {
match lua_gcinc(state, pause, step_mul, step_size) {
GcGen => GcMode::Gen
GcInc => GcMode::Inc
mode => abort("unexpected gc mode: \{mode}")
}
}
///|
extern "c" fn lua_gcgen(state : State, minor_mul : Int, major_mul : Int) -> Int = "moonbit_lua_gcgen"
///|
/// Changes the collector to generational mode with the given parameters (see
/// [§2.5.2](https://www.lua.org/manual/5.4/manual.html#2.5.2)).
///
/// Returns the previous mode (`GcMode::Gen` or `GcMode::Inc`).
///
/// This function should not be called by a finalizer.
pub fn gc_gen(state : State, minor_mul : Int, major_mul : Int) -> GcMode {
match lua_gcgen(state, minor_mul, major_mul) {
GcGen => GcMode::Gen
GcInc => GcMode::Inc
mode => abort("unexpected gc mode: \{mode}")
}
}
///|
extern "c" fn lua_error(state : State) = "lua_error"
///|
/// Raises a Lua error, using the value on the top of the stack as the error
/// object. This function does a long jump, and therefore never returns.
pub fn[X] error(state : State) -> X {
lua_error(state)
panic()
}
///|
/// Pops a key from the stack, and pushes a key–value pair from the table at the
/// given index, the "next" pair after the given key. If there are no more
/// elements in the table, then lua_next returns 0 and pushes nothing.
///
/// A typical table traversal looks like this:
///
/// ```moonbit check
/// let lua : State = ...
/// // table is in the stack at index 't'
/// lua.push_nil()
/// while lua.next(t) {
/// // uses 'key' (at index -2) and 'value' (at index -1)
/// let key_tn = lua.type_name(lua.type_(-2))
/// let val_tn = lua.type_name(lua.type_(-1))
/// println("\{key_tn} - \{val_tn}")
/// // removes 'value'; keeps 'key' for next iteration
/// lua.pop(1)
/// }
/// ```
pub extern "c" fn next(state : State, index : Int) -> Bool = "lua_next"
///|
/// Concatenates the `n` values at the top of the stack, pops them, and leaves
/// the result on the top. If `n` is 1, the result is the single value on the
/// stack (that is, the function does nothing); if `n` is 0, the result is the
/// empty string. Concatenation is performed following the usual semantics of
/// Lua (see [§3.4.6](https://www.lua.org/manual/5.4/manual.html#3.4.6)).
pub extern "c" fn concat(state : State, n : Int) = "lua_concat"
///|
/// Returns the length of the value at the given index. It is equivalent to the
/// '#' operator in Lua (see
/// [§3.4.7](https://www.lua.org/manual/5.4/manual.html#3.4.7)) and may trigger
/// a metamethod for the "length" event (see
/// [§2.4](https://www.lua.org/manual/5.4/manual.html#2.4)). The result is
/// pushed on the stack.
pub extern "c" fn len(state : State, index : Int) = "lua_len"
///|
/// Converts the zero-terminated string s to a number, pushes that number into
/// the stack, and returns the total size of the string, that is, its length
/// plus one. The conversion can result in an integer or a float, according to
/// the lexical conventions of Lua (see
/// [§3.1](https://www.lua.org/manual/5.4/manual.html#3.1)). The string may have
/// leading and trailing whitespaces and a sign. If the string is not a valid
/// numeral, returns 0 and pushes nothing. (Note that the result can be used as
/// a boolean, true if the conversion succeeds.)
#borrow(s)
pub extern "c" fn string_to_number(state : State, s : Bytes) -> UInt64 = "lua_stringtonumber"
///|
#borrow(ud)
extern "c" fn lua_getallocf(
state : State,
ud : Ref[Alloc],
) -> FuncRef[
(@c.Pointer[Unit], @c.Pointer[Unit], UInt64, UInt64) -> @c.Pointer[Unit],
] = "lua_getallocf"
///|
/// Returns the memory-allocation function of a given state.
pub fn get_alloc_f(state : State) -> Alloc {
let ud : Ref[Alloc] = Ref::new((_, _, _) => @c.Pointer::null())
ignore(lua_getallocf(state, ud))
ud.val
}
///|
extern "c" fn lua_setallocf(
state : State,
f : FuncRef[(Alloc, @c.Pointer[Unit], UInt64, UInt64) -> @c.Pointer[Unit]],
ud : Alloc,
) = "lua_setallocf"
///|
/// Changes the allocator function of a given state to `f`.
pub fn set_alloc_f(state : State, f : Alloc) -> Unit {
lua_setallocf(state, (f, ptr, osize, nsize) => f(ptr, osize, nsize), f)
}
///|
/// Marks the given index in the stack as a to-be-closed slot
/// (see [§3.3.8](https://www.lua.org/manual/5.4/manual.html#3.3.8)). Like
/// a to-be-closed variable in Lua, the value at that slot in the stack will be
/// closed when it goes out of scope. Here, in the context of a C function, to
/// go out of scope means that the running function returns to Lua, or there is
/// an error, or the slot is removed from the stack through lua_settop or
/// lua_pop, or there is a call to lua_closeslot. A slot marked as to-be-closed
/// should not be removed from the stack by any other function in the API except
/// lua_settop or lua_pop, unless previously deactivated by lua_closeslot.
///
/// This function raises an error if the value at the given slot neither has a
/// `__close` metamethod nor is a false value.
///
/// This function should not be called for an index that is equal to or below an
/// active to-be-closed slot.
///
/// Note that, both in case of errors and of a regular return, by the time the
/// `__close` metamethod runs, the C stack was already unwound, so that any
/// automatic C variable declared in the calling function (e.g., a buffer) will
/// be out of scope.
pub extern "c" fn to_close(state : State, idx : Int) = "lua_toclose"
///|
/// Close the to-be-closed slot at the given index and set its value to **nil**
/// The index must be the last index previously marked to be closed (see
/// [`@lua.to_close`](#to_close)) that is still active (that is, not closed
/// yet).
///
/// A `__close` metamethod cannot yield when called through this function.
///
/// (This function was introduced in release 5.4.3.)
pub extern "c" fn close_slot(state : State, idx : Int) = "lua_closeslot"
///|
/// Moves the top element into the given valid index, shifting up the elements
/// above this index to open space. This function cannot be called with a
/// pseudo-index, because a pseudo-index is not an actual stack position.
pub fn insert(state : State, index : Int) -> Unit {
rotate(state, index, 1)
}
///|
/// Removes the element at the given valid index, shifting down the elements
/// above this index to fill the gap. This function cannot be called with a
/// pseudo-index, because a pseudo-index is not an actual stack position.
pub fn remove(state : State, index : Int) -> Unit {
rotate(state, index, -1)
pop(state, 1)
}
///|
/// Moves the top element into the given valid index without shifting any
/// element (therefore replacing the value at that given index), and then pops
/// the top element.
pub fn replace(state : State, index : Int) -> Unit {
copy(state, -1, index)
pop(state, 1)
}
///|
pub(all) enum EventCode {
Call = 0
Ret = 1
Line = 2
Count = 3
TailCall = 4
}
///|
pub const HookCall = 0
///|
pub const HookRet = 1
///|
pub const HookLine = 2
///|
pub const HookCount = 3
///|
pub const HookTailCall = 4
///|
pub const MaskCall : Int = 1 << HookCall
///|
pub const MaskRet : Int = 1 << HookRet
///|
pub const MaskLine : Int = 1 << HookLine
///|
pub const MaskCount : Int = 1 << HookCount
///|
extern "c" fn lua_id_size() -> Int = "moonbit_lua_id_size"
///|
pub let id_size : Int = lua_id_size()
///|
/// A structure used to carry different pieces of information about a function
/// or an activation record. [`@lua.get_stack`](#get_stack) fills only the
/// private part of this structure, for later use. To fill the other fields of
/// [`@lua.Debug`](#Debug) with useful information, you must call
/// [`@lua.get_info`](#get_info) with an appropriate parameter. (Specifically,
/// to get a field, you must add the letter between parentheses in the field's
/// comment to the parameter what of [`@lua.get_info`](#get_info).)
pub(all) struct Debug(@c.Pointer[Unit])
///|
pub extern "c" fn Debug::sizeof() -> UInt64 = "moonbit_lua_sizeofdebug"
///|
pub extern "c" fn Debug::event(ar : Debug) -> Int = "moonbit_lua_debugevent"
///|
/// A reasonable name for the given function. Because functions in Lua are
/// first-class values, they do not have a fixed name: some functions can be
/// the value of multiple global variables, while others can be stored only in a
/// table field. The lua_getinfo function checks how the function was called to
/// find a suitable name. If it cannot find a name, then name is set to NULL.
pub extern "c" fn Debug::name(ar : Debug) -> @c.Pointer[Byte] = "moonbit_lua_debugname"
///|
/// Explains the `name` field. The value of `name_what` can be `"global"`,
/// `"local"`, `"method"`, `"field"`, `"upvalue"`, or `""` (the empty string),
/// according to how the function was called. (Lua uses the empty string when no
/// other option seems to apply.)
pub extern "c" fn Debug::name_what(ar : Debug) -> @c.Pointer[Byte] = "moonbit_lua_debugnamewhat"
///|
/// the string `"Lua"` if the function is a Lua function, `"C"` if it is a C
/// function, `"main"` if it is the main part of a chunk.
pub extern "c" fn Debug::what(ar : Debug) -> @c.Pointer[Byte] = "moonbit_lua_debugwhat"
///|
/// The source of the chunk that created the function. If `source` starts with a
/// `'@'`, it means that the function was defined in a file where the file name
/// follows the `'@'`. If `source` starts with a '=', the remainder of its
/// contents describes the `source` in a user-dependent manner. Otherwise, the
/// function was defined in a string where `source` is that string.
pub extern "c" fn Debug::source(ar : Debug) -> @c.Pointer[Byte] = "moonbit_lua_debugsource"
///|
/// The length of the string `source`.
pub extern "c" fn Debug::src_len(ar : Debug) -> UInt64 = "moonbit_lua_debugsrclen"
///|
/// The current line where the given function is executing. When no line
/// information is available, `current_line` returns set to -1.
pub extern "c" fn Debug::current_line(ar : Debug) -> Int = "moonbit_lua_debugcurrentline"
///|
/// The line number where the definition of the function starts.
pub extern "c" fn Debug::line_defined(ar : Debug) -> Int = "moonbit_lua_debuglinedefined"
///|
/// The line number where the definition of the function ends.
pub extern "c" fn Debug::last_line_defined(ar : Debug) -> Int = "moonbit_lua_debuglastlinedefined"
///|
/// The number of upvalues of the function.
pub extern "c" fn Debug::n_ups(ar : Debug) -> Int = "moonbit_lua_debugnups"
///|
/// The number of parameters of the function (always 0 for C functions).
pub extern "c" fn Debug::n_params(ar : Debug) -> Int = "moonbit_lua_debugnparams"
///|
/// True if the function is a variadic function (always true for C functions).
pub extern "c" fn Debug::is_var_arg(ar : Debug) -> Bool = "moonbit_lua_debugisvararg"
///|
/// True if this function invocation was called by a tail call. In this case,
/// the caller of this level is not in the stack.
pub extern "c" fn Debug::is_tail_call(ar : Debug) -> Bool = "moonbit_lua_debugistailcall"
///|
/// The index in the stack of the first value being "transferred", that is,
/// parameters in a call or return values in a return. (The other values are in
/// consecutive indices.) Using this index, you can access and modify these
/// values through [`@lua.get_local`](#get_local) and
/// [`@lua.set_local`](#set_local). This field is only meaningful during a call
/// hook, denoting the first parameter, or a return hook, denoting the first
/// value being returned. (For call hooks, this value is always 1.)
pub extern "c" fn Debug::f_transfer(ar : Debug) -> Int = "moonbit_lua_debugftransfer"
///|
/// The number of values being transferred (see `Debug::f_transfer`). (For calls of
/// Lua functions, this value is always equal to `n_params`.)
pub extern "c" fn Debug::n_transfer(ar : Debug) -> Int = "moonbit_lua_debugntransfer"
///|
/// A "printable" version of source, to be used in error messages.
pub extern "c" fn Debug::short_src(ar : Debug) -> @c.Pointer[Byte] = "moonbit_lua_debugshortsrc"
///|
/// Gets information about the interpreter runtime stack.
///
/// This function fills parts of a [`@lua.Debug`](#Debug) structure with an
/// identification of the activation record of the function executing at a given
/// level. Level 0 is the current running function, whereas level n+1 is the
/// function that has called level n (except for tail calls, which do not count
/// in the stack). When called with a level greater than the stack depth,
/// [`@lua.get_stack`](#get_stack) returns false; otherwise it returns true.
pub extern "c" fn get_stack(state : State, level : Int, ar : Debug) -> Bool = "lua_getstack"
///|
/// Gets information about a specific function or function invocation.
///
/// To get information about a function invocation, the parameter ar must be a
/// valid activation record that was filled by a previous call to
/// [`@lua.get_stack`](#get_stack) or given as argument to a hook (see
/// [`@lua.Hook`](#Hook)).
///
/// To get information about a function, you push it onto the stack and start
/// the what string with the character `'>'`. (In that case,
/// [`@lua.get_info`](#get_info) pops the function from the top of the stack.)
/// For instance, to know in which line a function f was defined, you can write
/// the following code:
///
/// ```mbt
/// let ar = Debug(@memory.malloc(Debug::sizeof()));
/// defer @memory.free(ar.0);
/// @lua.get_global(lua, "f"); // get global 'f'
/// @lua.get_info(lua, ">S", ar);
/// println("\{ar.line_defined()}");
/// ```
///
/// Each character in the string what selects some fields of the structure ar to
/// be filled or a value to be pushed on the stack. (These characters are also
/// documented in the declaration of the structure [`@lua.Debug`](#Debug),
/// between parentheses in the comments following each field.)
///
/// - `'f'`: pushes onto the stack the function that is running at the given
/// level;
/// - `'l'`: fills in the field `current_line`;
/// - `'n'`: fills in the fields `name` and `namewhat`;
/// - `'r'`: fills in the fields `f_transfer` and `n_transfer`;
/// - `'S'`: fills in the fields `source`, `short_src`, `line_defined`,
/// `last_line_defined`, and `what`;
/// - `'t'`: fills in the field `is_tail_call`;
/// - `'u'`: fills in the fields `n_ups`, `n_params`, and `is_var_arg`;
/// - `'L'`: pushes onto the stack a table whose indices are the lines on the
/// function with some associated code, that is, the lines where you can put a
/// break point. (Lines with no code include empty lines and comments.) If
/// this option is given together with option `'f'`, its table is pushed after
/// the function. This is the only option that can raise a memory error.
///
/// This function returns false to signal an invalid option in what; even then
/// the valid options are handled correctly.
#borrow(what)
pub extern "c" fn get_info(state : State, what : Bytes, ar : Debug) -> Bool = "lua_getinfo"
///|
/// Type for debugging hook functions.
///
/// Whenever a hook is called, its ar argument has its field event set to the
/// specific event that triggered the hook. Lua identifies these events with the
/// following constants: [`@lua.HookCall`](#HookCall),
/// [`@lua.HookRet`](#HookRet), [`@lua.HookTailCall`](#HookTailCall),
/// [`@lua.HookLine`](#HookLine), and [`@lua.HookCount`](#HookCount). Moreover,
/// for line events, the field `current_line` is also set. To get the value of
/// any other field in ar, the hook must call [`@lua.get_info`](#get_info).
///
/// For call events, event can be [`@lua.HookCall`](#HookCall), the normal
/// value, or [`@lua.HookTailCall`](#HookTailCall), for a tail call; in this
/// case, there will be no corresponding return event.
///
/// While Lua is running a hook, it disables other calls to hooks. Therefore, if
/// a hook calls back Lua to execute a function or a chunk, this execution
/// occurs without any calls to hooks.
///
/// Hook functions cannot have continuations, that is, they cannot call
/// [`@lua.yieldk`](#yieldk), [`@lua.pcallk`](#pcallk), or
/// [`@lua.callk`](#callk) with a non-null `k`.
///
/// Hook functions can yield under the following conditions: Only count and line
/// events can yield; to yield, a hook function must finish its execution
/// calling [`@lua.yield`](#yield) with nresults equal to zero (that is, with no
/// values).
pub(all) struct Hook(FuncRef[(State, Debug) -> Unit])
///|
/// Sets the debugging hook function.
///
/// Argument `f` is the hook function. mask specifies on which events the hook
/// will be called: it is formed by a bitwise OR of the constants
/// [`@lua.MaskCall`](#MaskCall), [`@lua.MaskRet`](#MaskRet),
/// [`@lua.MaskLine`](#MaskLine), and [`@lua.MaskCount`](#MaskCount). The
/// `count` argument is only meaningful when the mask includes
/// [`@lua.MaskCount`](#MaskCount). For each event, the hook is called as
/// explained below:
///
/// - The call hook: is called when the interpreter calls a function. The hook
/// is called just after Lua enters the new function.
/// - The return hook: is called when the interpreter returns from a function.
/// The hook is called just before Lua leaves the function.
/// - The line hook: is called when the interpreter is about to start the
/// execution of a new line of code, or when it jumps back in the code (even
/// to the same line). This event only happens while Lua is executing a Lua
/// function.
/// - The count hook: is called after the interpreter executes every count
/// instructions. This event only happens while Lua is executing a Lua
/// function.
///
/// Hooks are disabled by setting mask to zero.
pub extern "c" fn set_hook(state : State, func : Hook, mask : Int, count : Int) = "lua_sethook"
///|
/// Returns the current hook function.
pub extern "c" fn get_hook(state : State) -> Hook = "lua_gethook"
///|
/// Returns the current hook mask.
pub extern "c" fn get_hook_mask(state : State) -> Int = "lua_gethookmask"
///|
/// Returns the current hook count.
pub extern "c" fn get_hook_count(state : State) -> Int = "lua_gethookcount"
///|
/// Sets a new limit for the C stack. This limit controls how deeply nested
/// calls can go in Lua, with the intent of avoiding a stack overflow.
///
/// Returns the old limit in case of success, or zero in case of error.
pub extern "c" fn set_c_stack_limit(state : State, limit : UInt) -> Int = "lua_setcstacklimit"