diff options
Diffstat (limited to 'luajit.go')
| -rw-r--r-- | luajit.go | 129 |
1 files changed, 16 insertions, 113 deletions
@@ -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) |
