mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
reflect: add missing iterator methods
This commit is contained in:
@@ -8,6 +8,31 @@ import (
|
||||
"iter"
|
||||
)
|
||||
|
||||
// Fields returns an iterator over each StructField of v along with its Value.
|
||||
func (v Value) Fields() iter.Seq2[StructField, Value] {
|
||||
if v.Kind() != Struct {
|
||||
panic(&ValueError{Method: "reflect.Value.Fields", Kind: v.Kind()})
|
||||
}
|
||||
return func(yield func(StructField, Value) bool) {
|
||||
for i, n := 0, v.NumField(); i < n; i++ {
|
||||
if !yield(v.Type().Field(i), v.Field(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Methods returns an iterator over each Method of v along with its Value.
|
||||
func (v Value) Methods() iter.Seq2[Method, Value] {
|
||||
return func(yield func(Method, Value) bool) {
|
||||
for i, n := 0, v.NumMethod(); i < n; i++ {
|
||||
if !yield(v.Type().Method(i), v.Method(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rangeNum[T int8 | int16 | int32 | int64 | int |
|
||||
uint8 | uint16 | uint32 | uint64 | uint |
|
||||
uintptr, N int64 | uint64](num N, t Type) iter.Seq[Value] {
|
||||
|
||||
@@ -383,6 +383,45 @@ func TestValueSeq2(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueFields(t *testing.T) {
|
||||
type T struct {
|
||||
First int
|
||||
Second string
|
||||
Third bool
|
||||
}
|
||||
v := ValueOf(T{First: 10, Second: "visible", Third: true})
|
||||
|
||||
names := []string{"First", "Second", "Third"}
|
||||
values := []any{10, "visible", true}
|
||||
var count int
|
||||
for field, value := range v.Fields() {
|
||||
if field.Name != names[count] {
|
||||
t.Fatalf("field %d name = %q, want %q", count, field.Name, names[count])
|
||||
}
|
||||
if field.Index[0] != count {
|
||||
t.Fatalf("field %d index = %v, want [%d]", count, field.Index, count)
|
||||
}
|
||||
if got := value.Interface(); got != values[count] {
|
||||
t.Fatalf("field %d value = %v, want %v", count, got, values[count])
|
||||
}
|
||||
count++
|
||||
}
|
||||
if count != len(names) {
|
||||
t.Fatalf("field count = %d, want %d", count, len(names))
|
||||
}
|
||||
|
||||
count = 0
|
||||
for field := range v.Type().Fields() {
|
||||
if field.Name != names[count] {
|
||||
t.Fatalf("type field %d name = %q, want %q", count, field.Name, names[count])
|
||||
}
|
||||
count++
|
||||
}
|
||||
if count != len(names) {
|
||||
t.Fatalf("type field count = %d, want %d", count, len(names))
|
||||
}
|
||||
}
|
||||
|
||||
// methodIter is a type from which we can derive a method
|
||||
// value that is an iter.Seq.
|
||||
type methodIter struct{}
|
||||
|
||||
@@ -65,6 +65,7 @@ package reflect
|
||||
|
||||
import (
|
||||
"internal/reflectlite"
|
||||
"iter"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -265,6 +266,10 @@ type Type interface {
|
||||
// It panics if i is not in the range [0, NumField()).
|
||||
Field(i int) StructField
|
||||
|
||||
// Fields returns an iterator over each struct field for struct type t.
|
||||
// It panics if the type's Kind is not Struct.
|
||||
Fields() iter.Seq[StructField]
|
||||
|
||||
// FieldByIndex returns the nested field corresponding
|
||||
// to the index sequence. It is equivalent to calling Field
|
||||
// successively for each index i.
|
||||
@@ -294,6 +299,10 @@ type Type interface {
|
||||
// It panics if i is not in the range [0, NumIn()).
|
||||
In(i int) Type
|
||||
|
||||
// Ins returns an iterator over each input parameter of function type t.
|
||||
// It panics if the type's Kind is not Func.
|
||||
Ins() iter.Seq[Type]
|
||||
|
||||
// Key returns a map type's key type.
|
||||
// It panics if the type's Kind is not Map.
|
||||
Key() Type
|
||||
@@ -319,6 +328,10 @@ type Type interface {
|
||||
// It panics if i is not in the range [0, NumOut()).
|
||||
Out(i int) Type
|
||||
|
||||
// Outs returns an iterator over each output parameter of function type t.
|
||||
// It panics if the type's Kind is not Func.
|
||||
Outs() iter.Seq[Type]
|
||||
|
||||
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
|
||||
// It panics if t's Kind is not Complex64 or Complex128.
|
||||
OverflowComplex(x complex128) bool
|
||||
@@ -340,6 +353,9 @@ type Type interface {
|
||||
|
||||
// CanSeq2 reports whether a [Value] with this type can be iterated over using [Value.Seq2].
|
||||
CanSeq2() bool
|
||||
|
||||
// Methods returns an iterator over each method in the type's method set.
|
||||
Methods() iter.Seq[Method]
|
||||
}
|
||||
|
||||
type rawType struct {
|
||||
@@ -414,6 +430,16 @@ func (t *rawType) Field(i int) StructField {
|
||||
return toStructField(f)
|
||||
}
|
||||
|
||||
func (t *rawType) Fields() iter.Seq[StructField] {
|
||||
return func(yield func(StructField) bool) {
|
||||
for i, n := 0, t.NumField(); i < n; i++ {
|
||||
if !yield(t.Field(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *rawType) FieldByIndex(index []int) StructField {
|
||||
f := t.RawType.FieldByIndex(index)
|
||||
return toStructField(f)
|
||||
@@ -437,6 +463,16 @@ func (t *rawType) In(i int) Type {
|
||||
panic("unimplemented: (reflect.Type).In()")
|
||||
}
|
||||
|
||||
func (t *rawType) Ins() iter.Seq[Type] {
|
||||
return func(yield func(Type) bool) {
|
||||
for i, n := 0, t.NumIn(); i < n; i++ {
|
||||
if !yield(t.In(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *rawType) IsVariadic() bool {
|
||||
panic("unimplemented: (reflect.Type).IsVariadic()")
|
||||
}
|
||||
@@ -453,6 +489,16 @@ func (t *rawType) MethodByName(name string) (Method, bool) {
|
||||
panic("unimplemented: (reflect.Type).MethodByName()")
|
||||
}
|
||||
|
||||
func (t *rawType) Methods() iter.Seq[Method] {
|
||||
return func(yield func(Method) bool) {
|
||||
for i, n := 0, t.NumMethod(); i < n; i++ {
|
||||
if !yield(t.Method(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *rawType) NumIn() int {
|
||||
panic("unimplemented: (reflect.Type).NumIn()")
|
||||
}
|
||||
@@ -465,6 +511,16 @@ func (t *rawType) Out(i int) Type {
|
||||
panic("unimplemented: (reflect.Type).Out()")
|
||||
}
|
||||
|
||||
func (t *rawType) Outs() iter.Seq[Type] {
|
||||
return func(yield func(Type) bool) {
|
||||
for i, n := 0, t.NumOut(); i < n; i++ {
|
||||
if !yield(t.Out(i)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A StructField describes a single field in a struct.
|
||||
// This must be kept in sync with [reflectlite.StructField].
|
||||
type StructField struct {
|
||||
|
||||
Reference in New Issue
Block a user