lei/internal/lua.go

1001 lines
22 KiB
Go
Raw Normal View History

2024-07-17 12:39:44 +01:00
package internal
/*
#cgo CFLAGS: -Iluau/VM/include -I/usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/include
// #cgo LDFLAGS: -L${SRCDIR}/luau/cmake -lLuau.VM -lm -lstdc++
2024-07-17 12:39:44 +01:00
#include <lua.h>
#include <lualib.h>
#include <stdlib.h>
#include "clua.h"
2024-07-17 12:39:44 +01:00
*/
import "C"
2024-07-19 18:01:54 +01:00
import (
"errors"
"strconv"
"unsafe"
)
2024-07-17 12:39:44 +01:00
//
// ===========================
// luaconf.h Constants
// ===========================
//
const (
LUAI_MAXCSTACK = 1000000 // Max allowed values in lua stack
LUA_UTAG_LIMIT = 128 // Max number of lua userdata tags
LUA_LUTAG_LIMIT = 128 // Max number of light lua userdata tags
)
const LUA_MULTRET = -1
//
// ====================
// Pseudo Indices
// ====================
//
const (
LUA_REGISTRYINDEX = -LUAI_MAXCSTACK - 2000
LUA_ENVIRONINDEX = -LUAI_MAXCSTACK - 2001
LUA_GLOBALSINDEX = -LUAI_MAXCSTACK - 2002
)
//
// ======================
// Thread Status
// ======================
//
const (
LUA_OK = iota + 1
LUA_YIELD
LUA_ERRRUN
LUA_ERRSYNTAX
LUA_ERRMEM
LUA_ERRERR
LUA_BREAK
)
//
// =========================
// Coroutine Status
// =========================
//
const (
LUA_CORUN = iota + 1
LUA_COSUS
LUA_CONOR
LUA_COFIN
LUA_COERR
)
//
// ===================
// Basic Types
// ===================
//
const LUA_TNONE = -1
const (
LUA_TNIL = iota
LUA_TBOOLEAN
LUA_TLIGHTUSERDATA
LUA_TNUMBER
LUA_TVECTOR
LUA_TSTRING
LUA_TTABLE
LUA_TFUNCTION
LUA_TUSERDATA
LUA_TTHREAD
LUA_TBUFFER
LUA_TPROTO
LUA_TUPVAL
LUA_TDEADKEY
LUA_T_COUNT = LUA_TPROTO
)
type LuaNumber float64
type LuaInteger int32
type LuaUnsigned int32
2024-07-17 12:39:44 +01:00
type LuaState = C.lua_State
type LuaCFunction func(L *LuaState) int32
type LuaContinuation func(L *LuaState, status int32) int32
2024-07-17 12:39:44 +01:00
type LuaUDestructor = func(*C.void)
type LuaDestructor = func(L *LuaState, _ unsafe.Pointer)
2024-07-17 12:39:44 +01:00
type LuaAlloc = func(ud, ptr unsafe.Pointer, osize, nsize C.size_t) *C.void
2024-07-17 12:39:44 +01:00
//
// ==================
// VM state
// ==================
//
func NewState(f LuaAlloc, ud unsafe.Pointer) *LuaState {
cf := C.malloc(C.size_t(unsafe.Sizeof(f)))
defer C.free(cf)
*(*LuaAlloc)(cf) = f
cud := C.malloc(C.size_t(unsafe.Sizeof(ud)))
defer C.free(cud)
cud = ud
return C.clua_newstate(cf, cud)
2024-07-17 12:39:44 +01:00
}
func LuaClose(L *LuaState) {
2024-07-17 12:39:44 +01:00
C.lua_close(L)
}
func NewThread(L *LuaState) *LuaState {
2024-07-17 12:39:44 +01:00
return C.lua_newthread(L)
}
func MainThread(L *LuaState) *LuaState {
2024-07-17 12:39:44 +01:00
return C.lua_mainthread(L)
}
func ResetThread(L *LuaState) {
2024-07-17 12:39:44 +01:00
C.lua_resetthread(L)
}
func IsThreadReset(L *LuaState) bool {
2024-07-17 12:39:44 +01:00
return C.lua_isthreadreset(L) != 0
}
//
// ==================
// VM Stack
// ==================
//
func AbsIndex(L *LuaState, idx int32) int32 {
return int32(C.lua_absindex(L, C.int(idx)))
2024-07-17 12:39:44 +01:00
}
func GetTop(L *LuaState) int32 {
return int32(C.lua_gettop(L))
2024-07-17 12:39:44 +01:00
}
func SetTop(L *LuaState, idx int32) {
C.lua_settop(L, C.int(idx))
2024-07-17 12:39:44 +01:00
}
func PushValue(L *LuaState, idx int32) {
C.lua_pushvalue(L, C.int(idx))
2024-07-17 12:39:44 +01:00
}
func Remove(L *LuaState, idx int32) {
C.lua_remove(L, C.int(idx))
2024-07-17 12:39:44 +01:00
}
func Insert(L *LuaState, idx int32) {
C.lua_insert(L, C.int(idx))
2024-07-17 12:39:44 +01:00
}
func Replace(L *LuaState, idx int32) {
C.lua_replace(L, C.int(idx))
2024-07-17 12:39:44 +01:00
}
func CheckStack(L *LuaState, sz int32) bool {
return C.lua_checkstack(L, C.int(sz)) != 0
2024-07-17 12:39:44 +01:00
}
func RawCheckStack(L *LuaState, sz int32) {
C.lua_rawcheckstack(L, C.int(sz))
2024-07-17 12:39:44 +01:00
}
func XMove(from, to *LuaState, n int32) {
C.lua_xmove(from, to, C.int(n))
2024-07-17 12:39:44 +01:00
}
func XPush(from, to *LuaState, idx int32) {
C.lua_xpush(from, to, C.int(idx))
2024-07-17 12:39:44 +01:00
}
//
// ======================
// Stack Values
// ======================
//
func IsNumber(L *LuaState, idx int32) bool {
return C.lua_isnumber(L, C.int(idx)) != 0
2024-07-17 12:39:44 +01:00
}
func IsString(L *LuaState, idx int32) bool {
return C.lua_isstring(L, C.int(idx)) != 0
2024-07-17 12:39:44 +01:00
}
func IsCFunction(L *LuaState, idx int32) bool {
return C.lua_iscfunction(L, C.int(idx)) != 0
2024-07-17 12:39:44 +01:00
}
func IsLFunction(L *LuaState, idx int32) bool {
return C.lua_isLfunction(L, C.int(idx)) != 0
2024-07-17 12:39:44 +01:00
}
func IsUserData(L *LuaState, idx int32) bool {
return C.lua_isuserdata(L, C.int(idx)) != 0
2024-07-17 12:39:44 +01:00
}
func Type(L *LuaState, idx int32) int32 {
return int32(C.lua_type(L, C.int(idx)))
2024-07-17 12:39:44 +01:00
}
func TypeName(L *LuaState, tp int32) string {
return C.GoString(C.lua_typename(L, C.int(tp)))
2024-07-17 12:39:44 +01:00
}
func Equal(L *LuaState, idx1, idx2 int32) bool {
return C.lua_equal(L, C.int(idx1), C.int(idx2)) != 0
2024-07-17 12:39:44 +01:00
}
func RawEqual(L *LuaState, idx1, idx2 int32) bool {
return C.lua_rawequal(L, C.int(idx1), C.int(idx2)) != 0
2024-07-17 12:39:44 +01:00
}
func LessThan(L *LuaState, idx1, idx2 int32) bool {
return C.lua_lessthan(L, C.int(idx1), C.int(idx2)) != 0
2024-07-17 12:39:44 +01:00
}
func ToNumberX(L *LuaState, idx int32, isnum *bool) LuaNumber {
cisnumber := C.int(0)
if *isnum {
cisnumber = C.int(1)
2024-07-17 12:39:44 +01:00
}
num := LuaNumber(C.lua_tonumberx(L, C.int(idx), &cisnumber))
*isnum = cisnumber != C.int(0)
return num
2024-07-17 12:39:44 +01:00
}
func ToIntegerX(L *LuaState, idx int32, isnum *bool) LuaInteger {
cisnumber := C.int(0)
if *isnum {
cisnumber = C.int(1)
2024-07-17 12:39:44 +01:00
}
integer := LuaInteger(C.lua_tointegerx(L, C.int(idx), &cisnumber))
*isnum = cisnumber != C.int(0)
return integer
2024-07-17 12:39:44 +01:00
}
func ToUnsignedX(L *LuaState, idx int32, isnum *bool) LuaUnsigned {
cisnumber := C.int(0)
if *isnum {
cisnumber = C.int(1)
2024-07-17 12:39:44 +01:00
}
unsigned := LuaUnsigned(C.lua_tounsignedx(L, C.int(idx), &cisnumber))
*isnum = cisnumber != C.int(0)
return unsigned
2024-07-17 12:39:44 +01:00
}
func ToVector(L *LuaState, idx int32) {
2024-07-17 19:55:35 +01:00
C.lua_tovector(L, C.int(idx))
}
func ToBoolean(L *LuaState, idx int32) bool {
2024-07-17 19:55:35 +01:00
return C.lua_toboolean(L, C.int(idx)) != 0
}
func ToLString(L *LuaState, idx int32, len *uint64) string {
2024-07-17 19:55:35 +01:00
return C.GoString(C.lua_tolstring(L, C.int(idx), (*C.size_t)(len)))
}
func ToStringAtom(L *LuaState, idx int32, atom *int32) string {
2024-07-17 19:55:35 +01:00
return C.GoString(C.lua_tostringatom(L, C.int(idx), (*C.int)(atom)))
}
func NameCallAtom(L *LuaState, atom *int32) string {
2024-07-17 19:55:35 +01:00
return C.GoString(C.lua_namecallatom(L, (*C.int)(atom)))
}
func ObjLen(L *LuaState, idx int32) uint64 {
2024-07-17 19:55:35 +01:00
return uint64(C.lua_objlen(L, C.int(idx)))
}
func ToCFunction(L *LuaState, idx int32) LuaCFunction {
2024-07-17 19:55:35 +01:00
p := unsafe.Pointer(C.lua_tocfunction(L, C.int(idx)))
if p == C.NULL {
return nil
}
return *(*LuaCFunction)(p)
2024-07-17 19:55:35 +01:00
}
func ToLightUserdata(L *LuaState, idx int32) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_tolightuserdata(L, C.int(idx)))
}
func ToLightUserdataTagged(L *LuaState, idx int32, tag int32) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_tolightuserdatatagged(L, C.int(idx), C.int(tag)))
}
func ToUserdata(L *LuaState, idx int32) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_touserdata(L, C.int(idx)))
}
func ToUserdataTagged(L *LuaState, idx int32, tag int32) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_touserdatatagged(L, C.int(idx), C.int(tag)))
}
func UserdataTag(L *LuaState, idx int32) int32 {
2024-07-17 19:55:35 +01:00
return int32(C.lua_userdatatag(L, C.int(idx)))
}
func LightUserdataTag(L *LuaState, idx int32) int32 {
2024-07-17 19:55:35 +01:00
return int32(C.lua_lightuserdatatag(L, C.int(idx)))
}
func ToThread(L *LuaState, idx int32) *LuaState {
2024-07-17 19:55:35 +01:00
return C.lua_tothread(L, C.int(idx))
}
func ToBuffer(L *LuaState, idx int32, len *uint64) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_tobuffer(L, C.int(idx), (*C.size_t)(len)))
}
func ToPointer(L *LuaState, idx int32) unsafe.Pointer {
2024-07-17 19:55:35 +01:00
return unsafe.Pointer(C.lua_topointer(L, C.int(idx)))
}
//
2024-07-17 19:55:35 +01:00
// =======================
// Stack Manipulation
// =======================
//
2024-07-17 19:55:35 +01:00
func PushNil(L *LuaState) {
2024-07-17 19:55:35 +01:00
C.lua_pushnil(L)
}
func PushNumber(L *LuaState, n LuaNumber) {
2024-07-17 19:55:35 +01:00
C.lua_pushnumber(L, C.lua_Number(n))
}
func PushInteger(L *LuaState, n LuaInteger) {
2024-07-17 19:55:35 +01:00
C.lua_pushinteger(L, C.lua_Integer(n))
}
func PushUnsigned(L *LuaState, n LuaUnsigned) {
C.lua_pushunsigned(L, C.lua_Unsigned(n))
}
func PushLString(L *LuaState, s string, l uint64) {
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
// NOTE: CStrings are null-terminated, and hence one longer than Go strings
C.lua_pushlstring(L, cs, C.size_t(l+1))
}
func PushString(L *LuaState, s string) {
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
C.lua_pushstring(L, cs)
}
// NOTE: We can't have lua_pushfstringL, since varadic
// arguments from Go->C isn't something that is possible.
// func PushFStringL(L *lua_State, fmt string) {}
func PushCClosureK(L *LuaState, f LuaCFunction, debugname string, nup int32, cont LuaContinuation) {
cdebugname := C.CString(debugname)
defer C.free(unsafe.Pointer(cdebugname))
ccont := C.malloc(C.size_t(unsafe.Sizeof(cont)))
defer C.free(ccont)
if cont == nil {
ccont = C.NULL
} else {
*(*LuaContinuation)(ccont) = cont
}
cf := C.malloc(C.size_t(unsafe.Sizeof(f)))
defer C.free(cf)
*(*LuaCFunction)(cf) = f
C.clua_pushcclosurek(L, cf, cdebugname, C.int(nup), ccont)
}
2024-07-17 19:55:35 +01:00
func PushBoolean(L *LuaState, b bool) {
cb := C.int(0)
if b {
cb = C.int(1)
}
C.lua_pushboolean(L, cb)
}
func PushThread(L *LuaState) bool {
return C.lua_pushthread(L) != 0
}
func PushLightUserdataTagged(L *LuaState, p unsafe.Pointer, tag int32) {
C.lua_pushlightuserdatatagged(L, p, C.int(tag))
}
func NewUserdataTagged(L *LuaState, sz uint64, tag int32) unsafe.Pointer {
return C.lua_newuserdatatagged(L, C.size_t(sz), C.int(tag))
}
func NewUserdataDtor(L *LuaState, sz uint64, dtor LuaUDestructor) unsafe.Pointer {
cdtor := C.malloc(C.size_t(unsafe.Sizeof(dtor)))
defer C.free(cdtor)
*(*LuaUDestructor)(cdtor) = dtor
return C.clua_newuserdatadtor(L, C.size_t(sz), cdtor)
}
func NewBuffer(L *LuaState, sz uint64) unsafe.Pointer {
return C.lua_newbuffer(L, C.size_t(sz))
}
//
// =====================
// Get Functions
// =====================
//
func GetTable(L *LuaState, idx int32) int32 {
return int32(C.lua_gettable(L, C.int(idx)))
}
func GetField(L *LuaState, idx int32, k string) int32 {
ck := C.CString(k)
defer C.free(unsafe.Pointer(ck))
return int32(C.lua_getfield(L, C.int(idx), ck))
}
func RawGetField(L *LuaState, idx int32, k string) int32 {
ck := C.CString(k)
defer C.free(unsafe.Pointer(ck))
return int32(C.lua_rawgetfield(L, C.int(idx), ck))
}
func RawGet(L *LuaState, idx int32) int32 {
return int32(C.lua_rawget(L, C.int(idx)))
}
func RawGetI(L *LuaState, idx int32, n int32) int32 {
return int32(C.lua_rawgeti(L, C.int(idx), C.int(n)))
}
func CreateTable(L *LuaState, narr int32, nrec int32) {
C.lua_createtable(L, C.int(narr), C.int(nrec))
}
func SetReadonly(L *LuaState, idx int32, enabled bool) {
cenabled := C.int(0)
if enabled {
cenabled = C.int(1)
}
C.lua_setreadonly(L, C.int(idx), cenabled)
}
func GetReadonly(L *LuaState, idx int32) bool {
return C.lua_getreadonly(L, C.int(idx)) != 0
}
func SetSafeEnv(L *LuaState, idx int32, enabled bool) {
cenabled := C.int(0)
if enabled {
cenabled = C.int(1)
}
C.lua_setsafeenv(L, C.int(idx), cenabled)
}
func Getfenv(L *LuaState, idx int32) {
C.lua_getfenv(L, C.int(idx))
}
//
// ===================
// Set Functions
// ===================
//
func SetTable(L *LuaState, idx int32) {
C.lua_settable(L, C.int(idx))
}
func SetField(L *LuaState, idx int32, k string) {
ck := C.CString(k)
defer C.free(unsafe.Pointer(ck))
C.lua_setfield(L, C.int(idx), ck)
}
func RawSetI(L *LuaState, idx int32, n int32) {
C.lua_rawseti(L, C.int(idx), C.int(n))
}
func SetMetatable(L *LuaState, objindex int32) int32 {
return int32(C.lua_setmetatable(L, C.int(objindex)))
}
func Setfenv(L *LuaState, idx int32) int32 {
return int32(C.lua_setfenv(L, C.int(idx)))
}
//
// =========================
// Bytecode Functions
// =========================
//
func LuauLoad(L *LuaState, chunkname string, data string, size uint64, env int32) int32 {
cchunkname := C.CString(chunkname)
defer C.free(unsafe.Pointer(cchunkname))
cdata := C.CString(data)
defer C.free(unsafe.Pointer(cdata))
return int32(C.luau_load(L, cchunkname, cdata, C.size_t(size), C.int(env)))
}
func LuaCall(L *LuaState, nargs int32, nresults int32) {
C.lua_call(L, C.int(nargs), C.int(nresults))
}
func LuaPcall(L *LuaState, nargs int32, nresults int32, errfunc int32) int32 {
return int32(C.lua_pcall(L, C.int(nargs), C.int(nresults), C.int(errfunc)))
}
//
// ========================
// Coroutine Functions
// ========================
//
func LuaYield(L *LuaState, nresults int32) int32 {
return int32(C.lua_yield(L, C.int(nresults)))
}
func LuaBreak(L *LuaState) int32 {
return int32(C.lua_break(L))
}
func LuaResume(L *LuaState, from *LuaState, nargs int32) int32 {
return int32(C.lua_resume(L, from, C.int(nargs)))
}
func LuaResumeError(L *LuaState, from *LuaState) int32 {
return int32(C.lua_resumeerror(L, from))
}
func LuaStatus(L *LuaState) int32 {
return int32(C.lua_status(L))
}
func IsYieldable(L *LuaState) bool {
return C.lua_isyieldable(L) != 0
}
func GetThreadData(L *LuaState) unsafe.Pointer {
return C.lua_getthreaddata(L)
}
func SetThreadData(L *LuaState, data unsafe.Pointer) {
C.lua_setthreaddata(L, data)
}
//
// ======================
// Garbage Collection
// ======================
//
const (
LUA_GCSTOP = iota
LUA_GCRESTART
LUA_GCCOLLECT
LUA_GCCOUNT
LUA_GCCOUNTB
LUA_GCISRUNNING
LUA_GCSTEP
LUA_GCSETGOAL
LUA_GCSETSTEPMUL
LUA_GCSETSTEPSIZE
)
func LuaGc(L *LuaState, what int32, data int32) int32 {
return int32(C.lua_gc(L, C.int(what), C.int(data)))
}
//
// ======================
// Memory Statistics
// ======================
//
func SetMemCat(L *LuaState, category int32) {
C.lua_setmemcat(L, C.int(category))
}
func TotalBytes(L *LuaState, category int32) uint64 {
return uint64(C.lua_totalbytes(L, C.int(category)))
}
//
// ================================
// Miscellaneous Functions
// ================================
//
func Error(L *LuaState) {
C.lua_error(L)
}
func Next(L *LuaState, idx int32) int32 {
return int32(C.lua_next(L, C.int(idx)))
}
func RawIter(L *LuaState, idx int32, iter int32) int32 {
return int32(C.lua_rawiter(L, C.int(idx), C.int(iter)))
}
func Concat(L *LuaState, n int32) {
C.lua_concat(L, C.int(n))
}
func Clock() float64 {
return float64(C.lua_clock())
}
func SetUserdataTag(L *LuaState, idx int32, tag int32) {
C.lua_setuserdatatag(L, C.int(idx), C.int(tag))
}
func SetUserdataDtor(L *LuaState, tag int32, dtor LuaDestructor) {
cdtor := C.malloc(C.size_t(unsafe.Sizeof(dtor)))
defer C.free(cdtor)
if dtor == nil {
cdtor = C.NULL
} else {
*(*LuaDestructor)(cdtor) = dtor
}
C.clua_setuserdatadtor(L, C.int(tag), cdtor)
}
func GetUserdataDtor(L *LuaState, tag int32) LuaDestructor {
return *(*LuaDestructor)(unsafe.Pointer(C.lua_getuserdatadtor(L, C.int(tag))))
}
func SetUserdataMetatable(L *LuaState, tag int32, idx int32) {
C.lua_setuserdatametatable(L, C.int(tag), C.int(idx))
}
func GetUserdataMetatable(L *LuaState, tag int32) {
C.lua_getuserdatametatable(L, C.int(tag))
}
func SetLightUserdataName(L *LuaState, tag int32, name string) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
C.lua_setlightuserdataname(L, C.int(tag), cname)
}
func GetLightUserdataName(L *LuaState, tag int32) string {
return C.GoString(C.lua_getlightuserdataname(L, C.int(tag)))
}
func CloneFunction(L *LuaState, idx int32) {
C.lua_clonefunction(L, C.int(idx))
}
func ClearTable(L *LuaState, idx int32) {
C.lua_cleartable(L, C.int(idx))
}
func GetAllocF(L *LuaState, ud *unsafe.Pointer) LuaAlloc {
return *(*LuaAlloc)(unsafe.Pointer(C.lua_getallocf(L, ud)))
}
//
// ==========================
// Reference System
// ==========================
//
const (
LUA_NOREF = iota - 1
LUA_REFNIL
)
func Ref(L *LuaState, idx int32) int32 {
return int32(C.lua_ref(L, C.int(idx)))
}
func Unref(L *LuaState, ref int32) {
C.lua_unref(L, C.int(ref))
}
2024-07-19 18:01:54 +01:00
//
// ==================
// Debug API
// ==================
//
const LUA_IDSIZE = 256
type LuaDebug struct {
Name string
What string
Source string
ShortSrc string
LineDefined int8
CurrentLine int8
NUpVals uint8
NParams uint8
IsVarArg int8
Userdata unsafe.Pointer
SSbuf string // size = LUA_IDSIZE
}
type LuaHook = func(L *LuaState, ar *LuaDebug)
type LuaCoverage = func(
context unsafe.Pointer,
function string,
linedefined int32,
depth int32,
hits *int32,
size uint64,
)
func StackDepth(L *LuaState) int32 {
return int32(C.lua_stackdepth(L))
}
2024-07-20 12:47:02 +01:00
func (ar *LuaDebug) toCLuaDebug() (*C.lua_Debug, error) {
2024-07-19 18:01:54 +01:00
cname := C.CString(ar.Name)
defer C.free(unsafe.Pointer(cname))
carwhat := C.CString(ar.What)
defer C.free(unsafe.Pointer(carwhat))
csource := C.CString(ar.Source)
defer C.free(unsafe.Pointer(csource))
cshortsrc := C.CString(ar.ShortSrc)
defer C.free(unsafe.Pointer(cshortsrc))
if len(ar.SSbuf)+1 != LUA_IDSIZE { // contains null delimeter, so LUA_IDSIZE is one greater than the string len
2024-07-20 12:47:02 +01:00
return nil, errors.New("lua.GetInfo: SSbuf must be exactly " + strconv.Itoa(LUA_IDSIZE) + " bytes long")
2024-07-19 18:01:54 +01:00
}
cssbuf := C.CString(ar.SSbuf)
defer C.free(unsafe.Pointer(cssbuf))
2024-07-20 12:47:02 +01:00
return &C.lua_Debug{
2024-07-19 18:01:54 +01:00
name: cname,
what: carwhat,
source: csource,
short_src: cshortsrc,
linedefined: C.int(ar.LineDefined),
currentline: C.int(ar.CurrentLine),
nupvals: C.uchar(ar.NUpVals),
nparams: C.uchar(ar.NParams),
isvararg: C.char(ar.IsVarArg),
userdata: ar.Userdata,
ssbuf: *(*[LUA_IDSIZE]C.char)(unsafe.Pointer(cssbuf)),
2024-07-20 12:47:02 +01:00
}, nil
}
// Errors if invalid LuaDebug provided, returns -1
func GetInfo(L *LuaState, level int32, what string, ar *LuaDebug) (int32, error) {
cwhat := C.CString(what)
defer C.free(unsafe.Pointer(cwhat))
car, err := ar.toCLuaDebug()
if err != nil {
return -1, err
2024-07-19 18:01:54 +01:00
}
2024-07-20 12:47:02 +01:00
carp := C.malloc(C.size_t(unsafe.Sizeof(*ar)))
defer C.free(carp)
*(**C.lua_Debug)(carp) = car
return int32(C.lua_getinfo(L, C.int(level), cwhat, (*C.lua_Debug)(carp))), nil
2024-07-19 18:01:54 +01:00
}
func GetArgument(L *LuaState, level int32, n int32) int32 {
return int32(C.lua_getargument(L, C.int(level), C.int(n)))
}
func GetLocal(L *LuaState, level int32, n int32) string {
return C.GoString(C.lua_getlocal(L, C.int(level), C.int(n)))
}
func SetLocal(L *LuaState, level int32, n int32) string {
return C.GoString(C.lua_setlocal(L, C.int(level), C.int(n)))
}
func GetUpvalue(L *LuaState, funcindex int32, n int32) string {
return C.GoString(C.lua_getupvalue(L, C.int(funcindex), C.int(n)))
}
func SetUpvalue(L *LuaState, funcindex int32, n int32) string {
return C.GoString(C.lua_setupvalue(L, C.int(funcindex), C.int(n)))
}
func SingleStep(L *LuaState, enabled bool) {
cenabled := C.int(0)
if enabled {
cenabled = C.int(1)
}
C.lua_singlestep(L, cenabled)
}
func Breakpoint(L *LuaState, funcindex int32, line int32, enabled bool) int32 {
cenabled := C.int(0)
if enabled {
cenabled = C.int(1)
}
return int32(C.lua_breakpoint(L, C.int(funcindex), C.int(line), cenabled))
}
func GetCoverage(L *LuaState, funcindex int32, context unsafe.Pointer, callback LuaCoverage) {
ccallback := C.malloc(C.size_t(unsafe.Sizeof(callback)))
defer C.free(ccallback)
*(*LuaCoverage)(ccallback) = callback
C.clua_getcoverage(L, C.int(funcindex), context, ccallback)
}
func DebugTrace(L *LuaState) string {
return C.GoString(C.lua_debugtrace(L))
}
2024-07-20 12:47:02 +01:00
type LuaCallbacks struct {
Userdata unsafe.Pointer
Interrupt func(L *LuaState, gc int32)
Panic func(L *LuaState, errcode int32)
UserThread func(LP *LuaState, L *LuaState)
UserAtom func(s string, l uint64)
DebugBreak func(L *LuaState, ar *LuaDebug)
DebugStep func(L *LuaState, ar *LuaDebug)
DebugInterrupt func(L *LuaState, ar *LuaDebug)
DebugProtectedError func(L *LuaState)
}
func Callbacks(L *LuaState) *LuaCallbacks {
ccallbacks := C.lua_callbacks(L)
// sorry
return &LuaCallbacks{
Userdata: ccallbacks.userdata,
Interrupt: *(*func(L *LuaState, gc int32))(unsafe.Pointer(ccallbacks.interrupt)),
Panic: *(*func(L *LuaState, errcode int32))(unsafe.Pointer(ccallbacks.panic)),
UserThread: *(*func(LP *LuaState, L *LuaState))(unsafe.Pointer(ccallbacks.userthread)),
UserAtom: *(*func(s string, l uint64))(unsafe.Pointer(ccallbacks.useratom)),
DebugBreak: *(*func(L *LuaState, ar *LuaDebug))(unsafe.Pointer(ccallbacks.debugbreak)),
DebugStep: *(*func(L *LuaState, ar *LuaDebug))(unsafe.Pointer(ccallbacks.debugstep)),
DebugInterrupt: *(*func(L *LuaState, ar *LuaDebug))(unsafe.Pointer(ccallbacks.debugstep)),
DebugProtectedError: *(*func(L *LuaState))(unsafe.Pointer(ccallbacks.debugstep)),
}
}
func ToNumber(L *LuaState, i int32) LuaNumber {
return ToNumberX(L, i, new(bool))
}
func ToInteger(L *LuaState, i int32) LuaInteger {
return ToIntegerX(L, i, new(bool))
}
func ToUnsigned(L *LuaState, i int32) LuaUnsigned {
return ToUnsignedX(L, i, new(bool))
}
func Pop(L *LuaState, n int32) {
SetTop(L, -n-1)
}
func NewTable(L *LuaState) {
CreateTable(L, 0, 0)
}
func NewUserdata(L *LuaState, sz uint64) unsafe.Pointer {
return NewUserdataTagged(L, sz, 0)
}
func IsFunction(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TFUNCTION
}
func IsTable(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TTABLE
}
func IsLightUserdata(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TLIGHTUSERDATA
}
func IsNil(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TNIL
}
func IsBoolean(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TBOOLEAN
}
func IsVector(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TVECTOR
}
func IsThread(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TTHREAD
}
func IsBuffer(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TBUFFER
}
func IsNone(L *LuaState, n int32) bool {
return Type(L, n) == LUA_TNONE
}
func IsNoneOrNil(L *LuaState, n int32) bool {
return Type(L, n) <= LUA_TNIL
}
func PushLiteral(L *LuaState, s string) {
PushLString(L, s, uint64(len(s)))
}
func PushCFunction(L *LuaState, f LuaCFunction) {
PushCClosureK(L, f, *new(string), 0, nil)
}
func PushCFunctionD(L *LuaState, f LuaCFunction, debugname string) {
PushCClosureK(L, f, debugname, 0, nil)
}
func PushCClosure(L *LuaState, f LuaCFunction, nup int32) {
PushCClosureK(L, f, *new(string), nup, nil)
}
func PushCClosureD(L *LuaState, f LuaCFunction, debugname string, nup int32) {
PushCClosureK(L, f, debugname, nup, nil)
}
func PushLightUserdata(L *LuaState, p unsafe.Pointer) {
PushLightUserdataTagged(L, p, 0)
}
func SetGlobal(L *LuaState, global string) {
SetField(L, LUA_GLOBALSINDEX, global)
}
func GetGlobal(L *LuaState, global string) int32 {
return GetField(L, LUA_GLOBALSINDEX, global)
}
func ToString(L *LuaState, i int32) string {
return ToLString(L, i, new(uint64))
}