File: iter.go

package info (click to toggle)
golang-starlark 0.0~git20240725.42030a7-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 1,296 kB
  • sloc: makefile: 8; sh: 8
file content (118 lines) | stat: -rw-r--r-- 2,923 bytes parent folder | download | duplicates (2)
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
			}
		}
	}
}