package luajit /* #include #include */ import "C" import "fmt" // LuaError represents an error from the Lua state type LuaError struct { Code int Message string } func (e *LuaError) Error() string { return fmt.Sprintf("lua error (code=%d): %s", e.Code, e.Message) } // Stack management constants from lua.h const ( LUA_MINSTACK = 20 // Minimum Lua stack size LUA_MAXSTACK = 1000000 // Maximum Lua stack size LUA_REGISTRYINDEX = -10000 // Pseudo-index for the Lua registry LUA_GLOBALSINDEX = -10002 // Pseudo-index for globals table ) // checkStack ensures there is enough space on the Lua stack func (s *State) checkStack(n int) error { if C.lua_checkstack(s.L, C.int(n)) == 0 { return fmt.Errorf("stack overflow (cannot allocate %d slots)", n) } return nil } // safeCall wraps a potentially dangerous C call with stack checking func (s *State) safeCall(f func() C.int) error { // Save current stack size top := s.GetTop() // Ensure we have enough stack space (minimum 20 slots as per Lua standard) if err := s.checkStack(LUA_MINSTACK); err != nil { return err } // Make the call status := f() // Check for errors if status != 0 { err := &LuaError{ Code: int(status), Message: s.ToString(-1), } s.Pop(1) // Remove error message return err } // For lua_pcall, the function and arguments are popped before results are pushed // So we don't consider it an underflow if the new top is less than the original if status == 0 && s.GetType(-1) == TypeFunction { // If we still have a function on the stack, restore original size s.SetTop(top) } return nil } // stackGuard wraps a function with stack checking func stackGuard[T any](s *State, f func() (T, error)) (T, error) { // Save current stack size top := s.GetTop() defer func() { // Only restore if stack is larger than original if s.GetTop() > top { s.SetTop(top) } }() // Run the protected function return f() } // stackGuardValue executes a function with stack protection func stackGuardValue[T any](s *State, f func() (T, error)) (T, error) { return stackGuard(s, f) } // stackGuardErr executes a function that only returns an error with stack protection func stackGuardErr(s *State, f func() error) error { // Save current stack size top := s.GetTop() defer func() { // Only restore if stack is larger than original if s.GetTop() > top { s.SetTop(top) } }() // Run the protected function return f() } // getStackTrace returns the current Lua stack trace func (s *State) getStackTrace() string { // Same implementation... return "" }