Skip to content

Commit ead7e9b

Browse files
committed
[dev.go2go] cmd/compile/internal/syntax: add more parser tests
Updated existing tests to more closely match the go/types tests; added *B.go2 versions for some tests, using [] for type parameters. Change-Id: Ie7cfd9f5515f541d9422a2b2ab8a5d3e02d0499a Reviewed-on: https://go-review.googlesource.com/c/go/+/246261 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent d8b0f3b commit ead7e9b

File tree

6 files changed

+336
-14
lines changed

6 files changed

+336
-14
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package chans
2+
3+
import "runtime"
4+
5+
// Ranger returns a Sender and a Receiver. The Receiver provides a
6+
// Next method to retrieve values. The Sender provides a Send method
7+
// to send values and a Close method to stop sending values. The Next
8+
// method indicates when the Sender has been closed, and the Send
9+
// method indicates when the Receiver has been freed.
10+
//
11+
// This is a convenient way to exit a goroutine sending values when
12+
// the receiver stops reading them.
13+
func Ranger[type T]() (*Sender[T], *Receiver[T]) {
14+
c := make(chan T)
15+
d := make(chan bool)
16+
s := &Sender[T]{values: c, done: d}
17+
r := &Receiver[T]{values: c, done: d}
18+
runtime.SetFinalizer(r, r.finalize)
19+
return s, r
20+
}
21+
22+
// A sender is used to send values to a Receiver.
23+
type Sender[type T] struct {
24+
values chan<- T
25+
done <-chan bool
26+
}
27+
28+
// Send sends a value to the receiver. It returns whether any more
29+
// values may be sent; if it returns false the value was not sent.
30+
func (s *Sender[T]) Send(v T) bool {
31+
select {
32+
case s.values <- v:
33+
return true
34+
case <-s.done:
35+
return false
36+
}
37+
}
38+
39+
// Close tells the receiver that no more values will arrive.
40+
// After Close is called, the Sender may no longer be used.
41+
func (s *Sender[T]) Close() {
42+
close(s.values)
43+
}
44+
45+
// A Receiver receives values from a Sender.
46+
type Receiver[type T] struct {
47+
values <-chan T
48+
done chan<- bool
49+
}
50+
51+
// Next returns the next value from the channel. The bool result
52+
// indicates whether the value is valid, or whether the Sender has
53+
// been closed and no more values will be received.
54+
func (r *Receiver[T]) Next() (T, bool) {
55+
v, ok := <-r.values
56+
return v, ok
57+
}
58+
59+
// finalize is a finalizer for the receiver.
60+
func (r *Receiver[T]) finalize() {
61+
close(r.done)
62+
}

src/cmd/compile/internal/syntax/testdata/go2/linalg.go2

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ package linalg
77
import "math"
88

99
// Numeric is type bound that matches any numeric type.
10-
// It would likely be in a contracts package in the standard library.
10+
// It would likely be in a constraints package in the standard library.
1111
type Numeric interface {
12-
type int, int8, int16, int32, int64
13-
type uint, uint8, uint16, uint32, uint64, uintptr
14-
type float32, float64
15-
type complex64, complex128
12+
type int, int8, int16, int32, int64,
13+
uint, uint8, uint16, uint32, uint64, uintptr,
14+
float32, float64,
15+
complex64, complex128
1616
}
1717

