Merge pull request #981 from visualfc/reflectlite
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 {
|
func (t rtype) NumMethod() int {
|
||||||
/*
|
tt := t.Type.InterfaceType()
|
||||||
tt := t.Type.InterfaceType()
|
if tt != nil {
|
||||||
if tt != nil {
|
return tt.NumMethod()
|
||||||
return tt.NumMethod()
|
}
|
||||||
}
|
return len(t.exportedMethods())
|
||||||
return len(t.exportedMethods())
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.NumMethod")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) PkgPath() string {
|
func (t rtype) PkgPath() string {
|
||||||
/*
|
if t.TFlag&abi.TFlagNamed == 0 {
|
||||||
if t.TFlag&abi.TFlagNamed == 0 {
|
return ""
|
||||||
return ""
|
}
|
||||||
}
|
ut := t.uncommon()
|
||||||
ut := t.uncommon()
|
if ut == nil {
|
||||||
if ut == nil {
|
return ""
|
||||||
return ""
|
}
|
||||||
}
|
return ut.PkgPath_
|
||||||
return t.nameOff(ut.PkgPath).Name()
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.PkgPath")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) Name() string {
|
func (t rtype) Name() string {
|
||||||
/*
|
if !t.HasName() {
|
||||||
if !t.HasName() {
|
return ""
|
||||||
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--
|
||||||
i := len(s) - 1
|
}
|
||||||
sqBrackets := 0
|
return s[i+1:]
|
||||||
for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
|
|
||||||
switch s[i] {
|
|
||||||
case ']':
|
|
||||||
sqBrackets++
|
|
||||||
case '[':
|
|
||||||
sqBrackets--
|
|
||||||
}
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
return s[i+1:]
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.Name")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toRType(t *abi.Type) rtype {
|
func toRType(t *abi.Type) rtype {
|
||||||
@@ -213,14 +204,11 @@ func (t rtype) Elem() Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) In(i int) Type {
|
func (t rtype) In(i int) Type {
|
||||||
/*
|
tt := t.Type.FuncType()
|
||||||
tt := t.Type.FuncType()
|
if tt == nil {
|
||||||
if tt == nil {
|
panic("reflect: In of non-func type")
|
||||||
panic("reflect: In of non-func type")
|
}
|
||||||
}
|
return toType(tt.In[i])
|
||||||
return toType(tt.InSlice()[i])
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.In")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) Key() Type {
|
func (t rtype) Key() Type {
|
||||||
@@ -248,36 +236,27 @@ func (t rtype) NumField() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) NumIn() int {
|
func (t rtype) NumIn() int {
|
||||||
/*
|
tt := t.Type.FuncType()
|
||||||
tt := t.Type.FuncType()
|
if tt == nil {
|
||||||
if tt == nil {
|
panic("reflect: NumIn of non-func type")
|
||||||
panic("reflect: NumIn of non-func type")
|
}
|
||||||
}
|
return len(tt.In)
|
||||||
return int(tt.InCount)
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.NumIn")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) NumOut() int {
|
func (t rtype) NumOut() int {
|
||||||
/*
|
tt := t.Type.FuncType()
|
||||||
tt := t.Type.FuncType()
|
if tt == nil {
|
||||||
if tt == nil {
|
panic("reflect: NumOut of non-func type")
|
||||||
panic("reflect: NumOut of non-func type")
|
}
|
||||||
}
|
return len(tt.Out)
|
||||||
return tt.NumOut()
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.NumOut")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t rtype) Out(i int) Type {
|
func (t rtype) Out(i int) Type {
|
||||||
/*
|
tt := t.Type.FuncType()
|
||||||
tt := t.Type.FuncType()
|
if tt == nil {
|
||||||
if tt == nil {
|
panic("reflect: Out of non-func type")
|
||||||
panic("reflect: Out of non-func type")
|
}
|
||||||
}
|
return toType(tt.Out[i])
|
||||||
return toType(tt.OutSlice()[i])
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.rtype.Out")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add returns p+x.
|
// add returns p+x.
|
||||||
@@ -322,94 +301,9 @@ func (t rtype) Comparable() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// implements reports whether the type V implements the interface type T.
|
// implements reports whether the type V implements the interface type T.
|
||||||
func implements(T, V *abi.Type) bool {
|
//
|
||||||
/*
|
//go:linkname implements github.com/goplus/llgo/runtime/internal/runtime.Implements
|
||||||
t := T.InterfaceType()
|
func implements(T, V *abi.Type) bool
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
// directlyAssignable reports whether a value x of type V can be directly
|
// directlyAssignable reports whether a value x of type V can be directly
|
||||||
// assigned (using memmove) to a value of type T.
|
// assigned (using memmove) to a value of type T.
|
||||||
@@ -460,91 +354,88 @@ func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Composite types.
|
||||||
// Composite types.
|
switch kind {
|
||||||
switch kind {
|
case abi.Array:
|
||||||
case abi.Array:
|
return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||||
return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
|
||||||
|
|
||||||
case abi.Chan:
|
case abi.Chan:
|
||||||
// Special case:
|
// Special case:
|
||||||
// x is a bidirectional channel value, T is a channel type,
|
// x is a bidirectional channel value, T is a channel type,
|
||||||
// and x's type V and T have identical element types.
|
// and x's type V and T have identical element types.
|
||||||
if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
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
|
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
|
// 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/abi"
|
||||||
_ "github.com/goplus/llgo/runtime/internal/runtime"
|
_ "github.com/goplus/llgo/runtime/internal/runtime"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/runtime/goarch"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Value is the reflection interface to a Go value.
|
// 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.
|
// pointer returns the underlying pointer represented by v.
|
||||||
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
|
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
|
||||||
func (v Value) pointer() unsafe.Pointer {
|
func (v Value) pointer() unsafe.Pointer {
|
||||||
/*
|
if v.typ.Size() != goarch.PtrSize || !v.typ.Pointers() {
|
||||||
if v.typ.Size() != goarch.PtrSize || !v.typ.Pointers() {
|
panic("can't call pointer on a non-pointer Value")
|
||||||
panic("can't call pointer on a non-pointer Value")
|
}
|
||||||
}
|
if v.flag&flagIndir != 0 {
|
||||||
if v.flag&flagIndir != 0 {
|
return *(*unsafe.Pointer)(v.ptr)
|
||||||
return *(*unsafe.Pointer)(v.ptr)
|
}
|
||||||
}
|
return v.ptr
|
||||||
return v.ptr
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.Value.pointer")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// packEface converts v to the empty interface.
|
// packEface converts v to the empty interface.
|
||||||
@@ -147,6 +145,9 @@ func unpackEface(i any) Value {
|
|||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
f := flag(t.Kind())
|
f := flag(t.Kind())
|
||||||
|
if t.IsClosure() {
|
||||||
|
f = flag(abi.Func)
|
||||||
|
}
|
||||||
if ifaceIndir(t) {
|
if ifaceIndir(t) {
|
||||||
f |= flagIndir
|
f |= flagIndir
|
||||||
}
|
}
|
||||||
@@ -229,41 +230,38 @@ func (v Value) CanSet() bool {
|
|||||||
// It panics if v's Kind is not Interface or Pointer.
|
// It panics if v's Kind is not Interface or Pointer.
|
||||||
// It returns the zero Value if v is nil.
|
// It returns the zero Value if v is nil.
|
||||||
func (v Value) Elem() Value {
|
func (v Value) Elem() Value {
|
||||||
/*
|
k := v.kind()
|
||||||
k := v.kind()
|
switch k {
|
||||||
switch k {
|
case abi.Interface:
|
||||||
case abi.Interface:
|
var eface any
|
||||||
var eface any
|
if v.typ.NumMethod() == 0 {
|
||||||
if v.typ.NumMethod() == 0 {
|
eface = *(*any)(v.ptr)
|
||||||
eface = *(*any)(v.ptr)
|
} else {
|
||||||
} else {
|
eface = (any)(*(*interface {
|
||||||
eface = (any)(*(*interface {
|
M()
|
||||||
M()
|
})(v.ptr))
|
||||||
})(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}
|
|
||||||
}
|
}
|
||||||
panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
|
x := unpackEface(eface)
|
||||||
*/
|
if x.flag != 0 {
|
||||||
panic("todo: reflectlite.Value.Elem")
|
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 {
|
func valueInterface(v Value) any {
|
||||||
@@ -329,11 +327,11 @@ func (v Value) Kind() Kind {
|
|||||||
return v.kind()
|
return v.kind()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO(xsw):
|
//go:linkname chanlen github.com/goplus/llgo/runtime/internal/runtime.ChanLen
|
||||||
// implemented in runtime:
|
func chanlen(ch unsafe.Pointer) int
|
||||||
func chanlen(unsafe.Pointer) int
|
|
||||||
func maplen(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.
|
// Len returns v's length.
|
||||||
// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
|
// 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:
|
case abi.Array:
|
||||||
tt := (*arrayType)(unsafe.Pointer(v.typ))
|
tt := (*arrayType)(unsafe.Pointer(v.typ))
|
||||||
return int(tt.Len)
|
return int(tt.Len)
|
||||||
/* TODO(xsw):
|
case abi.Chan:
|
||||||
case abi.Chan:
|
return chanlen(v.pointer())
|
||||||
return chanlen(v.pointer())
|
case abi.Map:
|
||||||
case abi.Map:
|
return maplen(v.pointer())
|
||||||
return maplen(v.pointer())
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
panic(&ValueError{"reflect.Value.Len", v.kind()})
|
panic(&ValueError{"reflect.Value.Len", v.kind()})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumMethod returns the number of exported methods in the value's method set.
|
// NumMethod returns the number of exported methods in the value's method set.
|
||||||
func (v Value) numMethod() int {
|
func (v Value) numMethod() int {
|
||||||
/*
|
if v.typ == nil {
|
||||||
if v.typ == nil {
|
panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
|
||||||
panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
|
}
|
||||||
}
|
return v.typ.NumMethod()
|
||||||
return v.typ.NumMethod()
|
|
||||||
*/
|
|
||||||
panic("todo: reflectlite.Value.numMethod")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set assigns x to the value v.
|
// Set assigns x to the value v.
|
||||||
@@ -394,10 +387,18 @@ func (v Value) Type() Type {
|
|||||||
if f == 0 {
|
if f == 0 {
|
||||||
panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
|
panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
|
||||||
}
|
}
|
||||||
|
// closure func
|
||||||
|
if v.typ.IsClosure() {
|
||||||
|
return toRType(&v.closureFunc().Type)
|
||||||
|
}
|
||||||
// Method values not supported.
|
// Method values not supported.
|
||||||
return toRType(v.typ)
|
return toRType(v.typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Value) closureFunc() *abi.FuncType {
|
||||||
|
return v.typ.StructType().Fields[0].Typ.FuncType()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* constructors
|
* 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.
|
// Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
|
||||||
return Value{dst, nil, flag(abi.Interface)}
|
return Value{dst, nil, flag(abi.Interface)}
|
||||||
}
|
}
|
||||||
/* TODO(xsw):
|
|
||||||
x := valueInterface(v)
|
x := valueInterface(v)
|
||||||
if dst.NumMethod() == 0 {
|
if dst.NumMethod() == 0 {
|
||||||
*(*any)(target) = x
|
*(*any)(target) = x
|
||||||
@@ -449,13 +449,10 @@ func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Va
|
|||||||
ifaceE2I(dst, x, target)
|
ifaceE2I(dst, x, target)
|
||||||
}
|
}
|
||||||
return Value{dst, target, flagIndir | flag(abi.Interface)}
|
return Value{dst, target, flagIndir | flag(abi.Interface)}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed.
|
// Failed.
|
||||||
// TODO(xsw):
|
panic(context + ": value of type " + toRType(v.typ).String() + " is not assignable to type " + toRType(dst).String())
|
||||||
// panic(context + ": value of type " + toRType(v.typ).String() + " is not assignable to type " + toRType(dst).String())
|
|
||||||
panic("todo: reflectlite.Value.assignTo")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// arrayAt returns the i-th element of p,
|
// 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")
|
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.
|
// 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 {
|
func (t *rtype) Implements(u Type) bool {
|
||||||
/*
|
if u == nil {
|
||||||
if u == nil {
|
panic("reflect: nil type passed to Type.Implements")
|
||||||
panic("reflect: nil type passed to Type.Implements")
|
}
|
||||||
}
|
if u.Kind() != Interface {
|
||||||
if u.Kind() != Interface {
|
panic("reflect: non-interface type passed to Type.Implements")
|
||||||
panic("reflect: non-interface type passed to Type.Implements")
|
}
|
||||||
}
|
return implements(u.common(), t.common())
|
||||||
return implements(u.common(), t.common())
|
|
||||||
*/
|
|
||||||
panic("todo: reflect.rtype.Implements")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *rtype) AssignableTo(u Type) bool {
|
func (t *rtype) AssignableTo(u Type) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user