153 lines
2.9 KiB
Go
153 lines
2.9 KiB
Go
package luajit
|
|
|
|
/*
|
|
#include <lua.h>
|
|
*/
|
|
import "C"
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
// LuaType represents Lua value types
|
|
type LuaType int
|
|
|
|
const (
|
|
// These constants match lua.h's LUA_T* values
|
|
TypeNone LuaType = -1
|
|
TypeNil LuaType = 0
|
|
TypeBoolean LuaType = 1
|
|
TypeLightUserData LuaType = 2
|
|
TypeNumber LuaType = 3
|
|
TypeString LuaType = 4
|
|
TypeTable LuaType = 5
|
|
TypeFunction LuaType = 6
|
|
TypeUserData LuaType = 7
|
|
TypeThread LuaType = 8
|
|
)
|
|
|
|
// String returns the string representation of the Lua type
|
|
func (t LuaType) String() string {
|
|
switch t {
|
|
case TypeNone:
|
|
return "none"
|
|
case TypeNil:
|
|
return "nil"
|
|
case TypeBoolean:
|
|
return "boolean"
|
|
case TypeLightUserData:
|
|
return "lightuserdata"
|
|
case TypeNumber:
|
|
return "number"
|
|
case TypeString:
|
|
return "string"
|
|
case TypeTable:
|
|
return "table"
|
|
case TypeFunction:
|
|
return "function"
|
|
case TypeUserData:
|
|
return "userdata"
|
|
case TypeThread:
|
|
return "thread"
|
|
default:
|
|
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)
|
|
}
|