summaryrefslogtreecommitdiff
path: root/luajit.go
diff options
context:
space:
mode:
Diffstat (limited to 'luajit.go')
-rw-r--r--luajit.go129
1 files changed, 16 insertions, 113 deletions
diff --git a/luajit.go b/luajit.go
index 0c51f13..2ed3788 100644
--- a/luajit.go
+++ b/luajit.go
@@ -24,20 +24,18 @@ static inline void luna_push_function(lua_State *l, uintptr_t f) {
import "C"
import (
"errors"
- "fmt"
"runtime/cgo"
- "time"
"unsafe"
)
type LuaRef C.int
+
// Lua is a wrapper around C Lua state with several conveniences.
type Lua struct {
l *C.lua_State
running **Lua
yield func()
resume func() bool
- tracebackHandler LuaRef
}
//export luna_run_go_func
@@ -53,9 +51,9 @@ func (l *Lua) Start() {
l.running = &l
C.luaL_openlibs(l.l)
- // Put debug handler into the registry for later copies to the stack.
+ // Put traceback function at the start of the stack so it's always
+ // possible to refer to it via stack index 1.
l.PushGoFunction(TracebackHandler)
- l.tracebackHandler = l.PopToRef()
}
// Close closes the Lua context.
@@ -63,23 +61,6 @@ func (l *Lua) Close() {
C.lua_close(l.l)
}
-// Require loads and executes the file pushing results onto the Lua stack.
-// FIXME: traceback handler remains dangling on the stack, we need to remove
-// it somehow.
-func (l *Lua) Require(file string) error {
- l.PushTracebackHandler()
- if !l.LoadFile(file) {
- errMsg := l.ToString(-1)
- l.Pop(1)
- return errors.New("could not open the file:\n" + errMsg)
- }
- err := l.PCall(0, C.LUA_MULTRET, -2)
- if err != nil {
- return errors.New("could not execute the file:\n" + err.Error())
- }
- return nil
-}
-
// PCall calls a function with the stack index (-nargs-1) expecting nresults
// number of results.
func (l *Lua) PCall(nargs int, nresults int, errfunc int) error {
@@ -94,11 +75,16 @@ func (l *Lua) PCall(nargs int, nresults int, errfunc int) error {
}
// LoadFile loads the file code in the current Lua context.
-func (l *Lua) LoadFile(file string) bool {
+func (l *Lua) LoadFile(file string) error {
cstr := C.CString(file)
defer C.free(unsafe.Pointer(cstr))
res := C.luaL_loadfilex(l.l, cstr, nil)
- return res == C.LUA_OK
+ if res != C.LUA_OK {
+ errMsg := l.ToString(-1)
+ l.Pop(1)
+ return errors.New(errMsg)
+ }
+ return nil
}
// StackLen returns the length of the Lua stack.
@@ -132,6 +118,11 @@ func (l *Lua) Pop(n int) {
C.lua_settop(l.l, C.int(-n - 1))
}
+// SetTop sets head of the stack at top.
+func (l *Lua) SetTop(top int) {
+ C.lua_settop(l.l, C.int(top))
+}
+
// PushNil pushes tnil onto the Lua stack.
func (l *Lua) PushNil() {
C.lua_pushnil(l.l)
@@ -202,63 +193,6 @@ func (l *Lua) RawGetI(tableOffset, i int) {
C.lua_rawgeti(l.l, C.int(tableOffset), C.int(i))
}
-// PushAny pushes value v onto the stack.
-func (l *Lua) PushAny(v any) error {
- switch v.(type) {
- case nil:
- l.PushNil()
- case string:
- v, _ := v.(string)
- l.PushString(v)
- case func (l *Lua) int:
- v, _ := v.(func (l *Lua) int)
- l.PushGoFunction(v)
- case int:
- v, _ := v.(int)
- l.PushNumber(v)
- case int64:
- v, _ := v.(int64)
- l.PushNumber(int(v))
- case float64:
- v, _ := v.(float64)
- l.PushFloatNumber(v)
- case bool:
- v, _ := v.(bool)
- l.PushBoolean(v)
- case map[string]any:
- v, _ := v.(map[string]any)
- err := l.PushObject(v)
- if err != nil {
- return fmt.Errorf("object push error: ", err)
- }
- case []any:
- v, _ := v.([]any)
- err := l.PushArray(v)
- if err != nil {
- return fmt.Errorf("array push error: ", err)
- }
- case time.Time:
- v, _ := v.(time.Time)
- l.PushString(v.Format(time.DateTime))
- default:
- return fmt.Errorf("unsupported value type: %T", v)
- }
- return nil
-}
-
-// PushObject recursively pushes string->any Go table onto the stack.
-func (l *Lua) PushObject(table map[string]any) error {
- l.CreateTable(len(table))
- for k, v := range table {
- err := l.PushAny(v)
- if err != nil {
- return err
- }
- l.SetTableItem(k)
- }
- return nil
-}
-
// PushArray recursively pushes an array of Go values onto the stack.
func (l *Lua) PushArray(array []any) error {
l.CreateTable(len(array))
@@ -326,45 +260,21 @@ func (l *Lua) Next() bool {
// LoadAndCall loads and calls the code in the current Lua context. Whatever
// the code returns is stored in the stack. To drop the results use l.Pop.
-// FIXME: traceback handler remains dangling on the stack, we need to remove
-// it somehow.
func (l *Lua) LoadAndCall(code string) error {
cstr := C.CString(code)
defer C.free(unsafe.Pointer(cstr))
- l.PushTracebackHandler()
if C.luaL_loadstring(l.l, cstr) != C.LUA_OK {
errMsg := l.ToString(-1)
l.Pop(1)
return errors.New(errMsg)
}
- err := l.PCall(0, C.LUA_MULTRET, -2)
+ err := l.PCall(0, C.LUA_MULTRET, 1)
if err != nil {
return err
}
return nil
}
-// RestoreStackFunc remembers the Lua stack size and then restores it when a
-// returned function is called. It's a helper function to avoid stack leakage.
-func (l *Lua) RestoreStackFunc() func () {
- before := l.StackLen()
- return func () {
- after := l.StackLen()
- diff := after - before
- if diff == 0 {
- return
- } else if diff < 0 {
- msg := fmt.Sprintf(
- "too many stack pops: len before: %d, after: %d\n",
- before,
- after,
- )
- panic(msg)
- }
- C.lua_settop(l.l, C.int(before))
- }
-}
-
// SetGlobal sets a global value at the -1 stack index with the name.
func (l *Lua) SetGlobal(name string) {
cstr := C.CString(name)
@@ -385,16 +295,9 @@ func (l *Lua) NewThread(yield func(), resume func() bool) *Lua {
running: l.running,
resume: resume,
yield: yield,
- tracebackHandler: l.tracebackHandler,
}
}
-// PushTracebackHandler puts the traceback handler onto the stack for using
-// as a errfunc argument when calling PCall.
-func (l *Lua) PushTracebackHandler() {
- l.PushFromRef(l.tracebackHandler)
-}
-
// TracebackHandler handles stack trace formatting on errors.
func TracebackHandler(l *Lua) int {
msg := l.ToString(-1)