runtime/internal/lib/reflectlite: implement func
This commit is contained in:
@@ -150,50 +150,41 @@ func (t rtype) exportedMethods() []abi.Method {
|
||||
}
|
||||
|
||||
func (t rtype) NumMethod() int {
|
||||
/*
|
||||
tt := t.Type.InterfaceType()
|
||||
if tt != nil {
|
||||
return tt.NumMethod()
|
||||
}
|
||||
return len(t.exportedMethods())
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.NumMethod")
|
||||
tt := t.Type.InterfaceType()
|
||||
if tt != nil {
|
||||
return tt.NumMethod()
|
||||
}
|
||||
return len(t.exportedMethods())
|
||||
}
|
||||
|
||||
func (t rtype) PkgPath() string {
|
||||
/*
|
||||
if t.TFlag&abi.TFlagNamed == 0 {
|
||||
return ""
|
||||
}
|
||||
ut := t.uncommon()
|
||||
if ut == nil {
|
||||
return ""
|
||||
}
|
||||
return t.nameOff(ut.PkgPath).Name()
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.PkgPath")
|
||||
if t.TFlag&abi.TFlagNamed == 0 {
|
||||
return ""
|
||||
}
|
||||
ut := t.uncommon()
|
||||
if ut == nil {
|
||||
return ""
|
||||
}
|
||||
return ut.PkgPath_
|
||||
}
|
||||
|
||||
func (t rtype) Name() string {
|
||||
/*
|
||||
if !t.HasName() {
|
||||
return ""
|
||||
if !t.HasName() {
|
||||
return ""
|
||||
}
|
||||
s := t.String()
|
||||
i := len(s) - 1
|
||||
sqBrackets := 0
|
||||
for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
|
||||
switch s[i] {
|
||||
case ']':
|
||||
sqBrackets++
|
||||
case '[':
|
||||
sqBrackets--
|
||||
}
|
||||
s := t.String()
|
||||
i := len(s) - 1
|
||||
sqBrackets := 0
|
||||
for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
|
||||
switch s[i] {
|
||||
case ']':
|
||||
sqBrackets++
|
||||
case '[':
|
||||
sqBrackets--
|
||||
}
|
||||
i--
|
||||
}
|
||||
return s[i+1:]
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.Name")
|
||||
i--
|
||||
}
|
||||
return s[i+1:]
|
||||
}
|
||||
|
||||
func toRType(t *abi.Type) rtype {
|
||||
@@ -213,14 +204,11 @@ func (t rtype) Elem() Type {
|
||||
}
|
||||
|
||||
func (t rtype) In(i int) Type {
|
||||
/*
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: In of non-func type")
|
||||
}
|
||||
return toType(tt.InSlice()[i])
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.In")
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: In of non-func type")
|
||||
}
|
||||
return toType(tt.In[i])
|
||||
}
|
||||
|
||||
func (t rtype) Key() Type {
|
||||
@@ -248,36 +236,27 @@ func (t rtype) NumField() int {
|
||||
}
|
||||
|
||||
func (t rtype) NumIn() int {
|
||||
/*
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumIn of non-func type")
|
||||
}
|
||||
return int(tt.InCount)
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.NumIn")
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumIn of non-func type")
|
||||
}
|
||||
return len(tt.In)
|
||||
}
|
||||
|
||||
func (t rtype) NumOut() int {
|
||||
/*
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumOut of non-func type")
|
||||
}
|
||||
return tt.NumOut()
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.NumOut")
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumOut of non-func type")
|
||||
}
|
||||
return len(tt.Out)
|
||||
}
|
||||
|
||||
func (t rtype) Out(i int) Type {
|
||||
/*
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: Out of non-func type")
|
||||
}
|
||||
return toType(tt.OutSlice()[i])
|
||||
*/
|
||||
panic("todo: reflectlite.rtype.Out")
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: Out of non-func type")
|
||||
}
|
||||
return toType(tt.Out[i])
|
||||
}
|
||||
|
||||
// add returns p+x.
|
||||
@@ -322,94 +301,9 @@ func (t rtype) Comparable() bool {
|
||||
}
|
||||
|
||||
// implements reports whether the type V implements the interface type T.
|
||||
func implements(T, V *abi.Type) bool {
|
||||
/*
|
||||
t := T.InterfaceType()
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
if len(t.Methods) == 0 {
|
||||
return true
|
||||
}
|
||||
rT := toRType(T)
|
||||
rV := toRType(V)
|
||||
|
||||
// The same algorithm applies in both cases, but the
|
||||
// method tables for an interface type and a concrete type
|
||||
// are different, so the code is duplicated.
|
||||
// In both cases the algorithm is a linear scan over the two
|
||||
// lists - T's methods and V's methods - simultaneously.
|
||||
// Since method tables are stored in a unique sorted order
|
||||
// (alphabetical, with no duplicate method names), the scan
|
||||
// through V's methods must hit a match for each of T's
|
||||
// methods along the way, or else V does not implement T.
|
||||
// This lets us run the scan in overall linear time instead of
|
||||
// the quadratic time a naive search would require.
|
||||
// See also ../runtime/iface.go.
|
||||
if V.Kind() == Interface {
|
||||
v := (*interfaceType)(unsafe.Pointer(V))
|
||||
i := 0
|
||||
for j := 0; j < len(v.Methods); j++ {
|
||||
tm := &t.Methods[i]
|
||||
tmName := rT.nameOff(tm.Name)
|
||||
vm := &v.Methods[j]
|
||||
vmName := rV.nameOff(vm.Name)
|
||||
if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
|
||||
if !tmName.IsExported() {
|
||||
tmPkgPath := pkgPath(tmName)
|
||||
if tmPkgPath == "" {
|
||||
tmPkgPath = t.PkgPath.Name()
|
||||
}
|
||||
vmPkgPath := pkgPath(vmName)
|
||||
if vmPkgPath == "" {
|
||||
vmPkgPath = v.PkgPath.Name()
|
||||
}
|
||||
if tmPkgPath != vmPkgPath {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if i++; i >= len(t.Methods) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
v := V.Uncommon()
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
i := 0
|
||||
vmethods := v.Methods()
|
||||
for j := 0; j < int(v.Mcount); j++ {
|
||||
tm := &t.Methods[i]
|
||||
tmName := rT.nameOff(tm.Name)
|
||||
vm := vmethods[j]
|
||||
vmName := rV.nameOff(vm.Name)
|
||||
if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
|
||||
if !tmName.IsExported() {
|
||||
tmPkgPath := pkgPath(tmName)
|
||||
if tmPkgPath == "" {
|
||||
tmPkgPath = t.PkgPath.Name()
|
||||
}
|
||||
vmPkgPath := pkgPath(vmName)
|
||||
if vmPkgPath == "" {
|
||||
vmPkgPath = rV.nameOff(v.PkgPath).Name()
|
||||
}
|
||||
if tmPkgPath != vmPkgPath {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if i++; i >= len(t.Methods) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
*/
|
||||
panic("todo: reflectlite.implements")
|
||||
}
|
||||
//
|
||||
//go:linkname implements github.com/goplus/llgo/runtime/internal/runtime.Implements
|
||||
func implements(T, V *abi.Type) bool
|
||||
|
||||
// directlyAssignable reports whether a value x of type V can be directly
|
||||
// assigned (using memmove) to a value of type T.
|
||||
@@ -460,91 +354,88 @@ func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
// Composite types.
|
||||
switch kind {
|
||||
case abi.Array:
|
||||
return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
// Composite types.
|
||||
switch kind {
|
||||
case abi.Array:
|
||||
return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Chan:
|
||||
// Special case:
|
||||
// x is a bidirectional channel value, T is a channel type,
|
||||
// and x's type V and T have identical element types.
|
||||
if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise continue test for identical underlying type.
|
||||
return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Func:
|
||||
t := (*funcType)(unsafe.Pointer(T))
|
||||
v := (*funcType)(unsafe.Pointer(V))
|
||||
if t.OutCount != v.OutCount || t.InCount != v.InCount {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < t.NumIn(); i++ {
|
||||
if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < t.NumOut(); i++ {
|
||||
if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case Interface:
|
||||
t := (*interfaceType)(unsafe.Pointer(T))
|
||||
v := (*interfaceType)(unsafe.Pointer(V))
|
||||
if len(t.Methods) == 0 && len(v.Methods) == 0 {
|
||||
return true
|
||||
}
|
||||
// Might have the same methods but still
|
||||
// need a run time conversion.
|
||||
return false
|
||||
|
||||
case abi.Map:
|
||||
return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case Ptr, abi.Slice:
|
||||
return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Struct:
|
||||
t := (*structType)(unsafe.Pointer(T))
|
||||
v := (*structType)(unsafe.Pointer(V))
|
||||
if len(t.Fields) != len(v.Fields) {
|
||||
return false
|
||||
}
|
||||
if t.PkgPath.Name() != v.PkgPath.Name() {
|
||||
return false
|
||||
}
|
||||
for i := range t.Fields {
|
||||
tf := &t.Fields[i]
|
||||
vf := &v.Fields[i]
|
||||
if tf.Name.Name() != vf.Name.Name() {
|
||||
return false
|
||||
}
|
||||
if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
|
||||
return false
|
||||
}
|
||||
if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
|
||||
return false
|
||||
}
|
||||
if tf.Offset != vf.Offset {
|
||||
return false
|
||||
}
|
||||
if tf.Embedded() != vf.Embedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case abi.Chan:
|
||||
// Special case:
|
||||
// x is a bidirectional channel value, T is a channel type,
|
||||
// and x's type V and T have identical element types.
|
||||
if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise continue test for identical underlying type.
|
||||
return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Func:
|
||||
t := (*funcType)(unsafe.Pointer(T))
|
||||
v := (*funcType)(unsafe.Pointer(V))
|
||||
if len(t.Out) != len(v.Out) || len(t.In) != len(v.In) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(t.In); i++ {
|
||||
if !haveIdenticalType(t.In[i], v.In[i], cmpTags) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(t.Out); i++ {
|
||||
if !haveIdenticalType(t.Out[i], v.Out[i], cmpTags) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case Interface:
|
||||
t := (*interfaceType)(unsafe.Pointer(T))
|
||||
v := (*interfaceType)(unsafe.Pointer(V))
|
||||
if len(t.Methods) == 0 && len(v.Methods) == 0 {
|
||||
return true
|
||||
}
|
||||
// Might have the same methods but still
|
||||
// need a run time conversion.
|
||||
return false
|
||||
*/
|
||||
panic("todo: reflectlite.haveIdenticalUnderlyingType")
|
||||
|
||||
case abi.Map:
|
||||
return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case Ptr, abi.Slice:
|
||||
return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Struct:
|
||||
t := (*structType)(unsafe.Pointer(T))
|
||||
v := (*structType)(unsafe.Pointer(V))
|
||||
if len(t.Fields) != len(v.Fields) {
|
||||
return false
|
||||
}
|
||||
if t.PkgPath_ != v.PkgPath_ {
|
||||
return false
|
||||
}
|
||||
for i := range t.Fields {
|
||||
tf := &t.Fields[i]
|
||||
vf := &v.Fields[i]
|
||||
if tf.Name_ != vf.Name_ {
|
||||
return false
|
||||
}
|
||||
if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
|
||||
return false
|
||||
}
|
||||
if cmpTags && tf.Tag_ != vf.Tag_ {
|
||||
return false
|
||||
}
|
||||
if tf.Offset != vf.Offset {
|
||||
return false
|
||||
}
|
||||
if tf.Embedded() != vf.Embedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// toType converts from a *rtype to a Type that can be returned
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/goplus/llgo/runtime/abi"
|
||||
_ "github.com/goplus/llgo/runtime/internal/runtime"
|
||||
"github.com/goplus/llgo/runtime/internal/runtime/goarch"
|
||||
)
|
||||
|
||||
// Value is the reflection interface to a Go value.
|
||||
@@ -89,16 +90,13 @@ func (f flag) ro() flag {
|
||||
// pointer returns the underlying pointer represented by v.
|
||||
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
|
||||
func (v Value) pointer() unsafe.Pointer {
|
||||
/*
|
||||
if v.typ.Size() != goarch.PtrSize || !v.typ.Pointers() {
|
||||
panic("can't call pointer on a non-pointer Value")
|
||||
}
|
||||
if v.flag&flagIndir != 0 {
|
||||
return *(*unsafe.Pointer)(v.ptr)
|
||||
}
|
||||
return v.ptr
|
||||
*/
|
||||
panic("todo: reflectlite.Value.pointer")
|
||||
if v.typ.Size() != goarch.PtrSize || !v.typ.Pointers() {
|
||||
panic("can't call pointer on a non-pointer Value")
|
||||
}
|
||||
if v.flag&flagIndir != 0 {
|
||||
return *(*unsafe.Pointer)(v.ptr)
|
||||
}
|
||||
return v.ptr
|
||||
}
|
||||
|
||||
// packEface converts v to the empty interface.
|
||||
@@ -147,6 +145,9 @@ func unpackEface(i any) Value {
|
||||
return Value{}
|
||||
}
|
||||
f := flag(t.Kind())
|
||||
if t.IsClosure() {
|
||||
f = flag(abi.Func)
|
||||
}
|
||||
if ifaceIndir(t) {
|
||||
f |= flagIndir
|
||||
}
|
||||
@@ -229,41 +230,38 @@ func (v Value) CanSet() bool {
|
||||
// It panics if v's Kind is not Interface or Pointer.
|
||||
// It returns the zero Value if v is nil.
|
||||
func (v Value) Elem() Value {
|
||||
/*
|
||||
k := v.kind()
|
||||
switch k {
|
||||
case abi.Interface:
|
||||
var eface any
|
||||
if v.typ.NumMethod() == 0 {
|
||||
eface = *(*any)(v.ptr)
|
||||
} else {
|
||||
eface = (any)(*(*interface {
|
||||
M()
|
||||
})(v.ptr))
|
||||
}
|
||||
x := unpackEface(eface)
|
||||
if x.flag != 0 {
|
||||
x.flag |= v.flag.ro()
|
||||
}
|
||||
return x
|
||||
case abi.Pointer:
|
||||
ptr := v.ptr
|
||||
if v.flag&flagIndir != 0 {
|
||||
ptr = *(*unsafe.Pointer)(ptr)
|
||||
}
|
||||
// The returned value's address is v's value.
|
||||
if ptr == nil {
|
||||
return Value{}
|
||||
}
|
||||
tt := (*ptrType)(unsafe.Pointer(v.typ))
|
||||
typ := tt.Elem
|
||||
fl := v.flag&flagRO | flagIndir | flagAddr
|
||||
fl |= flag(typ.Kind())
|
||||
return Value{typ, ptr, fl}
|
||||
k := v.kind()
|
||||
switch k {
|
||||
case abi.Interface:
|
||||
var eface any
|
||||
if v.typ.NumMethod() == 0 {
|
||||
eface = *(*any)(v.ptr)
|
||||
} else {
|
||||
eface = (any)(*(*interface {
|
||||
M()
|
||||
})(v.ptr))
|
||||
}
|
||||
panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
|
||||
*/
|
||||
panic("todo: reflectlite.Value.Elem")
|
||||
x := unpackEface(eface)
|
||||
if x.flag != 0 {
|
||||
x.flag |= v.flag.ro()
|
||||
}
|
||||
return x
|
||||
case abi.Pointer:
|
||||
ptr := v.ptr
|
||||
if v.flag&flagIndir != 0 {
|
||||
ptr = *(*unsafe.Pointer)(ptr)
|
||||
}
|
||||
// The returned value's address is v's value.
|
||||
if ptr == nil {
|
||||
return Value{}
|
||||
}
|
||||
tt := (*ptrType)(unsafe.Pointer(v.typ))
|
||||
typ := tt.Elem
|
||||
fl := v.flag&flagRO | flagIndir | flagAddr
|
||||
fl |= flag(typ.Kind())
|
||||
return Value{typ, ptr, fl}
|
||||
}
|
||||
panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
|
||||
}
|
||||
|
||||
func valueInterface(v Value) any {
|
||||
@@ -329,11 +327,11 @@ func (v Value) Kind() Kind {
|
||||
return v.kind()
|
||||
}
|
||||
|
||||
/* TODO(xsw):
|
||||
// implemented in runtime:
|
||||
func chanlen(unsafe.Pointer) int
|
||||
func maplen(unsafe.Pointer) int
|
||||
*/
|
||||
//go:linkname chanlen github.com/goplus/llgo/runtime/internal/runtime.ChanLen
|
||||
func chanlen(ch unsafe.Pointer) int
|
||||
|
||||
//go:linkname maplen github.com/goplus/llgo/runtime/internal/runtime.MapLen
|
||||
func maplen(ch unsafe.Pointer) int
|
||||
|
||||
// Len returns v's length.
|
||||
// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
|
||||
@@ -349,25 +347,20 @@ func (v Value) Len() int {
|
||||
case abi.Array:
|
||||
tt := (*arrayType)(unsafe.Pointer(v.typ))
|
||||
return int(tt.Len)
|
||||
/* TODO(xsw):
|
||||
case abi.Chan:
|
||||
return chanlen(v.pointer())
|
||||
case abi.Map:
|
||||
return maplen(v.pointer())
|
||||
*/
|
||||
case abi.Chan:
|
||||
return chanlen(v.pointer())
|
||||
case abi.Map:
|
||||
return maplen(v.pointer())
|
||||
}
|
||||
panic(&ValueError{"reflect.Value.Len", v.kind()})
|
||||
}
|
||||
|
||||
// NumMethod returns the number of exported methods in the value's method set.
|
||||
func (v Value) numMethod() int {
|
||||
/*
|
||||
if v.typ == nil {
|
||||
panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
|
||||
}
|
||||
return v.typ.NumMethod()
|
||||
*/
|
||||
panic("todo: reflectlite.Value.numMethod")
|
||||
if v.typ == nil {
|
||||
panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
|
||||
}
|
||||
return v.typ.NumMethod()
|
||||
}
|
||||
|
||||
// Set assigns x to the value v.
|
||||
@@ -394,10 +387,18 @@ func (v Value) Type() Type {
|
||||
if f == 0 {
|
||||
panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
|
||||
}
|
||||
// closure func
|
||||
if v.typ.IsClosure() {
|
||||
return toRType(&v.closureFunc().Type)
|
||||
}
|
||||
// Method values not supported.
|
||||
return toRType(v.typ)
|
||||
}
|
||||
|
||||
func (v Value) closureFunc() *abi.FuncType {
|
||||
return v.typ.StructType().Fields[0].Typ.FuncType()
|
||||
}
|
||||
|
||||
/*
|
||||
* constructors
|
||||
*/
|
||||
@@ -441,7 +442,6 @@ func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Va
|
||||
// Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
|
||||
return Value{dst, nil, flag(abi.Interface)}
|
||||
}
|
||||
/* TODO(xsw):
|
||||
x := valueInterface(v)
|
||||
if dst.NumMethod() == 0 {
|
||||
*(*any)(target) = x
|
||||
@@ -449,13 +449,10 @@ func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Va
|
||||
ifaceE2I(dst, x, target)
|
||||
}
|
||||
return Value{dst, target, flagIndir | flag(abi.Interface)}
|
||||
*/
|
||||
}
|
||||
|
||||
// Failed.
|
||||
// TODO(xsw):
|
||||
// panic(context + ": value of type " + toRType(v.typ).String() + " is not assignable to type " + toRType(dst).String())
|
||||
panic("todo: reflectlite.Value.assignTo")
|
||||
panic(context + ": value of type " + toRType(v.typ).String() + " is not assignable to type " + toRType(dst).String())
|
||||
}
|
||||
|
||||
// arrayAt returns the i-th element of p,
|
||||
@@ -469,7 +466,8 @@ func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Po
|
||||
return add(p, uintptr(i)*eltSize, "i < len")
|
||||
}
|
||||
|
||||
// func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
|
||||
//go:linkname ifaceE2I github.com/goplus/llgo/runtime/internal/runtime.IfaceE2I
|
||||
func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
|
||||
|
||||
// typedmemmove copies a value of type t to dst from src.
|
||||
//
|
||||
|
||||
@@ -903,16 +903,13 @@ func fnv1(x uint32, list ...byte) uint32 {
|
||||
}
|
||||
|
||||
func (t *rtype) Implements(u Type) bool {
|
||||
/*
|
||||
if u == nil {
|
||||
panic("reflect: nil type passed to Type.Implements")
|
||||
}
|
||||
if u.Kind() != Interface {
|
||||
panic("reflect: non-interface type passed to Type.Implements")
|
||||
}
|
||||
return implements(u.common(), t.common())
|
||||
*/
|
||||
panic("todo: reflect.rtype.Implements")
|
||||
if u == nil {
|
||||
panic("reflect: nil type passed to Type.Implements")
|
||||
}
|
||||
if u.Kind() != Interface {
|
||||
panic("reflect: non-interface type passed to Type.Implements")
|
||||
}
|
||||
return implements(u.common(), t.common())
|
||||
}
|
||||
|
||||
func (t *rtype) AssignableTo(u Type) bool {
|
||||
|
||||
Reference in New Issue
Block a user