mirror of https://github.com/golang/go.git
[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 <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
d8b0f3b91f
commit
ead7e9b351
|
|
@ -0,0 +1,62 @@
|
|||
package chans
|
||||
|
||||
import "runtime"
|
||||
|
||||
// Ranger returns a Sender and a Receiver. The Receiver provides a
|
||||
// Next method to retrieve values. The Sender provides a Send method
|
||||
// to send values and a Close method to stop sending values. The Next
|
||||
// method indicates when the Sender has been closed, and the Send
|
||||
// method indicates when the Receiver has been freed.
|
||||
//
|
||||
// This is a convenient way to exit a goroutine sending values when
|
||||
// the receiver stops reading them.
|
||||
func Ranger[type T]() (*Sender[T], *Receiver[T]) {
|
||||
c := make(chan T)
|
||||
d := make(chan bool)
|
||||
s := &Sender[T]{values: c, done: d}
|
||||
r := &Receiver[T]{values: c, done: d}
|
||||
runtime.SetFinalizer(r, r.finalize)
|
||||
return s, r
|
||||
}
|
||||
|
||||
// A sender is used to send values to a Receiver.
|
||||
type Sender[type T] struct {
|
||||
values chan<- T
|
||||
done <-chan bool
|
||||
}
|
||||
|
||||
// Send sends a value to the receiver. It returns whether any more
|
||||
// values may be sent; if it returns false the value was not sent.
|
||||
func (s *Sender[T]) Send(v T) bool {
|
||||
select {
|
||||
case s.values <- v:
|
||||
return true
|
||||
case <-s.done:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Close tells the receiver that no more values will arrive.
|
||||
// After Close is called, the Sender may no longer be used.
|
||||
func (s *Sender[T]) Close() {
|
||||
close(s.values)
|
||||
}
|
||||
|
||||
// A Receiver receives values from a Sender.
|
||||
type Receiver[type T] struct {
|
||||
values <-chan T
|
||||
done chan<- bool
|
||||
}
|
||||
|
||||
// Next returns the next value from the channel. The bool result
|
||||
// indicates whether the value is valid, or whether the Sender has
|
||||
// been closed and no more values will be received.
|
||||
func (r *Receiver[T]) Next() (T, bool) {
|
||||
v, ok := <-r.values
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// finalize is a finalizer for the receiver.
|
||||
func (r *Receiver[T]) finalize() {
|
||||
close(r.done)
|
||||
}
|
||||
|
|
@ -7,12 +7,12 @@ package linalg
|
|||
import "math"
|
||||
|
||||
// Numeric is type bound that matches any numeric type.
|
||||
// It would likely be in a contracts package in the standard library.
|
||||
// It would likely be in a constraints package in the standard library.
|
||||
type Numeric interface {
|
||||
type int, int8, int16, int32, int64
|
||||
type uint, uint8, uint16, uint32, uint64, uintptr
|
||||
type float32, float64
|
||||
type complex64, complex128
|
||||
type int, int8, int16, int32, int64,
|
||||
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||
float32, float64,
|
||||
complex64, complex128
|
||||
}
|
||||
|
||||
func DotProduct(type T Numeric)(s1, s2 []T) T {
|
||||
|
|
@ -42,9 +42,9 @@ func AbsDifference(type T NumericAbs)(a, b T) T {
|
|||
|
||||
// OrderedNumeric is a type bound that matches numeric types that support the < operator.
|
||||
type OrderedNumeric interface {
|
||||
type int, int8, int16, int32, int64
|
||||
type uint, uint8, uint16, uint32, uint64, uintptr
|
||||
type float32, float64
|
||||
type int, int8, int16, int32, int64,
|
||||
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||
float32, float64
|
||||
}
|
||||
|
||||
// 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) {
|
|||
r := float64(real(a))
|
||||
i := float64(imag(a))
|
||||
d := math.Sqrt(r * r + i * i)
|
||||
return T(complex(d, 0))
|
||||
return (ComplexAbs(T))(complex(d, 0))
|
||||
}
|
||||
|
||||
func OrderedAbsDifference(type T OrderedNumeric)(a, b T) T {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package linalg
|
||||
|
||||
import "math"
|
||||
|
||||
// Numeric is type bound that matches any numeric type.
|
||||
// It would likely be in a constraints package in the standard library.
|
||||
type Numeric interface {
|
||||
type int, int8, int16, int32, int64,
|
||||
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||
float32, float64,
|
||||
complex64, complex128
|
||||
}
|
||||
|
||||
func DotProduct[type T Numeric](s1, s2 []T) T {
|
||||
if len(s1) != len(s2) {
|
||||
panic("DotProduct: slices of unequal length")
|
||||
}
|
||||
var r T
|
||||
for i := range s1 {
|
||||
r += s1[i] * s2[i]
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// NumericAbs matches numeric types with an Abs method.
|
||||
type NumericAbs[type T] interface {
|
||||
Numeric
|
||||
|
||||
Abs() T
|
||||
}
|
||||
|
||||
// AbsDifference computes the absolute value of the difference of
|
||||
// a and b, where the absolute value is determined by the Abs method.
|
||||
func AbsDifference[type T NumericAbs](a, b T) T {
|
||||
d := a - b
|
||||
return d.Abs()
|
||||
}
|
||||
|
||||
// OrderedNumeric is a type bound that matches numeric types that support the < operator.
|
||||
type OrderedNumeric interface {
|
||||
type int, int8, int16, int32, int64,
|
||||
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||
float32, float64
|
||||
}
|
||||
|
||||
// Complex is a type bound that matches the two complex types, which do not have a < operator.
|
||||
type Complex interface {
|
||||
type complex64, complex128
|
||||
}
|
||||
|
||||
// OrderedAbs is a helper type that defines an Abs method for
|
||||
// ordered numeric types.
|
||||
type OrderedAbs[type T OrderedNumeric] T
|
||||
|
||||
func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
|
||||
if a < 0 {
|
||||
return -a
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// ComplexAbs is a helper type that defines an Abs method for
|
||||
// complex types.
|
||||
type ComplexAbs[type T Complex] T
|
||||
|
||||
func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
|
||||
r := float64(real(a))
|
||||
i := float64(imag(a))
|
||||
d := math.Sqrt(r * r + i * i)
|
||||
return ComplexAbs[T](complex(d, 0))
|
||||
}
|
||||
|
||||
func OrderedAbsDifference[type T OrderedNumeric](a, b T) T {
|
||||
return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
|
||||
}
|
||||
|
||||
func ComplexAbsDifference[type T Complex](a, b T) T {
|
||||
return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
|
||||
}
|
||||
|
|
@ -5,8 +5,7 @@
|
|||
// Package orderedmap provides an ordered map, implemented as a binary tree.
|
||||
package orderedmap
|
||||
|
||||
// TODO(gri) fix imports for tests
|
||||
import "chans" // ERROR could not import
|
||||
import "chans"
|
||||
|
||||
// Map is an ordered map.
|
||||
type Map(type K, V) struct {
|
||||
|
|
@ -92,10 +91,7 @@ func (m *Map(K, V)) InOrder() *Iterator(K, V) {
|
|||
f(m.root)
|
||||
sender.Close()
|
||||
}()
|
||||
// TODO(gri) The design draft doesn't require that we repeat
|
||||
// the type parameters here. Fix the implementation.
|
||||
return &Iterator(K, V){receiver}
|
||||
// return &Iterator{receiver}
|
||||
}
|
||||
|
||||
// Iterator is used to iterate over the map.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package orderedmap provides an ordered map, implemented as a binary tree.
|
||||
package orderedmap
|
||||
|
||||
// TODO(gri) fix imports for tests
|
||||
import "chans" // ERROR could not import
|
||||
|
||||
// Map is an ordered map.
|
||||
type Map[type K, V] struct {
|
||||
root *node[K, V]
|
||||
compare func(K, K) int
|
||||
}
|
||||
|
||||
// node is the type of a node in the binary tree.
|
||||
type node[type K, V] struct {
|
||||
key K
|
||||
val V
|
||||
left, right *node[K, V]
|
||||
}
|
||||
|
||||
// New returns a new map.
|
||||
func New[type K, V](compare func(K, K) int) *Map[K, V] {
|
||||
return &Map[K, V]{compare: compare}
|
||||
}
|
||||
|
||||
// find looks up key in the map, and returns either a pointer
|
||||
// to the node holding key, or a pointer to the location where
|
||||
// such a node would go.
|
||||
func (m *Map[K, V]) find(key K) **node[K, V] {
|
||||
pn := &m.root
|
||||
for *pn != nil {
|
||||
switch cmp := m.compare(key, (*pn).key); {
|
||||
case cmp < 0:
|
||||
pn = &(*pn).left
|
||||
case cmp > 0:
|
||||
pn = &(*pn).right
|
||||
default:
|
||||
return pn
|
||||
}
|
||||
}
|
||||
return pn
|
||||
}
|
||||
|
||||
// Insert inserts a new key/value into the map.
|
||||
// If the key is already present, the value is replaced.
|
||||
// Returns true if this is a new key, false if already present.
|
||||
func (m *Map[K, V]) Insert(key K, val V) bool {
|
||||
pn := m.find(key)
|
||||
if *pn != nil {
|
||||
(*pn).val = val
|
||||
return false
|
||||
}
|
||||
*pn = &node[K, V]{key: key, val: val}
|
||||
return true
|
||||
}
|
||||
|
||||
// Find returns the value associated with a key, or zero if not present.
|
||||
// The found result reports whether the key was found.
|
||||
func (m *Map[K, V]) Find(key K) (V, bool) {
|
||||
pn := m.find(key)
|
||||
if *pn == nil {
|
||||
var zero V // see the discussion of zero values, above
|
||||
return zero, false
|
||||
}
|
||||
return (*pn).val, true
|
||||
}
|
||||
|
||||
// keyValue is a pair of key and value used when iterating.
|
||||
type keyValue[type K, V] struct {
|
||||
key K
|
||||
val V
|
||||
}
|
||||
|
||||
// InOrder returns an iterator that does an in-order traversal of the map.
|
||||
func (m *Map[K, V]) InOrder() *Iterator[K, V] {
|
||||
sender, receiver := chans.Ranger[keyValue[K, V]]()
|
||||
var f func(*node[K, V]) bool
|
||||
f = func(n *node[K, V]) bool {
|
||||
if n == nil {
|
||||
return true
|
||||
}
|
||||
// Stop sending values if sender.Send returns false,
|
||||
// meaning that nothing is listening at the receiver end.
|
||||
return f(n.left) &&
|
||||
sender.Send(keyValue[K, V]{n.key, n.val}) &&
|
||||
f(n.right)
|
||||
}
|
||||
go func() {
|
||||
f(m.root)
|
||||
sender.Close()
|
||||
}()
|
||||
return &Iterator[K, V]{receiver}
|
||||
}
|
||||
|
||||
// Iterator is used to iterate over the map.
|
||||
type Iterator[type K, V] struct {
|
||||
r *chans.Receiver[keyValue[K, V]]
|
||||
}
|
||||
|
||||
// Next returns the next key and value pair, and a boolean indicating
|
||||
// whether they are valid or whether we have reached the end.
|
||||
func (it *Iterator[K, V]) Next() (K, V, bool) {
|
||||
keyval, ok := it.r.Next()
|
||||
if !ok {
|
||||
var zerok K
|
||||
var zerov V
|
||||
return zerok, zerov, false
|
||||
}
|
||||
return keyval.key, keyval.val, true
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package slices implements various slice algorithms.
|
||||
package slices
|
||||
|
||||
// Map turns a []T1 to a []T2 using a mapping function.
|
||||
func Map[type T1, T2](s []T1, f func(T1) T2) []T2 {
|
||||
r := make([]T2, len(s))
|
||||
for i, v := range s {
|
||||
r[i] = f(v)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Reduce reduces a []T1 to a single value using a reduction function.
|
||||
func Reduce[type T1, T2](s []T1, initializer T2, f func(T2, T1) T2) T2 {
|
||||
r := initializer
|
||||
for _, v := range s {
|
||||
r = f(r, v)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Filter filters values from a slice using a filter function.
|
||||
func Filter[type T](s []T, f func(T) bool) []T {
|
||||
var r []T
|
||||
for _, v := range s {
|
||||
if f(v) {
|
||||
r = append(r, v)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Example uses
|
||||
|
||||
func limiter(x int) byte {
|
||||
switch {
|
||||
case x < 0:
|
||||
return 0
|
||||
default:
|
||||
return byte(x)
|
||||
case x > 255:
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
var input = []int{-4, 68954, 7, 44, 0, -555, 6945}
|
||||
var limited1 = Map[int, byte](input, limiter)
|
||||
var limited2 = Map(input, limiter) // using type inference
|
||||
|
||||
func reducer(x float64, y int) float64 {
|
||||
return x + float64(y)
|
||||
}
|
||||
|
||||
var reduced1 = Reduce[int, float64](input, 0, reducer)
|
||||
var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference
|
||||
var reduced3 = Reduce(input, 1, reducer) // using type inference
|
||||
|
||||
func filter(x int) bool {
|
||||
return x&1 != 0
|
||||
}
|
||||
|
||||
var filtered1 = Filter[int](input, filter)
|
||||
var filtered2 = Filter(input, filter) // using type inference
|
||||
|
||||
Loading…
Reference in New Issue