route/vendor/layeh.com/gopher-luar/ptr.go

77 lines
1.4 KiB
Go

package luar
import (
"reflect"
"github.com/yuin/gopher-lua"
)
func checkPtr(L *lua.LState, idx int) (ref reflect.Value, mt *Metatable) {
ud := L.CheckUserData(idx)
ref = reflect.ValueOf(ud.Value)
kind := reflect.Ptr
if ref.Kind() != kind {
L.ArgError(idx, "expecting "+kind.String())
}
mt = &Metatable{LTable: ud.Metatable.(*lua.LTable)}
return
}
func ptrIndex(L *lua.LState) int {
ref, mt := checkPtr(L, 1)
key := L.CheckString(2)
if fn := mt.method(key); fn != nil {
L.Push(fn)
return 1
}
// fallback to non-pointer method
ref = ref.Elem()
mt = MT(L, ref.Interface())
if fn := mt.method(key); fn != nil {
L.Push(fn)
return 1
}
return 0
}
func ptrPow(L *lua.LState) int {
ref, _ := checkPtr(L, 1)
val := L.CheckAny(2)
if ref.IsNil() {
L.RaiseError("cannot dereference nil pointer")
}
elem := ref.Elem()
if !elem.CanSet() {
L.RaiseError("unable to set pointer value")
}
value, err := lValueToReflect(L, val, elem.Type(), nil)
if err != nil {
L.ArgError(2, err.Error())
}
elem.Set(value)
L.SetTop(1)
return 1
}
func ptrUnm(L *lua.LState) int {
ref, _ := checkPtr(L, 1)
elem := ref.Elem()
if !elem.CanInterface() {
L.RaiseError("cannot interface pointer type " + elem.String())
}
L.Push(New(L, elem.Interface()))
return 1
}
func ptrEq(L *lua.LState) int {
ref1, _ := checkPtr(L, 1)
ref2, _ := checkPtr(L, 2)
L.Push(lua.LBool(ref1.Pointer() == ref2.Pointer()))
return 1
}