mirror of
https://github.com/hanzoai/yaegi.git
synced 2026-10-01 00:49:47 +00:00
* feat: generate go1.21 files * chore: update CI * feat: add support for generic symbols in standard library packages This is necessary to fully support go1.21 and beyond, which now provide some generic packages such as `cmp`, `maps` or `slices` in the standard library. The principle is to embed the generic symbols in source form (as strings) so they can be instantiated as required during interpretation. Extract() has been modified to skip the generic types, functions and constraint interfaces which can't be represented as reflect.Values. A new stdlib/generic package has been added to provide the corresponding source files as embedded strings. The `Use()` function has been changed to pre-parse generic symbols as doing lazy parsing was causing cyclic dependencies issues at compiling. This is something we may improve in the future. A unit test using `cmp` has been added. For now, there are still some issues with generic stdlib packages inter-dependencies, for example `slices` importing `cmp`, or when generic types or function signatures depends on pre-compiled types in the same package, which we will support shortly. * fixup * fixup * fixup * fixup * fixup * fixup * fixes for go1.20 * fix previous * update unsafe2 for go1.21, skip faky tests In go1.21, the reflect rtype definition has been move to internal/abi. We follow this change for maintainability, even if there is no layout change (the go1.20 unsafe2 is compatible with go1.21). We have isolated a few problematic tests which are failing sometimes in go1.21, but work in go1.20, and also in go1.22. Those tests are skipped if in go1.21. A preliminary investigation can not confirm that something is wrong in yaegi, and the problem disappears with go1.22. * add new wrapper for go1.21 package testing/slogtest * add missing wrapper for go/doc/comment * add support for slices generic package --------- Co-authored-by: Marc Vertes <[email protected]>
201 lines
6.5 KiB
Plaintext
201 lines
6.5 KiB
Plaintext
// Copyright 2022 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 atomic
|
|
|
|
import "unsafe"
|
|
|
|
// A Bool is an atomic boolean value.
|
|
// The zero value is false.
|
|
type Bool struct {
|
|
_ noCopy
|
|
v uint32
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Bool) Load() bool { return LoadUint32(&x.v) != 0 }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Bool) Store(val bool) { StoreUint32(&x.v, b32(val)) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Bool) Swap(new bool) (old bool) { return SwapUint32(&x.v, b32(new)) != 0 }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for the boolean value x.
|
|
func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) {
|
|
return CompareAndSwapUint32(&x.v, b32(old), b32(new))
|
|
}
|
|
|
|
// b32 returns a uint32 0 or 1 representing b.
|
|
func b32(b bool) uint32 {
|
|
if b {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// For testing *Pointer[T]'s methods can be inlined.
|
|
// Keep in sync with cmd/compile/internal/test/inl_test.go:TestIntendedInlining.
|
|
var _ = &Pointer[int]{}
|
|
|
|
// A Pointer is an atomic pointer of type *T. The zero value is a nil *T.
|
|
type Pointer[T any] struct {
|
|
// Mention *T in a field to disallow conversion between Pointer types.
|
|
// See go.dev/issue/56603 for more details.
|
|
// Use *T, not T, to avoid spurious recursive type definition errors.
|
|
_ [0]*T
|
|
|
|
_ noCopy
|
|
v unsafe.Pointer
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Pointer[T]) Load() *T { return (*T)(LoadPointer(&x.v)) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Pointer[T]) Store(val *T) { StorePointer(&x.v, unsafe.Pointer(val)) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Pointer[T]) Swap(new *T) (old *T) { return (*T)(SwapPointer(&x.v, unsafe.Pointer(new))) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {
|
|
return CompareAndSwapPointer(&x.v, unsafe.Pointer(old), unsafe.Pointer(new))
|
|
}
|
|
|
|
// An Int32 is an atomic int32. The zero value is zero.
|
|
type Int32 struct {
|
|
_ noCopy
|
|
v int32
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Int32) Load() int32 { return LoadInt32(&x.v) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Int32) Store(val int32) { StoreInt32(&x.v, val) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Int32) Swap(new int32) (old int32) { return SwapInt32(&x.v, new) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Int32) CompareAndSwap(old, new int32) (swapped bool) {
|
|
return CompareAndSwapInt32(&x.v, old, new)
|
|
}
|
|
|
|
// Add atomically adds delta to x and returns the new value.
|
|
func (x *Int32) Add(delta int32) (new int32) { return AddInt32(&x.v, delta) }
|
|
|
|
// An Int64 is an atomic int64. The zero value is zero.
|
|
type Int64 struct {
|
|
_ noCopy
|
|
_ align64
|
|
v int64
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Int64) Load() int64 { return LoadInt64(&x.v) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Int64) Store(val int64) { StoreInt64(&x.v, val) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Int64) Swap(new int64) (old int64) { return SwapInt64(&x.v, new) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) {
|
|
return CompareAndSwapInt64(&x.v, old, new)
|
|
}
|
|
|
|
// Add atomically adds delta to x and returns the new value.
|
|
func (x *Int64) Add(delta int64) (new int64) { return AddInt64(&x.v, delta) }
|
|
|
|
// A Uint32 is an atomic uint32. The zero value is zero.
|
|
type Uint32 struct {
|
|
_ noCopy
|
|
v uint32
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Uint32) Load() uint32 { return LoadUint32(&x.v) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Uint32) Store(val uint32) { StoreUint32(&x.v, val) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Uint32) Swap(new uint32) (old uint32) { return SwapUint32(&x.v, new) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) {
|
|
return CompareAndSwapUint32(&x.v, old, new)
|
|
}
|
|
|
|
// Add atomically adds delta to x and returns the new value.
|
|
func (x *Uint32) Add(delta uint32) (new uint32) { return AddUint32(&x.v, delta) }
|
|
|
|
// A Uint64 is an atomic uint64. The zero value is zero.
|
|
type Uint64 struct {
|
|
_ noCopy
|
|
_ align64
|
|
v uint64
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Uint64) Load() uint64 { return LoadUint64(&x.v) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Uint64) Store(val uint64) { StoreUint64(&x.v, val) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Uint64) Swap(new uint64) (old uint64) { return SwapUint64(&x.v, new) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) {
|
|
return CompareAndSwapUint64(&x.v, old, new)
|
|
}
|
|
|
|
// Add atomically adds delta to x and returns the new value.
|
|
func (x *Uint64) Add(delta uint64) (new uint64) { return AddUint64(&x.v, delta) }
|
|
|
|
// A Uintptr is an atomic uintptr. The zero value is zero.
|
|
type Uintptr struct {
|
|
_ noCopy
|
|
v uintptr
|
|
}
|
|
|
|
// Load atomically loads and returns the value stored in x.
|
|
func (x *Uintptr) Load() uintptr { return LoadUintptr(&x.v) }
|
|
|
|
// Store atomically stores val into x.
|
|
func (x *Uintptr) Store(val uintptr) { StoreUintptr(&x.v, val) }
|
|
|
|
// Swap atomically stores new into x and returns the previous value.
|
|
func (x *Uintptr) Swap(new uintptr) (old uintptr) { return SwapUintptr(&x.v, new) }
|
|
|
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
|
func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) {
|
|
return CompareAndSwapUintptr(&x.v, old, new)
|
|
}
|
|
|
|
// Add atomically adds delta to x and returns the new value.
|
|
func (x *Uintptr) Add(delta uintptr) (new uintptr) { return AddUintptr(&x.v, delta) }
|
|
|
|
// noCopy may be added to structs which must not be copied
|
|
// after the first use.
|
|
//
|
|
// See https://golang.org/issues/8005#issuecomment-190753527
|
|
// for details.
|
|
//
|
|
// Note that it must not be embedded, due to the Lock and Unlock methods.
|
|
type noCopy struct{}
|
|
|
|
// Lock is a no-op used by -copylocks checker from `go vet`.
|
|
func (*noCopy) Lock() {}
|
|
func (*noCopy) Unlock() {}
|
|
|
|
// align64 may be added to structs that must be 64-bit aligned.
|
|
// This struct is recognized by a special case in the compiler
|
|
// and will not work if copied to any other package.
|
|
type align64 struct{}
|