1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// Copyright 2024 The Bazel Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.23
package starlark
import (
"fmt"
"iter"
)
func (d *Dict) Entries() iter.Seq2[Value, Value] { return d.ht.entries }
// Elements returns a go1.23 iterator over the elements of the list.
//
// Example:
//
// for elem := range list.Elements() { ... }
func (l *List) Elements() iter.Seq[Value] {
return func(yield func(Value) bool) {
if !l.frozen {
l.itercount++
defer func() { l.itercount-- }()
}
for _, x := range l.elems {
if !yield(x) {
break
}
}
}
}
// Elements returns a go1.23 iterator over the elements of the tuple.
//
// (A Tuple is a slice, so it is of course directly iterable. This
// method exists to provide a fast path for the [Elements] standalone
// function.)
func (t Tuple) Elements() iter.Seq[Value] {
return func(yield func(Value) bool) {
for _, x := range t {
if !yield(x) {
break
}
}
}
}
func (s *Set) Elements() iter.Seq[Value] {
return func(yield func(k Value) bool) {
s.ht.entries(func(k, _ Value) bool { return yield(k) })
}
}
// Elements returns an iterator for the elements of the iterable value.
//
// Example of go1.23 iteration:
//
// for elem := range Elements(iterable) { ... }
//
// Push iterators are provided as a convenience for Go client code. The
// core iteration behavior of Starlark for-loops is defined by the
// [Iterable] interface.
func Elements(iterable Iterable) iter.Seq[Value] {
// Use specialized push iterator if available (*List, Tuple, *Set).
type hasElements interface {
Elements() iter.Seq[Value]
}
if iterable, ok := iterable.(hasElements); ok {
return iterable.Elements()
}
iter := iterable.Iterate()
return func(yield func(Value) bool) {
defer iter.Done()
var x Value
for iter.Next(&x) && yield(x) {
}
}
}
// Entries returns an iterator over the entries (key/value pairs) of
// the iterable mapping.
//
// Example of go1.23 iteration:
//
// for k, v := range Entries(mapping) { ... }
//
// Push iterators are provided as a convenience for Go client code. The
// core iteration behavior of Starlark for-loops is defined by the
// [Iterable] interface.
func Entries(mapping IterableMapping) iter.Seq2[Value, Value] {
// If available (e.g. *Dict), use specialized push iterator,
// as it gets k and v in one shot.
type hasEntries interface {
Entries() iter.Seq2[Value, Value]
}
if mapping, ok := mapping.(hasEntries); ok {
return mapping.Entries()
}
iter := mapping.Iterate()
return func(yield func(k, v Value) bool) {
defer iter.Done()
var k Value
for iter.Next(&k) {
v, found, err := mapping.Get(k)
if err != nil || !found {
panic(fmt.Sprintf("Iterate and Get are inconsistent (mapping=%v, key=%v)",
mapping.Type(), k.Type()))
}
if !yield(k, v) {
break
}
}
}
}
|