1818
func DotProduct(type T Numeric)(s1, s2 []T) T {
@@ -42,9 +42,9 @@ func AbsDifference(type T NumericAbs)(a, b T) T {
4242

4343
// OrderedNumeric is a type bound that matches numeric types that support the < operator.
4444
type OrderedNumeric interface {
45-
type int, int8, int16, int32, int64
46-
type uint, uint8, uint16, uint32, uint64, uintptr
47-
type float32, float64
45+
type int, int8, int16, int32, int64,
46+
uint, uint8, uint16, uint32, uint64, uintptr,
47+
float32, float64
4848
}
4949

5050
// Complex is a type bound that matches the two complex types, which do not have a < operator.
@@ -71,7 +71,7 @@ func (a ComplexAbs(T)) Abs() ComplexAbs(T) {
7171
r := float64(real(a))
7272
i := float64(imag(a))
7373
d := math.Sqrt(r * r + i * i)
74-
return T(complex(d, 0))
74+
return (ComplexAbs(T))(complex(d, 0))
7575
}
7676

7777
func OrderedAbsDifference(type T OrderedNumeric)(a, b T) T {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package linalg
6+
7+
import "math"
8+
9+
// Numeric is type bound that matches any numeric type.
10+
// It would likely be in a constraints package in the standard library.
11+
type Numeric interface {
12+
type int, int8, int16, int32, int64,
13+
uint, uint8, uint16, uint32, uint64, uintptr,
14+
float32, float64,
15+
complex64, complex128
16+
}
17+
18+
func DotProduct[type T Numeric](s1, s2 []T) T {
19+
if len(s1) != len(s2) {
20+
panic("DotProduct: slices of unequal length")
21+
}
22+
var r T
23+
for i := range s1 {
24+
r += s1[i] * s2[i]
25+
}
26+
return r
27+
}
28+
29+
// NumericAbs matches numeric types with an Abs method.
30+
type NumericAbs[type T] interface {
31+
Numeric
32+
33+
Abs() T
34+
}
35+
36+
// AbsDifference computes the absolute value of the difference of
37+
// a and b, where the absolute value is determined by the Abs method.
38+
func AbsDifference[type T NumericAbs](a, b T) T {
39+
d := a - b
40+
return d.Abs()
41+
}
42+
43+
// OrderedNumeric is a type bound that matches numeric types that support the < operator.
44+
type OrderedNumeric interface {
45+
type int, int8, int16, int32, int64,
46+
uint, uint8, uint16, uint32, uint64, uintptr,
47+
float32, float64
48+
}
49+
50+
// Complex is a type bound that matches the two complex types, which do not have a < operator.
51+
type Complex interface {
52+
type complex64, complex128
53+
}
54+
55+
// OrderedAbs is a helper type that defines an Abs method for
56+
// ordered numeric types.
57+
type OrderedAbs[type T OrderedNumeric] T
58+
59+
func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
60+
if a < 0 {
61+
return -a
62+
}
63+
return a
64+
}
65+
66+
// ComplexAbs is a helper type that defines an Abs method for
67+
// complex types.
68+
type ComplexAbs[type T Complex] T
69+
70+
func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
71+
r := float64(real(a))
72+
i := float64(imag(a))
73+
d := math.Sqrt(r * r + i * i)
74+
return ComplexAbs[T](complex(d, 0))
75+
}
76+
77+
func OrderedAbsDifference[type T OrderedNumeric](a, b T) T {
78+
return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
79+
}
80+
81+
func ComplexAbsDifference[type T Complex](a, b T) T {
82+
return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
83+
}

src/cmd/compile/internal/syntax/testdata/go2/map.go2

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// Package orderedmap provides an ordered map, implemented as a binary tree.
66
package orderedmap
77

8-
// TODO(gri) fix imports for tests
9-
import "chans" // ERROR could not import
8+
import "chans"
109

1110
// Map is an ordered map.
1211
type Map(type K, V) struct {
@@ -92,10 +91,7 @@ func (m *Map(K, V)) InOrder() *Iterator(K, V) {
9291
f(m.root)
9392
sender.Close()
9493
}()
95-
// TODO(gri) The design draft doesn't require that we repeat
96-
// the type parameters here. Fix the implementation.
9794
return &Iterator(K, V){receiver}
98-
// return &Iterator{receiver}
9995
}
10096

10197
// Iterator is used to iterate over the map.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package orderedmap provides an ordered map, implemented as a binary tree.
6+
package orderedmap
7+
8+
// TODO(gri) fix imports for tests
9+
import "chans" // ERROR could not import
10+
11+
// Map is an ordered map.
12+
type Map[type K, V] struct {
13+
root *node[K, V]
14+
compare func(K, K) int
15+
}
16+
17+
// node is the type of a node in the binary tree.
18+
type node[type K, V] struct {
19+
key K
20+
val V
21+
left, right *node[K, V]
22+
}
23+
24+
// New returns a new map.
25+
func New[type K, V](compare func(K, K) int) *Map[K, V] {
26+
return &Map[K, V]{compare: compare}
27+
}
28+
29+
// find looks up key in the map, and returns either a pointer
30+
// to the node holding key, or a pointer to the location where
31+
// such a node would go.
32+
func (m *Map[K, V]) find(key K) **node[K, V] {
33+
pn := &m.root
34+
for *pn != nil {
35+
switch cmp := m.compare(key, (*pn).key); {
36+
case cmp < 0:
37+
pn = &(*pn).left
38+
case cmp > 0:
39+
pn = &(*pn).right
40+
default:
41+
return pn
42+
}
43+
}
44+
return pn
45+
}
46+
47+
// Insert inserts a new key/value into the map.
48+
// If the key is already present, the value is replaced.
49+
// Returns true if this is a new key, false if already present.
50+
func (m *Map[K, V]) Insert(key K, val V) bool {
51+
pn := m.find(key)
52+
if *pn != nil {
53+
(*pn).val = val
54+
return false
55+
}
56+
*pn = &node[K, V]{key: key, val: val}
57+
return true
58+
}
59+
60+
// Find returns the value associated with a key, or zero if not present.
61+
// The found result reports whether the key was found.
62+
func (m *Map[K, V]) Find(key K) (V, bool) {
63+
pn := m.find(key)
64+
if *pn == nil {
65+
var zero V // see the discussion of zero values, above
66+
return zero, false
67+
}
68+
return (*pn).val, true
69+
}
70+
71+
// keyValue is a pair of key and value used when iterating.
72+
type keyValue[type K, V] struct {
73+
key K
74+
val V
75+
}
76+
77+
// InOrder returns an iterator that does an in-order traversal of the map.
78+
func (m *Map[K, V]) InOrder() *Iterator[K, V] {
79+
sender, receiver := chans.Ranger[keyValue[K, V]]()
80+
var f func(*node[K, V]) bool
81+
f = func(n *node[K, V]) bool {
82+
if n == nil {
83+
return true
84+
}
85+
// Stop sending values if sender.Send returns false,
86+
// meaning that nothing is listening at the receiver end.
87+
return f(n.left) &&
88+
sender.Send(keyValue[K, V]{n.key, n.val}) &&
89+
f(n.right)
90+
}
91+
go func() {
92+
f(m.root)
93+
sender.Close()
94+
}()
95+
return &Iterator[K, V]{receiver}
96+
}
97+
98+
// Iterator is used to iterate over the map.
99+
type Iterator[type K, V] struct {
100+
r *chans.Receiver[keyValue[K, V]]
101+
}
102+
103+
// Next returns the next key and value pair, and a boolean indicating
104+
// whether they are valid or whether we have reached the end.
105+
func (it *Iterator[K, V]) Next() (K, V, bool) {
106+
keyval, ok := it.r.Next()
107+
if !ok {
108+
var zerok K
109+
var zerov V
110+
return zerok, zerov, false
111+
}
112+
return keyval.key, keyval.val, true
113+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package slices implements various slice algorithms.
6+
package slices
7+
8+
// Map turns a []T1 to a []T2 using a mapping function.
9+
func Map[type T1, T2](s []T1, f func(T1) T2) []T2 {
10+
r := make([]T2, len(s))
11+
for i, v := range s {
12+
r[i] = f(v)
13+
}
14+
return r
15+
}
16+
17+
// Reduce reduces a []T1 to a single value using a reduction function.
18+
func Reduce[type T1, T2](s []T1, initializer T2, f func(T2, T1) T2) T2 {
19+
r := initializer
20+
for _, v := range s {
21+
r = f(r, v)
22+
}
23+
return r
24+
}
25+
26+
// Filter filters values from a slice using a filter function.
27+
func Filter[type T](s []T, f func(T) bool) []T {
28+
var r []T
29+
for _, v := range s {
30+
if f(v) {
31+
r = append(r, v)
32+
}
33+
}
34+
return r
35+
}
36+
37+
// Example uses
38+
39+
func limiter(x int) byte {
40+
switch {
41+
case x < 0:
42+
return 0
43+
default:
44+
return byte(x)
45+
case x > 255:
46+
return 255
47+
}
48+
}
49+
50+
var input = []int{-4, 68954, 7, 44, 0, -555, 6945}
51+
var limited1 = Map[int, byte](input, limiter)
52+
var limited2 = Map(input, limiter) // using type inference
53+
54+
func reducer(x float64, y int) float64 {
55+
return x + float64(y)
56+
}
57+
58+
var reduced1 = Reduce[int, float64](input, 0, reducer)
59+
var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference
60+
var reduced3 = Reduce(input, 1, reducer) // using type inference
61+
62+
func filter(x int) bool {
63+
return x&1 != 0
64+
}
65+
66+
var filtered1 = Filter[int](input, filter)
67+
var filtered2 = Filter(input, filter) // using type inference
68+

0 commit comments

Comments
 (0)