diff --git a/types.go b/types.go index 48b4559..1498059 100644 --- a/types.go +++ b/types.go @@ -4,6 +4,10 @@ package luajit #include */ import "C" +import ( + "fmt" + "strconv" +) // LuaType represents Lua value types type LuaType int @@ -49,3 +53,100 @@ func (t LuaType) String() string { return "unknown" } } + +// ConvertValue converts a value to the requested type with proper type conversion +func ConvertValue[T any](value any) (T, bool) { + var zero T + + // Handle nil case + if value == nil { + return zero, false + } + + // Try direct type assertion first + if result, ok := value.(T); ok { + return result, true + } + + // Type-specific conversions + switch any(zero).(type) { + case string: + switch v := value.(type) { + case float64: + return any(fmt.Sprintf("%g", v)).(T), true + case int: + return any(strconv.Itoa(v)).(T), true + case bool: + if v { + return any("true").(T), true + } + return any("false").(T), true + } + case int: + switch v := value.(type) { + case float64: + return any(int(v)).(T), true + case string: + if i, err := strconv.Atoi(v); err == nil { + return any(i).(T), true + } + case bool: + if v { + return any(1).(T), true + } + return any(0).(T), true + } + case float64: + switch v := value.(type) { + case int: + return any(float64(v)).(T), true + case string: + if f, err := strconv.ParseFloat(v, 64); err == nil { + return any(f).(T), true + } + case bool: + if v { + return any(1.0).(T), true + } + return any(0.0).(T), true + } + case bool: + switch v := value.(type) { + case string: + switch v { + case "true", "yes", "1": + return any(true).(T), true + case "false", "no", "0": + return any(false).(T), true + } + case int: + return any(v != 0).(T), true + case float64: + return any(v != 0).(T), true + } + } + + return zero, false +} + +// GetTypedValue gets a value from the state with type conversion +func GetTypedValue[T any](s *State, index int) (T, bool) { + var zero T + + // Get the value as any type + value, err := s.ToValue(index) + if err != nil { + return zero, false + } + + // Convert it to the requested type + return ConvertValue[T](value) +} + +// GetGlobalTyped gets a global variable with type conversion +func GetGlobalTyped[T any](s *State, name string) (T, bool) { + s.GetGlobal(name) + defer s.Pop(1) + + return GetTypedValue[T](s, -1) +}