85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
package luar
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/yuin/gopher-lua"
|
|
)
|
|
|
|
func checkStruct(L *lua.LState, idx int) reflect.Value {
|
|
ud := L.CheckUserData(idx)
|
|
ref := reflect.ValueOf(ud.Value)
|
|
if ref.Kind() != reflect.Struct {
|
|
L.ArgError(idx, "expecting struct")
|
|
}
|
|
return ref
|
|
}
|
|
|
|
func structIndex(L *lua.LState) int {
|
|
ref := checkStruct(L, 1)
|
|
refType := ref.Type()
|
|
|
|
// Check for method
|
|
key := L.OptString(2, "")
|
|
exKey := getExportedName(key)
|
|
if exKey != "" {
|
|
if method, ok := refType.MethodByName(exKey); ok {
|
|
L.Push(New(L, method.Func.Interface()))
|
|
return 1
|
|
}
|
|
}
|
|
|
|
// Check for field
|
|
if field := ref.FieldByName(exKey); field.IsValid() {
|
|
if !field.CanInterface() {
|
|
L.RaiseError("cannot interface field " + exKey)
|
|
}
|
|
L.Push(New(L, field.Interface()))
|
|
return 1
|
|
}
|
|
|
|
if ret := metaFunction(L, luarIndexFunc, ref); ret >= 0 {
|
|
return ret
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func structNewIndex(L *lua.LState) int {
|
|
ref := checkStruct(L, 1)
|
|
key := L.OptString(2, "")
|
|
value := L.CheckAny(3)
|
|
|
|
if key == "" {
|
|
if ret := metaFunction(L, luarNewIndexFunc, ref); ret >= 0 {
|
|
return ret
|
|
}
|
|
L.TypeError(2, lua.LTString)
|
|
return 0
|
|
}
|
|
|
|
exKey := getExportedName(key)
|
|
|
|
field := ref.FieldByName(exKey)
|
|
if !field.IsValid() {
|
|
if ret := metaFunction(L, luarNewIndexFunc, ref); ret >= 0 {
|
|
return ret
|
|
}
|
|
L.ArgError(2, "unknown field "+exKey)
|
|
}
|
|
if !field.CanSet() {
|
|
L.ArgError(2, "cannot set field "+exKey)
|
|
}
|
|
field.Set(lValueToReflect(value, field.Type()))
|
|
|
|
return 0
|
|
}
|
|
|
|
func structCall(L *lua.LState) int {
|
|
ref := checkStruct(L, 1)
|
|
if ret := metaFunction(L, luarCallFunc, ref); ret >= 0 {
|
|
return ret
|
|
}
|
|
L.RaiseError("attempt to call a non-function object")
|
|
return 0
|
|
}
|