124 lines
2.6 KiB
Go
124 lines
2.6 KiB
Go
package luajit
|
|
|
|
/*
|
|
#include <lua.h>
|
|
#include <lauxlib.h>
|
|
*/
|
|
import "C"
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// LuaError represents an enhanced error from the Lua state
|
|
type LuaError struct {
|
|
Code int
|
|
Message string
|
|
File string
|
|
Line int
|
|
StackTrace string
|
|
Context string
|
|
}
|
|
|
|
func (e *LuaError) Error() string {
|
|
var parts []string
|
|
|
|
if e.File != "" && e.Line > 0 {
|
|
parts = append(parts, fmt.Sprintf("%s:%d", e.File, e.Line))
|
|
}
|
|
|
|
if e.Context != "" {
|
|
parts = append(parts, fmt.Sprintf("[%s]", e.Context))
|
|
}
|
|
|
|
parts = append(parts, e.Message)
|
|
|
|
if e.Code != 0 {
|
|
parts = append(parts, fmt.Sprintf("(code=%d)", e.Code))
|
|
}
|
|
|
|
result := strings.Join(parts, " ")
|
|
|
|
if e.StackTrace != "" {
|
|
result += "\n" + e.StackTrace
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// 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
|
|
)
|
|
|
|
// GetStackTrace returns the current Lua stack trace
|
|
func (s *State) GetStackTrace() string {
|
|
s.GetGlobal("debug")
|
|
if !s.IsTable(-1) {
|
|
s.Pop(1)
|
|
return "debug table not available"
|
|
}
|
|
|
|
s.GetField(-1, "traceback")
|
|
if !s.IsFunction(-1) {
|
|
s.Pop(2) // Remove debug table and non-function
|
|
return "debug.traceback not available"
|
|
}
|
|
|
|
s.Call(0, 1)
|
|
trace := s.ToString(-1)
|
|
s.Pop(1) // Remove the trace
|
|
|
|
return trace
|
|
}
|
|
|
|
// GetErrorInfo extracts detailed error information from the Lua stack
|
|
func (s *State) GetErrorInfo(context string) *LuaError {
|
|
if s.GetTop() == 0 {
|
|
return &LuaError{
|
|
Message: "unknown error (empty stack)",
|
|
Context: context,
|
|
}
|
|
}
|
|
|
|
message := s.ToString(-1)
|
|
|
|
// Parse file:line from common Lua error format
|
|
var file string
|
|
var line int
|
|
|
|
if colonPos := strings.Index(message, ":"); colonPos > 0 {
|
|
beforeColon := message[:colonPos]
|
|
afterColon := message[colonPos+1:]
|
|
|
|
if secondColonPos := strings.Index(afterColon, ":"); secondColonPos > 0 {
|
|
file = beforeColon
|
|
if n, err := fmt.Sscanf(afterColon[:secondColonPos], "%d", &line); n == 1 && err == nil {
|
|
// Strip the file:line part from message for cleaner display
|
|
message = strings.TrimSpace(afterColon[secondColonPos+1:])
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get stack trace
|
|
stackTrace := s.GetStackTrace()
|
|
|
|
return &LuaError{
|
|
Message: message,
|
|
File: file,
|
|
Line: line,
|
|
StackTrace: stackTrace,
|
|
Context: context,
|
|
}
|
|
}
|
|
|
|
// CreateLuaError creates a LuaError with full context information
|
|
func (s *State) CreateLuaError(code int, context string) *LuaError {
|
|
err := s.GetErrorInfo(context)
|
|
err.Code = code
|
|
return err
|
|
}
|