Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a5b16cad6 | ||
|
|
1990b96ccd | ||
|
|
da27c4fbc2 | ||
|
|
f5b5481794 | ||
|
|
79b7420ee1 | ||
|
|
8a6061cc86 | ||
|
|
c10e468d01 | ||
|
|
75e5f99bc5 | ||
|
|
79e32b5a92 | ||
|
|
63b8cc42b9 | ||
|
|
f4a9cd3cbe | ||
|
|
6447a677f3 | ||
|
|
68a430f969 | ||
|
|
dc7c64ba88 | ||
|
|
d6ad13acea | ||
|
|
d124954a7d | ||
|
|
8de3add6fa |
2
.github/workflows/go-cross.yml
vendored
2
.github/workflows/go-cross.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.19, '1.20' ]
|
||||
go-version: [ '1.21', '1.22' ]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
include:
|
||||
|
||||
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@@ -7,8 +7,8 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.19
|
||||
GOLANGCI_LINT_VERSION: v1.47.1
|
||||
GO_VERSION: '1.22'
|
||||
GOLANGCI_LINT_VERSION: v1.55.2
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
needs: linting
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.19, '1.20' ]
|
||||
go-version: [ '1.21', '1.22' ]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v2
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/yaegi
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.19, '1.20' ]
|
||||
go-version: [ '1.21', '1.22' ]
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }}
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
- v[0-9]+.[0-9]+*
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.20'
|
||||
GO_VERSION: '1.21'
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
[run]
|
||||
deadline = "5m"
|
||||
skip-files = []
|
||||
|
||||
[linters-settings]
|
||||
|
||||
[linters-settings.govet]
|
||||
check-shadowing = false
|
||||
|
||||
[linters-settings.gocyclo]
|
||||
min-complexity = 12.0
|
||||
|
||||
[linters-settings.maligned]
|
||||
suggest-new = true
|
||||
|
||||
[linters-settings.goconst]
|
||||
min-len = 3.0
|
||||
min-occurrences = 3.0
|
||||
|
||||
[linters-settings.misspell]
|
||||
locale = "US"
|
||||
|
||||
[linters]
|
||||
enable-all = true
|
||||
disable = [
|
||||
"golint", # deprecated
|
||||
"scopelint", # deprecated
|
||||
"interfacer", # deprecated
|
||||
"maligned", # deprecated
|
||||
"exhaustivestruct", # deprecated
|
||||
"lll",
|
||||
"gas",
|
||||
"dupl",
|
||||
"prealloc",
|
||||
"gocyclo",
|
||||
"cyclop",
|
||||
"gochecknoinits",
|
||||
"gochecknoglobals",
|
||||
"wsl",
|
||||
"nlreturn",
|
||||
"godox",
|
||||
"funlen",
|
||||
"gocognit",
|
||||
"stylecheck",
|
||||
"gomnd",
|
||||
"testpackage",
|
||||
"paralleltest",
|
||||
"tparallel",
|
||||
"goerr113",
|
||||
"wrapcheck",
|
||||
"nestif",
|
||||
"exhaustive",
|
||||
"exhaustruct",
|
||||
"forbidigo",
|
||||
"ifshort",
|
||||
"forcetypeassert",
|
||||
"varnamelen",
|
||||
"nosnakecase",
|
||||
"nonamedreturns",
|
||||
"nilnil",
|
||||
"maintidx",
|
||||
"errorlint", # TODO: must be reactivate before fixes
|
||||
]
|
||||
|
||||
[issues]
|
||||
exclude-use-default = false
|
||||
max-per-linter = 0
|
||||
max-same-issues = 0
|
||||
exclude = []
|
||||
|
||||
[[issues.exclude-rules]]
|
||||
path = ".+_test\\.go"
|
||||
linters = ["goconst"]
|
||||
[[issues.exclude-rules]]
|
||||
path = ".+_test\\.go"
|
||||
text = "var-declaration:"
|
||||
|
||||
[[issues.exclude-rules]]
|
||||
path = "interp/interp.go"
|
||||
text = "`in` can be `io.Reader`"
|
||||
[[issues.exclude-rules]]
|
||||
path = "interp/interp.go"
|
||||
text = "`out` can be `io.Writer`"
|
||||
[[issues.exclude-rules]]
|
||||
path = "interp/interp.go"
|
||||
text = "`Panic` should conform to the `XxxError` format"
|
||||
[[issues.exclude-rules]]
|
||||
path = "interp/interp_eval_test.go"
|
||||
linters = ["thelper"]
|
||||
[[issues.exclude-rules]]
|
||||
path = "interp/debugger.go"
|
||||
linters = ["containedctx"]
|
||||
165
.golangci.yml
Normal file
165
.golangci.yml
Normal file
@@ -0,0 +1,165 @@
|
||||
run:
|
||||
timeout: 10m
|
||||
skip-files: []
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: false
|
||||
gocyclo:
|
||||
min-complexity: 12
|
||||
maligned:
|
||||
suggest-new: true
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
funlen:
|
||||
lines: -1
|
||||
statements: 50
|
||||
misspell:
|
||||
locale: US
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
files:
|
||||
- $all
|
||||
allow:
|
||||
- $gostd
|
||||
- github.com/traefik/yaegi
|
||||
tagalign:
|
||||
align: false
|
||||
order:
|
||||
- xml
|
||||
- json
|
||||
- yaml
|
||||
- yml
|
||||
- toml
|
||||
- mapstructure
|
||||
- url
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
disabled-checks:
|
||||
- paramTypeCombine # already handle by gofumpt.extra-rules
|
||||
- whyNoLint # already handle by nonolint
|
||||
- unnamedResult
|
||||
- hugeParam
|
||||
- sloppyReassign
|
||||
- rangeValCopy
|
||||
- octalLiteral
|
||||
- ptrToRefParam
|
||||
- appendAssign
|
||||
- ruleguard
|
||||
- httpNoBody
|
||||
- exposedSyncMutex
|
||||
- importShadow # TODO should be fixed
|
||||
- commentedOutCode # TODO should be fixed
|
||||
revive:
|
||||
rules:
|
||||
- name: struct-tag
|
||||
- name: blank-imports
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: error-naming
|
||||
- name: exported
|
||||
disabled: true
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: var-naming
|
||||
- name: var-declaration
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: time-naming
|
||||
- name: unexported-return
|
||||
- name: indent-error-flow
|
||||
- name: errorf
|
||||
- name: empty-block
|
||||
- name: superfluous-else
|
||||
- name: unused-parameter
|
||||
disabled: true
|
||||
- name: unreachable-code
|
||||
- name: redefines-builtin-id
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- deadcode # deprecated
|
||||
- exhaustivestruct # deprecated
|
||||
- golint # deprecated
|
||||
- ifshort # deprecated
|
||||
- interfacer # deprecated
|
||||
- maligned # deprecated
|
||||
- nosnakecase # deprecated
|
||||
- scopelint # deprecated
|
||||
- structcheck # deprecated
|
||||
- varcheck # deprecated
|
||||
- cyclop # duplicate of gocyclo
|
||||
- sqlclosecheck # not relevant (SQL)
|
||||
- rowserrcheck # not relevant (SQL)
|
||||
- execinquery # not relevant (SQL)
|
||||
- lll
|
||||
- gas
|
||||
- dupl
|
||||
- prealloc
|
||||
- gocyclo
|
||||
- cyclop
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
- wsl
|
||||
- nlreturn
|
||||
- godox
|
||||
- funlen
|
||||
- gocognit
|
||||
- stylecheck
|
||||
- gomnd
|
||||
- testpackage
|
||||
- paralleltest
|
||||
- tparallel
|
||||
- goerr113
|
||||
- wrapcheck
|
||||
- nestif
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- forbidigo
|
||||
- ifshort
|
||||
- forcetypeassert
|
||||
- varnamelen
|
||||
- nosnakecase
|
||||
- nonamedreturns
|
||||
- nilnil
|
||||
- maintidx
|
||||
- dupword # false positives
|
||||
- errorlint # TODO: must be reactivate after fixes
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
max-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude: []
|
||||
exclude-rules:
|
||||
- path: .+_test\.go
|
||||
linters:
|
||||
- goconst
|
||||
- path: .+_test\.go
|
||||
text: 'var-declaration:'
|
||||
- path: interp/interp.go
|
||||
text: '`in` can be `io.Reader`'
|
||||
- path: interp/interp.go
|
||||
text: '`out` can be `io.Writer`'
|
||||
- path: interp/interp.go
|
||||
text: '`Panic` should conform to the `XxxError` format'
|
||||
- path: interp/interp_eval_test.go
|
||||
linters:
|
||||
- thelper
|
||||
- path: interp/debugger.go
|
||||
linters:
|
||||
- containedctx
|
||||
13
Makefile
13
Makefile
@@ -27,4 +27,15 @@ tests:
|
||||
install.sh: .goreleaser.yml
|
||||
godownloader --repo=traefik/yaegi -o install.sh .goreleaser.yml
|
||||
|
||||
.PHONY: check gen_all_syscall gen_tests generate_downloader internal/cmd/extract/extract install
|
||||
generic_list = cmp/cmp.go slices/slices.go slices/sort.go slices/zsortanyfunc.go maps/maps.go \
|
||||
sync/oncefunc.go sync/atomic/type.go
|
||||
|
||||
# get_generic_src imports stdlib files containing generic symbols definitions
|
||||
get_generic_src:
|
||||
eval "`go env`"; echo $$GOROOT; gov=$${GOVERSION#*.}; gov=$${gov%.*}; \
|
||||
for f in ${generic_list}; do \
|
||||
nf=stdlib/generic/go1_$${gov}_`echo $$f | tr / _`.txt; echo "nf: $$nf"; \
|
||||
cat "$$GOROOT/src/$$f" > "$$nf"; \
|
||||
done
|
||||
|
||||
.PHONY: check gen_all_syscall internal/cmd/extract/extract get_generic_src install
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[](https://github.com/traefik/yaegi/releases)
|
||||
[](https://github.com/traefik/yaegi/actions/workflows/main.yml)
|
||||
[](https://pkg.go.dev/mod/github.com/traefik/yaegi)
|
||||
[](https://community.traefik.io/c/yaegi)
|
||||
|
||||
Yaegi is Another Elegant Go Interpreter.
|
||||
It powers executable Go scripts and plugins, in embedded interpreters or interactive shells, on top of the Go runtime.
|
||||
@@ -18,7 +17,7 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
|
||||
* Works everywhere Go works
|
||||
* All Go & runtime resources accessible from script (with control)
|
||||
* Security: `unsafe` and `syscall` packages neither used nor exported by default
|
||||
* Support Go 1.18 and Go 1.19 (the latest 2 major releases)
|
||||
* Support the latest 2 major releases of Go (Go 1.21 and Go 1.22)
|
||||
|
||||
## Install
|
||||
|
||||
@@ -31,7 +30,7 @@ import "github.com/traefik/yaegi/interp"
|
||||
### Command-line executable
|
||||
|
||||
```bash
|
||||
go get -u github.com/traefik/yaegi/cmd/yaegi
|
||||
go install github.com/traefik/yaegi/cmd/yaegi@latest
|
||||
```
|
||||
|
||||
Note that you can use [rlwrap](https://github.com/hanslub42/rlwrap) (install with your favorite package manager),
|
||||
@@ -173,6 +172,7 @@ Beside the known [bugs] which are supposed to be fixed in the short term, there
|
||||
|
||||
- Assembly files (`.s`) are not supported.
|
||||
- Calling C code is not supported (no virtual "C" package).
|
||||
- Directives about the compiler, the linker, or embedding files are not supported.
|
||||
- Interfaces to be used from the pre-compiled code can not be added dynamically, as it is required to pre-compile interface wrappers.
|
||||
- Representation of types by `reflect` and printing values using %T may give different results between compiled mode and interpreted mode.
|
||||
- Interpreting computation intensive code is likely to remain significantly slower than in compiled mode.
|
||||
|
||||
@@ -15,11 +15,10 @@ func main() {
|
||||
r := extendedRequest{}
|
||||
req := &r.Request
|
||||
|
||||
|
||||
fmt.Println(r)
|
||||
fmt.Println(req)
|
||||
fmt.Printf("%T\n", r.Request)
|
||||
fmt.Printf("%T\n", req)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// {{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>} }
|
||||
// &{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>}
|
||||
// http.Request
|
||||
// *http.Request
|
||||
|
||||
11
_test/assert4.go
Normal file
11
_test/assert4.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
var cc interface{} = 2
|
||||
var dd = cc.(int)
|
||||
|
||||
func main() {
|
||||
println(dd)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
15
_test/issue-1536.go
Normal file
15
_test/issue-1536.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
var a [len(prefix+path) + 2]int
|
||||
|
||||
const (
|
||||
prefix = "/usr/"
|
||||
path = prefix + "local/bin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(len(a))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 21
|
||||
20
_test/issue-1571.go
Normal file
20
_test/issue-1571.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
type A struct {
|
||||
*B[string]
|
||||
}
|
||||
|
||||
type B[T any] struct {
|
||||
data T
|
||||
}
|
||||
|
||||
func main() {
|
||||
_ = &A{
|
||||
B: &B[string]{},
|
||||
}
|
||||
|
||||
println("PASS")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// PASS
|
||||
17
_test/issue-1594.go
Normal file
17
_test/issue-1594.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var fns []func()
|
||||
for _, v := range []int{1, 2, 3} {
|
||||
x := v*100 + v
|
||||
fns = append(fns, func() { println(x) })
|
||||
}
|
||||
for _, fn := range fns {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 101
|
||||
// 202
|
||||
// 303
|
||||
32
_test/method40.go
Normal file
32
_test/method40.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
type TMemoryBuffer struct {
|
||||
*bytes.Buffer
|
||||
size int
|
||||
}
|
||||
|
||||
func newTMemoryBuffer() *TMemoryBuffer {
|
||||
return &TMemoryBuffer{}
|
||||
}
|
||||
|
||||
var globalMemoryBuffer = newTMemoryBuffer()
|
||||
|
||||
type TTransport interface {
|
||||
io.ReadWriter
|
||||
}
|
||||
|
||||
func check(t TTransport) {
|
||||
println("ok")
|
||||
}
|
||||
|
||||
func main() {
|
||||
check(globalMemoryBuffer)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// ok
|
||||
20
_test/panic0.go
Normal file
20
_test/panic0.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
foo()
|
||||
}
|
||||
|
||||
func foo() {
|
||||
bar()
|
||||
}
|
||||
|
||||
func bar() {
|
||||
baz()
|
||||
}
|
||||
|
||||
func baz() {
|
||||
panic("stop!")
|
||||
}
|
||||
|
||||
// Error:
|
||||
// stop!
|
||||
17
_test/unsafe10.go
Normal file
17
_test/unsafe10.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type T struct {
|
||||
X uint64
|
||||
Y uint64
|
||||
}
|
||||
|
||||
func f(off uintptr) { println(off) }
|
||||
|
||||
func main() {
|
||||
f(unsafe.Offsetof(T{}.Y))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 8
|
||||
@@ -21,3 +21,6 @@ func main() {
|
||||
|
||||
fmt.Println(i)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 5
|
||||
|
||||
18
_test/unsafe8.go
Normal file
18
_test/unsafe8.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type T struct {
|
||||
i uint64
|
||||
}
|
||||
|
||||
var d T
|
||||
|
||||
var b [unsafe.Sizeof(d)]byte
|
||||
|
||||
func main() {
|
||||
println(len(b))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 8
|
||||
@@ -69,7 +69,7 @@ func extractCmd(arg []string) error {
|
||||
ext.Include = strings.Split(include, ",")
|
||||
}
|
||||
|
||||
r := strings.NewReplacer("/", "-", ".", "_")
|
||||
r := strings.NewReplacer("/", "-", ".", "_", "~", "_")
|
||||
|
||||
for _, pkgIdent := range args {
|
||||
var buf bytes.Buffer
|
||||
|
||||
@@ -128,7 +128,7 @@ func TestPackages(t *testing.T) {
|
||||
if test.topImport != "" {
|
||||
topImport = test.topImport
|
||||
}
|
||||
if _, err = i.Eval(fmt.Sprintf(`import "%s"`, topImport)); err != nil {
|
||||
if _, err = i.Eval(fmt.Sprintf(`import %q`, topImport)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
value, err := i.Eval(`pkg.NewSample()`)
|
||||
|
||||
@@ -39,7 +39,9 @@ import (
|
||||
"{{$key}}"
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
{{- if or .Val .Typ }}
|
||||
"{{.ImportPath}}"
|
||||
{{- end}}
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@@ -130,9 +132,18 @@ func matchList(name string, list []string) (match bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Extractor creates a package with all the symbols from a dependency package.
|
||||
type Extractor struct {
|
||||
Dest string // The name of the created package.
|
||||
License string // License text to be included in the created package, optional.
|
||||
Exclude []string // Comma separated list of regexp matching symbols to exclude.
|
||||
Include []string // Comma separated list of regexp matching symbols to include.
|
||||
Tag []string // Comma separated of build tags to be added to the created package.
|
||||
}
|
||||
|
||||
func (e *Extractor) genContent(importPath string, p *types.Package) ([]byte, error) {
|
||||
prefix := "_" + importPath + "_"
|
||||
prefix = strings.NewReplacer("/", "_", "-", "_", ".", "_").Replace(prefix)
|
||||
prefix = strings.NewReplacer("/", "_", "-", "_", ".", "_", "~", "_").Replace(prefix)
|
||||
|
||||
typ := map[string]string{}
|
||||
val := map[string]Val{}
|
||||
@@ -190,6 +201,10 @@ func (e *Extractor) genContent(importPath string, p *types.Package) ([]byte, err
|
||||
val[name] = Val{pname, false}
|
||||
}
|
||||
case *types.Func:
|
||||
// Skip generic functions and methods.
|
||||
if s := o.Type().(*types.Signature); s.TypeParams().Len() > 0 || s.RecvTypeParams().Len() > 0 {
|
||||
continue
|
||||
}
|
||||
val[name] = Val{pname, false}
|
||||
case *types.Var:
|
||||
val[name] = Val{pname, true}
|
||||
@@ -198,9 +213,13 @@ func (e *Extractor) genContent(importPath string, p *types.Package) ([]byte, err
|
||||
if t, ok := o.Type().(*types.Named); ok && t.TypeParams().Len() > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
typ[name] = pname
|
||||
if t, ok := o.Type().Underlying().(*types.Interface); ok {
|
||||
if t.NumMethods() == 0 && t.NumEmbeddeds() != 0 {
|
||||
// Skip interfaces used to implement constraints for generics.
|
||||
delete(typ, name)
|
||||
continue
|
||||
}
|
||||
var methods []Method
|
||||
for i := 0; i < t.NumMethods(); i++ {
|
||||
f := t.Method(i)
|
||||
@@ -283,11 +302,11 @@ func (e *Extractor) genContent(importPath string, p *types.Package) ([]byte, err
|
||||
}
|
||||
|
||||
for _, t := range e.Tag {
|
||||
if len(t) != 0 {
|
||||
if t != "" {
|
||||
buildTags += "," + t
|
||||
}
|
||||
}
|
||||
if len(buildTags) != 0 && buildTags[0] == ',' {
|
||||
if buildTags != "" && buildTags[0] == ',' {
|
||||
buildTags = buildTags[1:]
|
||||
}
|
||||
|
||||
@@ -340,7 +359,7 @@ func fixConst(name string, val constant.Value, imports map[string]bool) string {
|
||||
str = f.Text('g', int(f.Prec()))
|
||||
case constant.Complex:
|
||||
// TODO: not sure how to parse this case
|
||||
fallthrough
|
||||
fallthrough //nolint:gocritic // Empty Fallthrough is expected.
|
||||
default:
|
||||
return name
|
||||
}
|
||||
@@ -351,15 +370,6 @@ func fixConst(name string, val constant.Value, imports map[string]bool) string {
|
||||
return fmt.Sprintf("constant.MakeFromLiteral(%q, token.%s, 0)", str, tok)
|
||||
}
|
||||
|
||||
// Extractor creates a package with all the symbols from a dependency package.
|
||||
type Extractor struct {
|
||||
Dest string // The name of the created package.
|
||||
License string // License text to be included in the created package, optional.
|
||||
Exclude []string // Comma separated list of regexp matching symbols to exclude.
|
||||
Include []string // Comma separated list of regexp matching symbols to include.
|
||||
Tag []string // Comma separated of build tags to be added to the created package.
|
||||
}
|
||||
|
||||
// importPath checks whether pkgIdent is an existing directory relative to
|
||||
// e.WorkingDir. If yes, it returns the actual import path of the Go package
|
||||
// located in the directory. If it is definitely a relative path, but it does not
|
||||
@@ -468,7 +478,7 @@ func GetMinor(part string) string {
|
||||
return minor
|
||||
}
|
||||
|
||||
const defaultMinorVersion = 20
|
||||
const defaultMinorVersion = 22
|
||||
|
||||
func genBuildTags() (string, error) {
|
||||
version := runtime.Version()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build !go1.21
|
||||
// +build !go1.21
|
||||
|
||||
// Package unsafe2 provides helpers to generate recursive struct types.
|
||||
package unsafe2
|
||||
|
||||
72
internal/unsafe2/go1_21_unsafe.go
Normal file
72
internal/unsafe2/go1_21_unsafe.go
Normal file
@@ -0,0 +1,72 @@
|
||||
//go:build go1.21
|
||||
// +build go1.21
|
||||
|
||||
// Package unsafe2 provides helpers to generate recursive struct types.
|
||||
package unsafe2
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type dummy struct{}
|
||||
|
||||
// DummyType represents a stand-in for a recursive type.
|
||||
var DummyType = reflect.TypeOf(dummy{})
|
||||
|
||||
// The following type sizes must match their original definition in Go src/internal/abi/type.go.
|
||||
type abiType struct {
|
||||
_ uintptr
|
||||
_ uintptr
|
||||
_ uint32
|
||||
_ uint8
|
||||
_ uint8
|
||||
_ uint8
|
||||
_ uint8
|
||||
_ uintptr
|
||||
_ uintptr
|
||||
_ int32
|
||||
_ int32
|
||||
}
|
||||
|
||||
type abiName struct {
|
||||
Bytes *byte
|
||||
}
|
||||
|
||||
type abiStructField struct {
|
||||
Name abiName
|
||||
Typ *abiType
|
||||
Offset uintptr
|
||||
}
|
||||
|
||||
type abiStructType struct {
|
||||
abiType
|
||||
PkgPath abiName
|
||||
Fields []abiStructField
|
||||
}
|
||||
|
||||
type emptyInterface struct {
|
||||
typ *abiType
|
||||
_ unsafe.Pointer
|
||||
}
|
||||
|
||||
// SetFieldType sets the type of the struct field at the given index, to the given type.
|
||||
//
|
||||
// The struct type must have been created at runtime. This is very unsafe.
|
||||
func SetFieldType(s reflect.Type, idx int, t reflect.Type) {
|
||||
if s.Kind() != reflect.Struct || idx >= s.NumField() {
|
||||
return
|
||||
}
|
||||
|
||||
rtyp := unpackType(s)
|
||||
styp := (*abiStructType)(unsafe.Pointer(rtyp))
|
||||
f := styp.Fields[idx]
|
||||
f.Typ = unpackType(t)
|
||||
styp.Fields[idx] = f
|
||||
}
|
||||
|
||||
func unpackType(t reflect.Type) *abiType {
|
||||
v := reflect.New(t).Elem().Interface()
|
||||
eface := *(*emptyInterface)(unsafe.Pointer(&v))
|
||||
return eface.typ
|
||||
}
|
||||
@@ -182,6 +182,7 @@ var knownOs = map[string]bool{
|
||||
"openbsd": true,
|
||||
"plan9": true,
|
||||
"solaris": true,
|
||||
"wasip1": true,
|
||||
"windows": true,
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,13 @@ var constBltn = map[string]func(*node){
|
||||
|
||||
const nilIdent = "nil"
|
||||
|
||||
func init() {
|
||||
// Use init() to avoid initialization cycles for the following constant builtins.
|
||||
constBltn[bltnAlignof] = alignof
|
||||
constBltn[bltnOffsetof] = offsetof
|
||||
constBltn[bltnSizeof] = sizeof
|
||||
}
|
||||
|
||||
// cfg generates a control flow graph (CFG) from AST (wiring successors in AST)
|
||||
// and pre-compute frame sizes and indexes for all un-named (temporary) and named
|
||||
// variables. A list of nodes of init functions is returned.
|
||||
@@ -422,7 +429,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
case funcDecl:
|
||||
// Do not allow function declarations without body.
|
||||
if len(n.child) < 4 {
|
||||
err = n.cfgErrorf("function declaration without body is unsupported (linkname or assembly can not be interpreted).")
|
||||
err = n.cfgErrorf("missing function body")
|
||||
return false
|
||||
}
|
||||
n.val = n
|
||||
@@ -748,7 +755,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
n.gen = nop
|
||||
src.findex = dest.findex
|
||||
src.level = level
|
||||
case len(n.child) < 4 && isArithmeticAction(src) && !isInterface(dest.typ):
|
||||
case len(n.child) < 4 && n.kind != defineStmt && isArithmeticAction(src) && !isInterface(dest.typ):
|
||||
// Optimize single assignments from some arithmetic operations.
|
||||
src.typ = dest.typ
|
||||
src.findex = dest.findex
|
||||
@@ -1154,6 +1161,10 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
case n.typ.cat == builtinT:
|
||||
n.findex = notInFrame
|
||||
n.val = nil
|
||||
switch bname {
|
||||
case "unsafe.alignOf", "unsafe.Offsetof", "unsafe.Sizeof":
|
||||
n.gen = nop
|
||||
}
|
||||
case n.anc.kind == returnStmt:
|
||||
// Store result directly to frame output location, to avoid a frame copy.
|
||||
n.findex = 0
|
||||
@@ -1186,8 +1197,8 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
default:
|
||||
n.findex = sc.add(n.typ)
|
||||
}
|
||||
if op, ok := constBltn[bname]; ok && n.anc.action != aAssign {
|
||||
op(n) // pre-compute non-assigned constant :
|
||||
if op, ok := constBltn[bname]; ok {
|
||||
op(n)
|
||||
}
|
||||
|
||||
case c0.isType(sc):
|
||||
@@ -1268,21 +1279,6 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
}
|
||||
}
|
||||
|
||||
case isOffsetof(c0):
|
||||
if len(n.child) != 2 || n.child[1].kind != selectorExpr || !isStruct(n.child[1].child[0].typ) {
|
||||
err = n.cfgErrorf("Offsetof argument: invalid expression")
|
||||
break
|
||||
}
|
||||
c1 := n.child[1]
|
||||
field, ok := c1.child[0].typ.rtype.FieldByName(c1.child[1].ident)
|
||||
if !ok {
|
||||
err = n.cfgErrorf("struct does not contain field: %s", c1.child[1].ident)
|
||||
break
|
||||
}
|
||||
n.typ = valueTOf(reflect.TypeOf(field.Offset))
|
||||
n.rval = reflect.ValueOf(field.Offset)
|
||||
n.gen = nop
|
||||
|
||||
default:
|
||||
// The call may be on a generic function. In that case, replace the
|
||||
// generic function AST by an instantiated one before going further.
|
||||
@@ -1816,6 +1812,10 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
} else {
|
||||
n.typ = valueTOf(fixPossibleConstType(s.Type()), withUntyped(isValueUntyped(s)))
|
||||
n.rval = s
|
||||
if pkg == "unsafe" && (name == "AlignOf" || name == "Offsetof" || name == "Sizeof") {
|
||||
n.sym = &symbol{kind: bltnSym, node: n, rval: s}
|
||||
n.ident = pkg + "." + name
|
||||
}
|
||||
}
|
||||
n.action = aGetSym
|
||||
n.gen = nop
|
||||
@@ -2794,10 +2794,6 @@ func isBinCall(n *node, sc *scope) bool {
|
||||
return c0.typ.cat == valueT && c0.typ.rtype.Kind() == reflect.Func
|
||||
}
|
||||
|
||||
func isOffsetof(n *node) bool {
|
||||
return n.typ != nil && n.typ.cat == valueT && n.rval.String() == "Offsetof"
|
||||
}
|
||||
|
||||
func mustReturnValue(n *node) bool {
|
||||
if len(n.child) < 3 {
|
||||
return false
|
||||
@@ -3136,3 +3132,24 @@ func isBlank(n *node) bool {
|
||||
}
|
||||
return n.ident == "_"
|
||||
}
|
||||
|
||||
func alignof(n *node) {
|
||||
n.gen = nop
|
||||
n.typ = n.scope.getType("uintptr")
|
||||
n.rval = reflect.ValueOf(uintptr(n.child[1].typ.TypeOf().Align()))
|
||||
}
|
||||
|
||||
func offsetof(n *node) {
|
||||
n.gen = nop
|
||||
n.typ = n.scope.getType("uintptr")
|
||||
c1 := n.child[1]
|
||||
if field, ok := c1.child[0].typ.rtype.FieldByName(c1.child[1].ident); ok {
|
||||
n.rval = reflect.ValueOf(field.Offset)
|
||||
}
|
||||
}
|
||||
|
||||
func sizeof(n *node) {
|
||||
n.gen = nop
|
||||
n.typ = n.scope.getType("uintptr")
|
||||
n.rval = reflect.ValueOf(n.child[1].typ.TypeOf().Size())
|
||||
}
|
||||
|
||||
@@ -306,12 +306,12 @@ func checkConstraint(it, ct *itype) error {
|
||||
return nil
|
||||
}
|
||||
for _, c := range ct.constraint {
|
||||
if it.equals(c) {
|
||||
if it.equals(c) || it.matchDefault(c) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
for _, c := range ct.ulconstraint {
|
||||
if it.underlying().equals(c) {
|
||||
if it.underlying().equals(c) || it.matchDefault(c) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,14 +184,14 @@ type opt struct {
|
||||
noRun bool // compile, but do not run
|
||||
fastChan bool // disable cancellable chan operations
|
||||
specialStdio bool // allows os.Stdin, os.Stdout, os.Stderr to not be file descriptors
|
||||
unrestricted bool // allow use of non sandboxed symbols
|
||||
unrestricted bool // allow use of non-sandboxed symbols
|
||||
}
|
||||
|
||||
// Interpreter contains global resources and state.
|
||||
type Interpreter struct {
|
||||
// id is an atomic counter counter used for run cancellation,
|
||||
// id is an atomic counter used for run cancellation,
|
||||
// only accessed via runid/stop
|
||||
// Located at start of struct to ensure proper alignment on 32 bit
|
||||
// Located at start of struct to ensure proper alignment on 32-bit
|
||||
// architectures.
|
||||
id uint64
|
||||
|
||||
@@ -405,6 +405,7 @@ func New(options Options) *Interpreter {
|
||||
}
|
||||
|
||||
const (
|
||||
bltnAlignof = "unsafe.Alignof"
|
||||
bltnAppend = "append"
|
||||
bltnCap = "cap"
|
||||
bltnClose = "close"
|
||||
@@ -415,11 +416,13 @@ const (
|
||||
bltnLen = "len"
|
||||
bltnMake = "make"
|
||||
bltnNew = "new"
|
||||
bltnOffsetof = "unsafe.Offsetof"
|
||||
bltnPanic = "panic"
|
||||
bltnPrint = "print"
|
||||
bltnPrintln = "println"
|
||||
bltnReal = "real"
|
||||
bltnRecover = "recover"
|
||||
bltnSizeof = "unsafe.Sizeof"
|
||||
)
|
||||
|
||||
func initUniverse() *scope {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package interp_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/build"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -14,6 +16,13 @@ import (
|
||||
"github.com/traefik/yaegi/stdlib/unsafe"
|
||||
)
|
||||
|
||||
// The following tests depend on an incompatible language change in go1.22, where `for` variables are now
|
||||
// defined in body (thus reallocated at each loop). We skip them until both supported versions behave the same.
|
||||
// We will remove this in Go1.23.
|
||||
var testsToSkipGo122 = map[string]bool{"closure9.go": true, "closure10.go": true, "closure11.go": true, "closure12.go": true}
|
||||
|
||||
var go122 = strings.HasPrefix(runtime.Version(), "go1.22")
|
||||
|
||||
func TestInterpConsistencyBuild(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("short mode")
|
||||
@@ -89,6 +98,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
file.Name() == "redeclaration-global5.go" || // expect error
|
||||
file.Name() == "redeclaration-global6.go" || // expect error
|
||||
file.Name() == "redeclaration-global7.go" || // expect error
|
||||
file.Name() == "panic0.go" || // expect error
|
||||
file.Name() == "pkgname0.go" || // has deps
|
||||
file.Name() == "pkgname1.go" || // expect error
|
||||
file.Name() == "pkgname2.go" || // has deps
|
||||
@@ -119,6 +129,13 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
file.Name() == "type33.go" { // expect error
|
||||
continue
|
||||
}
|
||||
// Skip some tests which are problematic in go1.21 only.
|
||||
if go121 && testsToSkipGo121[file.Name()] {
|
||||
continue
|
||||
}
|
||||
if go122 && testsToSkipGo122[file.Name()] {
|
||||
continue
|
||||
}
|
||||
|
||||
file := file
|
||||
t.Run(file.Name(), func(t *testing.T) {
|
||||
@@ -176,7 +193,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(outInterp) != string(outRun) {
|
||||
if !bytes.Equal(outInterp, outRun) {
|
||||
t.Errorf("\nGot: %q,\n want: %q", string(outInterp), string(outRun))
|
||||
}
|
||||
})
|
||||
@@ -187,6 +204,7 @@ func TestInterpErrorConsistency(t *testing.T) {
|
||||
testCases := []struct {
|
||||
fileName string
|
||||
expectedInterp string
|
||||
expectedStderr string
|
||||
expectedExec string
|
||||
}{
|
||||
{
|
||||
@@ -284,17 +302,28 @@ func TestInterpErrorConsistency(t *testing.T) {
|
||||
expectedInterp: "37:2: duplicate case Bir in type switch",
|
||||
expectedExec: "37:7: duplicate case Bir in type switch",
|
||||
},
|
||||
{
|
||||
fileName: "panic0.go",
|
||||
expectedInterp: "stop!",
|
||||
expectedStderr: `
|
||||
../_test/panic0.go:16:2: panic: main.baz(...)
|
||||
../_test/panic0.go:12:2: panic: main.bar(...)
|
||||
../_test/panic0.go:8:2: panic: main.foo(...)
|
||||
../_test/panic0.go:4:2: panic: main.main(...)
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.fileName, func(t *testing.T) {
|
||||
if len(test.expectedInterp) == 0 && len(test.expectedExec) == 0 {
|
||||
t.Fatal("at least expectedInterp must be define")
|
||||
if test.expectedInterp == "" && test.expectedExec == "" {
|
||||
t.Fatal("at least expectedInterp must be defined")
|
||||
}
|
||||
|
||||
filePath := filepath.Join("..", "_test", test.fileName)
|
||||
|
||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH})
|
||||
var stderr bytes.Buffer
|
||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, Stderr: &stderr})
|
||||
if err := i.Use(stdlib.Symbols); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -307,6 +336,12 @@ func TestInterpErrorConsistency(t *testing.T) {
|
||||
if !strings.Contains(errEval.Error(), test.expectedInterp) {
|
||||
t.Errorf("got %q, want: %q", errEval.Error(), test.expectedInterp)
|
||||
}
|
||||
if test.expectedStderr != "" {
|
||||
exp, got := strings.TrimSpace(test.expectedStderr), strings.TrimSpace(stderr.String())
|
||||
if exp != got {
|
||||
t.Errorf("got %q, want: %q", got, exp)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "run", filePath)
|
||||
outRun, errExec := cmd.CombinedOutput()
|
||||
@@ -315,7 +350,7 @@ func TestInterpErrorConsistency(t *testing.T) {
|
||||
t.Fatal("An error is expected but got none.")
|
||||
}
|
||||
|
||||
if len(test.expectedExec) == 0 && !strings.Contains(string(outRun), test.expectedInterp) {
|
||||
if test.expectedExec == "" && !strings.Contains(string(outRun), test.expectedInterp) {
|
||||
t.Errorf("got %q, want: %q", string(outRun), test.expectedInterp)
|
||||
} else if !strings.Contains(string(outRun), test.expectedExec) {
|
||||
t.Errorf("got %q, want: %q", string(outRun), test.expectedExec)
|
||||
|
||||
@@ -708,7 +708,7 @@ func TestEvalCall(t *testing.T) {
|
||||
{src: ` test := func(a, b int) int { return a }
|
||||
blah := func() (int, float64) { return 1, 1.1 }
|
||||
a := test(blah())`, err: "3:15: cannot use func() (int,float64) as type (int,int)"},
|
||||
{src: "func f()", err: "function declaration without body is unsupported"},
|
||||
{src: "func f()", err: "missing function body"},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1095,6 +1095,10 @@ func main() {
|
||||
}
|
||||
|
||||
func TestImportPathIsKey(t *testing.T) {
|
||||
// FIXME(marc): support of stdlib generic packages like "cmp", "maps", "slices" has changed
|
||||
// the scope layout by introducing new source packages when stdlib is used.
|
||||
// The logic of the following test doesn't apply anymore.
|
||||
t.Skip("This test needs to be reworked.")
|
||||
// No need to check the results of Eval, as TestFile already does it.
|
||||
i := interp.New(interp.Options{GoPath: filepath.FromSlash("../_test/testdata/redeclaration-global7")})
|
||||
if err := i.Use(stdlib.Symbols); err != nil {
|
||||
@@ -1252,11 +1256,10 @@ func TestConcurrentEvals2(t *testing.T) {
|
||||
if hello1 {
|
||||
if l == "hello world2" {
|
||||
break
|
||||
} else {
|
||||
}
|
||||
done <- fmt.Errorf("unexpected output: %v", l)
|
||||
return
|
||||
}
|
||||
}
|
||||
if l == "hello world1" {
|
||||
hello1 = true
|
||||
} else {
|
||||
@@ -1335,7 +1338,7 @@ func TestConcurrentEvals3(t *testing.T) {
|
||||
}()
|
||||
|
||||
for _, v := range input {
|
||||
in := strings.NewReader(fmt.Sprintf("println(\"%s\")\n", v))
|
||||
in := strings.NewReader(fmt.Sprintf("println(%q)\n", v))
|
||||
if _, err := io.Copy(poutin, in); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1880,25 +1883,25 @@ func TestIssue1383(t *testing.T) {
|
||||
}
|
||||
`
|
||||
|
||||
interp := interp.New(interp.Options{})
|
||||
err := interp.Use(stdlib.Symbols)
|
||||
i := interp.New(interp.Options{})
|
||||
err := i.Use(stdlib.Symbols)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = interp.Eval(`import "fmt"`)
|
||||
_, err = i.Eval(`import "fmt"`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ast, err := parser.ParseFile(interp.FileSet(), "_.go", src, parser.DeclarationErrors)
|
||||
ast, err := parser.ParseFile(i.FileSet(), "_.go", src, parser.DeclarationErrors)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prog, err := interp.CompileAST(ast)
|
||||
prog, err := i.CompileAST(ast)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = interp.Execute(prog)
|
||||
_, err = i.Execute(prog)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -16,6 +17,12 @@ import (
|
||||
"github.com/traefik/yaegi/stdlib/unsafe"
|
||||
)
|
||||
|
||||
// The following tests sometimes (not always) crash with go1.21 but not with go1.20 or go1.22.
|
||||
// The reason of failure is not obvious, maybe due to the runtime itself, and will be investigated separately.
|
||||
var testsToSkipGo121 = map[string]bool{"cli6.go": true, "cli7.go": true, "issue-1276.go": true, "issue-1330.go": true, "struct11.go": true}
|
||||
|
||||
var go121 = strings.HasPrefix(runtime.Version(), "go1.21")
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
filePath := "../_test/str.go"
|
||||
runCheck(t, filePath)
|
||||
@@ -27,10 +34,15 @@ func TestFile(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) != ".go" {
|
||||
continue
|
||||
}
|
||||
// Skip some tests which are problematic in go1.21 only.
|
||||
if go121 && testsToSkipGo121[file.Name()] {
|
||||
continue
|
||||
}
|
||||
file := file
|
||||
t.Run(file.Name(), func(t *testing.T) {
|
||||
runCheck(t, filepath.Join(baseDir, file.Name()))
|
||||
@@ -98,7 +110,7 @@ func wantedFromComment(p string) (res string, goPath string, err bool) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
goPath = filepath.Join(wd, "../_test", strings.TrimPrefix(parts[0], "GOPATH:"))
|
||||
goPath = filepath.Join(wd, "..", "_test", strings.TrimPrefix(parts[0], "GOPATH:"))
|
||||
}
|
||||
if strings.HasPrefix(text, "Output:\n") {
|
||||
return strings.TrimPrefix(text, "Output:\n"), goPath, false
|
||||
|
||||
@@ -180,6 +180,27 @@ var errAbortHandler = errors.New("net/http: abort Handler")
|
||||
|
||||
// Functions set to run during execution of CFG.
|
||||
|
||||
func panicFunc(s *scope) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
def := s.def
|
||||
if def == nil {
|
||||
return s.pkgID
|
||||
}
|
||||
switch def.kind {
|
||||
case funcDecl:
|
||||
if c := def.child[1]; c.kind == identExpr {
|
||||
return s.pkgID + "." + c.ident
|
||||
}
|
||||
case funcLit:
|
||||
if def.anc != nil {
|
||||
return panicFunc(def.anc.scope) + ".func"
|
||||
}
|
||||
}
|
||||
return s.pkgID
|
||||
}
|
||||
|
||||
// runCfg executes a node AST by walking its CFG and running node builtin at each step.
|
||||
func runCfg(n *node, f *frame, funcNode, callNode *node) {
|
||||
var exec bltn
|
||||
@@ -199,7 +220,7 @@ func runCfg(n *node, f *frame, funcNode, callNode *node) {
|
||||
// suppress the logging here accordingly, to get a similar and consistent
|
||||
// behavior.
|
||||
if !ok || errorer.Error() != errAbortHandler.Error() {
|
||||
fmt.Fprintln(n.interp.stderr, oNode.cfgErrorf("panic"))
|
||||
fmt.Fprintln(n.interp.stderr, oNode.cfgErrorf("panic: %s(...)", panicFunc(oNode.scope)))
|
||||
}
|
||||
f.mutex.Unlock()
|
||||
panic(f.recovered)
|
||||
@@ -1958,7 +1979,7 @@ func getMethodByName(n *node) {
|
||||
}
|
||||
if val, ok = val0.Field(i).Interface().(valueInterface); ok {
|
||||
break
|
||||
// TODO: should we keep track of all the the vals that are indeed valueInterface,
|
||||
// TODO: should we keep track of all the vals that are indeed valueInterface,
|
||||
// so that later on we can call MethodByName on all of them until one matches?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -208,7 +209,7 @@ func (interp *Interpreter) pkgDir(goPath string, root, importPath string) (strin
|
||||
return dir, root, nil // found!
|
||||
}
|
||||
|
||||
if len(root) == 0 {
|
||||
if root == "" {
|
||||
if interp.context.GOPATH == "" {
|
||||
return "", "", fmt.Errorf("unable to find source related to: %q. Either the GOPATH environment variable, or the Interpreter.Options.GoPath needs to be set", importPath)
|
||||
}
|
||||
@@ -245,7 +246,7 @@ func previousRoot(filesystem fs.FS, rootPath, root string) (string, error) {
|
||||
vendored = strings.TrimPrefix(strings.TrimPrefix(parent, prefix), string(filepath.Separator))
|
||||
break
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return "", err
|
||||
}
|
||||
// stop when we reach GOPATH/src
|
||||
|
||||
@@ -484,6 +484,7 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
length = int(vInt(sym.rval))
|
||||
default:
|
||||
// Size is defined by a numeric constant expression.
|
||||
var ok bool
|
||||
if _, err := interp.cfg(c0, sc, sc.pkgID, sc.pkgName); err != nil {
|
||||
if strings.Contains(err.Error(), " undefined: ") {
|
||||
incomplete = true
|
||||
@@ -491,6 +492,10 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if !c0.rval.IsValid() {
|
||||
return nil, c0.cfgErrorf("undefined array size")
|
||||
}
|
||||
if length, ok = c0.rval.Interface().(int); !ok {
|
||||
v, ok := c0.rval.Interface().(constant.Value)
|
||||
if !ok {
|
||||
incomplete = true
|
||||
@@ -498,6 +503,7 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
}
|
||||
length = constToInt(v)
|
||||
}
|
||||
}
|
||||
val, err := nodeType2(interp, sc, n.child[1], seen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -983,16 +989,18 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
rtype = rtype.Elem()
|
||||
}
|
||||
t = valueTOf(rtype, withNode(n), withScope(sc))
|
||||
} else {
|
||||
err = n.cfgErrorf("undefined selector %s.%s", lt.path, name)
|
||||
break
|
||||
}
|
||||
// Continue search in source package, as it may exist if package contains generics.
|
||||
fallthrough
|
||||
case srcPkgT:
|
||||
pkg := interp.srcPkg[lt.path]
|
||||
if pkg, ok := interp.srcPkg[lt.path]; ok {
|
||||
if s, ok := pkg[name]; ok {
|
||||
t = s.typ
|
||||
} else {
|
||||
err = n.cfgErrorf("undefined selector %s.%s", lt.path, name)
|
||||
break
|
||||
}
|
||||
}
|
||||
err = n.cfgErrorf("undefined selector %s.%s", lt.path, name)
|
||||
default:
|
||||
if m, _ := lt.lookupMethod(name); m != nil {
|
||||
t, err = nodeType2(interp, sc, m.child[2], seen)
|
||||
@@ -1087,6 +1095,9 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
sc.sym[sname].typ = t
|
||||
}
|
||||
|
||||
case typeAssertExpr:
|
||||
t, err = nodeType2(interp, sc, n.child[1], seen)
|
||||
|
||||
default:
|
||||
err = n.cfgErrorf("type definition not implemented: %s", n.kind)
|
||||
}
|
||||
@@ -1221,6 +1232,8 @@ func fieldName(n *node) string {
|
||||
return fieldName(n.child[1])
|
||||
case starExpr:
|
||||
return fieldName(n.child[0])
|
||||
case indexExpr:
|
||||
return fieldName(n.child[0])
|
||||
case identExpr:
|
||||
return n.ident
|
||||
default:
|
||||
@@ -1336,7 +1349,7 @@ func (t *itype) numOut() int {
|
||||
}
|
||||
case builtinT:
|
||||
switch t.name {
|
||||
case "append", "cap", "complex", "copy", "imag", "len", "make", "new", "real", "recover":
|
||||
case "append", "cap", "complex", "copy", "imag", "len", "make", "new", "real", "recover", "unsafe.Alignof", "unsafe.Offsetof", "unsafe.Sizeof":
|
||||
return 1
|
||||
}
|
||||
}
|
||||
@@ -1522,7 +1535,7 @@ func (t *itype) ordered() bool {
|
||||
return isInt(typ) || isFloat(typ) || isString(typ)
|
||||
}
|
||||
|
||||
// Equals returns true if the given type is identical to the receiver one.
|
||||
// equals returns true if the given type is identical to the receiver one.
|
||||
func (t *itype) equals(o *itype) bool {
|
||||
switch ti, oi := isInterface(t), isInterface(o); {
|
||||
case ti && oi:
|
||||
@@ -1536,13 +1549,21 @@ func (t *itype) equals(o *itype) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// matchDefault returns true if the receiver default type is the same as the given one.
|
||||
func (t *itype) matchDefault(o *itype) bool {
|
||||
return t.untyped && t.id() == "untyped "+o.id()
|
||||
}
|
||||
|
||||
// MethodSet defines the set of methods signatures as strings, indexed per method name.
|
||||
type methodSet map[string]string
|
||||
|
||||
// Contains returns true if the method set m contains the method set n.
|
||||
func (m methodSet) contains(n methodSet) bool {
|
||||
for k, v := range n {
|
||||
if m[k] != v {
|
||||
for k := range n {
|
||||
// Only check the presence of method, not its complete signature,
|
||||
// as the receiver may be part of the arguments, which makes a
|
||||
// robust check complex.
|
||||
if _, ok := m[k]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -2129,8 +2150,14 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type {
|
||||
var fields []reflect.StructField
|
||||
for _, f := range t.field {
|
||||
field := reflect.StructField{
|
||||
Name: exportName(f.name), Type: f.typ.refType(ctx),
|
||||
Tag: reflect.StructTag(f.tag), Anonymous: f.embed,
|
||||
Name: exportName(f.name),
|
||||
Type: f.typ.refType(ctx),
|
||||
Tag: reflect.StructTag(f.tag),
|
||||
}
|
||||
if len(t.field) == 1 && f.embed {
|
||||
// Mark the field as embedded (anonymous) only if it is the
|
||||
// only one, to avoid a panic due to golang/go#15924 issue.
|
||||
field.Anonymous = true
|
||||
}
|
||||
fields = append(fields, field)
|
||||
// Find any nil type refs that indicates a rebuild is needed on this field.
|
||||
|
||||
@@ -723,6 +723,7 @@ var builtinFuncs = map[string]struct {
|
||||
args int
|
||||
variadic bool
|
||||
}{
|
||||
bltnAlignof: {args: 1, variadic: false},
|
||||
bltnAppend: {args: 1, variadic: true},
|
||||
bltnCap: {args: 1, variadic: false},
|
||||
bltnClose: {args: 1, variadic: false},
|
||||
@@ -733,11 +734,13 @@ var builtinFuncs = map[string]struct {
|
||||
bltnLen: {args: 1, variadic: false},
|
||||
bltnMake: {args: 1, variadic: true},
|
||||
bltnNew: {args: 1, variadic: false},
|
||||
bltnOffsetof: {args: 1, variadic: false},
|
||||
bltnPanic: {args: 1, variadic: false},
|
||||
bltnPrint: {args: 0, variadic: true},
|
||||
bltnPrintln: {args: 0, variadic: true},
|
||||
bltnReal: {args: 1, variadic: false},
|
||||
bltnRecover: {args: 0, variadic: false},
|
||||
bltnSizeof: {args: 1, variadic: false},
|
||||
}
|
||||
|
||||
func (check typecheck) builtin(name string, n *node, child []*node, ellipsis bool) error {
|
||||
@@ -927,7 +930,7 @@ func (check typecheck) builtin(name string, n *node, child []*node, ellipsis boo
|
||||
return err
|
||||
}
|
||||
}
|
||||
case bltnRecover, bltnNew:
|
||||
case bltnRecover, bltnNew, bltnAlignof, bltnOffsetof, bltnSizeof:
|
||||
// Nothing to do.
|
||||
default:
|
||||
return n.cfgErrorf("unsupported builtin %s", name)
|
||||
@@ -1093,6 +1096,9 @@ func (check typecheck) convertUntyped(n *node, typ *itype) error {
|
||||
return convErr
|
||||
}
|
||||
return nil
|
||||
case n.typ.isNil() && typ.id() == "unsafe.Pointer":
|
||||
n.typ = typ
|
||||
return nil
|
||||
default:
|
||||
return convErr
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
|
||||
gen "github.com/traefik/yaegi/stdlib/generic"
|
||||
)
|
||||
|
||||
// Symbols returns a map of interpreter exported symbol values for the given
|
||||
@@ -139,6 +141,13 @@ func (interp *Interpreter) Use(values Exports) error {
|
||||
// well known stdlib package path.
|
||||
if _, ok := values["fmt/fmt"]; ok {
|
||||
fixStdlib(interp)
|
||||
|
||||
// Load stdlib generic source.
|
||||
for _, s := range gen.Sources {
|
||||
if _, err := interp.Compile(s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
59
stdlib/generic/go1_21_cmp.go.txt
Normal file
59
stdlib/generic/go1_21_cmp.go.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2023 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 cmp provides types and functions related to comparing
|
||||
// ordered values.
|
||||
package cmp
|
||||
|
||||
// Ordered is a constraint that permits any ordered type: any type
|
||||
// that supports the operators < <= >= >.
|
||||
// If future releases of Go add new ordered types,
|
||||
// this constraint will be modified to include them.
|
||||
//
|
||||
// Note that floating-point types may contain NaN ("not-a-number") values.
|
||||
// An operator such as == or < will always report false when
|
||||
// comparing a NaN value with any other value, NaN or not.
|
||||
// See the [Compare] function for a consistent way to compare NaN values.
|
||||
type Ordered interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
||||
~float32 | ~float64 |
|
||||
~string
|
||||
}
|
||||
|
||||
// Less reports whether x is less than y.
|
||||
// For floating-point types, a NaN is considered less than any non-NaN,
|
||||
// and -0.0 is not less than (is equal to) 0.0.
|
||||
func Less[T Ordered](x, y T) bool {
|
||||
return (isNaN(x) && !isNaN(y)) || x < y
|
||||
}
|
||||
|
||||
// Compare returns
|
||||
//
|
||||
// -1 if x is less than y,
|
||||
// 0 if x equals y,
|
||||
// +1 if x is greater than y.
|
||||
//
|
||||
// For floating-point types, a NaN is considered less than any non-NaN,
|
||||
// a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.
|
||||
func Compare[T Ordered](x, y T) int {
|
||||
xNaN := isNaN(x)
|
||||
yNaN := isNaN(y)
|
||||
if xNaN && yNaN {
|
||||
return 0
|
||||
}
|
||||
if xNaN || x < y {
|
||||
return -1
|
||||
}
|
||||
if yNaN || x > y {
|
||||
return +1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// isNaN reports whether x is a NaN without requiring the math package.
|
||||
// This will always return false if T is not floating-point.
|
||||
func isNaN[T Ordered](x T) bool {
|
||||
return x != x
|
||||
}
|
||||
33
stdlib/generic/go1_21_generic.go
Normal file
33
stdlib/generic/go1_21_generic.go
Normal file
@@ -0,0 +1,33 @@
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package generic
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed go1_21_cmp.go.txt
|
||||
var cmpSource string
|
||||
|
||||
//go:embed go1_21_maps.go.txt
|
||||
var mapsSource string
|
||||
|
||||
//go:embed go1_21_slices.go.txt
|
||||
var slicesSource string
|
||||
|
||||
/*
|
||||
//go:embed go1_21_sync.go.txt
|
||||
var syncSource string
|
||||
|
||||
//go:embed go1_21_sync_atomic.go.txt
|
||||
var syncAtomicSource string
|
||||
*/
|
||||
|
||||
// Sources contains the list of generic packages source strings.
|
||||
var Sources = [...]string{
|
||||
cmpSource,
|
||||
mapsSource,
|
||||
slicesSource,
|
||||
// FIXME(marc): support the following.
|
||||
// syncAtomicSource,
|
||||
// syncSource,
|
||||
}
|
||||
66
stdlib/generic/go1_21_maps.go.txt
Normal file
66
stdlib/generic/go1_21_maps.go.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2021 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 maps defines various functions useful with maps of any type.
|
||||
package maps
|
||||
|
||||
// Equal reports whether two maps contain the same key/value pairs.
|
||||
// Values are compared using ==.
|
||||
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool {
|
||||
if len(m1) != len(m2) {
|
||||
return false
|
||||
}
|
||||
for k, v1 := range m1 {
|
||||
if v2, ok := m2[k]; !ok || v1 != v2 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualFunc is like Equal, but compares values using eq.
|
||||
// Keys are still compared with ==.
|
||||
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool {
|
||||
if len(m1) != len(m2) {
|
||||
return false
|
||||
}
|
||||
for k, v1 := range m1 {
|
||||
if v2, ok := m2[k]; !ok || !eq(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// clone is implemented in the runtime package.
|
||||
func clone(m any) any { return m }
|
||||
|
||||
// Clone returns a copy of m. This is a shallow clone:
|
||||
// the new keys and values are set using ordinary assignment.
|
||||
func Clone[M ~map[K]V, K comparable, V any](m M) M {
|
||||
// Preserve nil in case it matters.
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return clone(m).(M)
|
||||
}
|
||||
|
||||
// Copy copies all key/value pairs in src adding them to dst.
|
||||
// When a key in src is already present in dst,
|
||||
// the value in dst will be overwritten by the value associated
|
||||
// with the key in src.
|
||||
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) {
|
||||
for k, v := range src {
|
||||
dst[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteFunc deletes any key/value pairs from m for which del returns true.
|
||||
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) {
|
||||
for k, v := range m {
|
||||
if del(k, v) {
|
||||
delete(m, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
1651
stdlib/generic/go1_21_slices.go.txt
Normal file
1651
stdlib/generic/go1_21_slices.go.txt
Normal file
File diff suppressed because it is too large
Load Diff
177
stdlib/generic/go1_21_sync.go.txt
Normal file
177
stdlib/generic/go1_21_sync.go.txt
Normal file
@@ -0,0 +1,177 @@
|
||||
// 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 sync
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// OnceFunc returns a function that invokes f only once. The returned function
|
||||
// may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceFunc(f func()) func() {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
)
|
||||
// Construct the inner closure just once to reduce costs on the fast path.
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
// Re-panic immediately so on the first call the user gets a
|
||||
// complete stack trace into f.
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
valid = true // Set only if f does not panic
|
||||
}
|
||||
return func() {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OnceValue returns a function that invokes f only once and returns the value
|
||||
// returned by f. The returned function may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceValue[T any](f func() T) func() T {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
result T
|
||||
)
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
result = f()
|
||||
valid = true
|
||||
}
|
||||
return func() T {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// OnceValues returns a function that invokes f only once and returns the values
|
||||
// returned by f. The returned function may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
r1 T1
|
||||
r2 T2
|
||||
)
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
r1, r2 = f()
|
||||
valid = true
|
||||
}
|
||||
return func() (T1, T2) {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
return r1, r2
|
||||
}
|
||||
}
|
||||
// Copyright 2009 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 sync
|
||||
|
||||
// import (
|
||||
// "sync/atomic"
|
||||
// )
|
||||
|
||||
// Once is an object that will perform exactly one action.
|
||||
//
|
||||
// A Once must not be copied after first use.
|
||||
//
|
||||
// In the terminology of the Go memory model,
|
||||
// the return from f “synchronizes before”
|
||||
// the return from any call of once.Do(f).
|
||||
type Once struct {
|
||||
// done indicates whether the action has been performed.
|
||||
// It is first in the struct because it is used in the hot path.
|
||||
// The hot path is inlined at every call site.
|
||||
// Placing done first allows more compact instructions on some architectures (amd64/386),
|
||||
// and fewer instructions (to calculate offset) on other architectures.
|
||||
done uint32
|
||||
m Mutex
|
||||
}
|
||||
|
||||
// Do calls the function f if and only if Do is being called for the
|
||||
// first time for this instance of Once. In other words, given
|
||||
//
|
||||
// var once Once
|
||||
//
|
||||
// if once.Do(f) is called multiple times, only the first call will invoke f,
|
||||
// even if f has a different value in each invocation. A new instance of
|
||||
// Once is required for each function to execute.
|
||||
//
|
||||
// Do is intended for initialization that must be run exactly once. Since f
|
||||
// is niladic, it may be necessary to use a function literal to capture the
|
||||
// arguments to a function to be invoked by Do:
|
||||
//
|
||||
// config.once.Do(func() { config.init(filename) })
|
||||
//
|
||||
// Because no call to Do returns until the one call to f returns, if f causes
|
||||
// Do to be called, it will deadlock.
|
||||
//
|
||||
// If f panics, Do considers it to have returned; future calls of Do return
|
||||
// without calling f.
|
||||
func (o *Once) Do(f func()) {
|
||||
// Note: Here is an incorrect implementation of Do:
|
||||
//
|
||||
// if atomic.CompareAndSwapUint32(&o.done, 0, 1) {
|
||||
// f()
|
||||
// }
|
||||
//
|
||||
// Do guarantees that when it returns, f has finished.
|
||||
// This implementation would not implement that guarantee:
|
||||
// given two simultaneous calls, the winner of the cas would
|
||||
// call f, and the second would return immediately, without
|
||||
// waiting for the first's call to f to complete.
|
||||
// This is why the slow path falls back to a mutex, and why
|
||||
// the atomic.StoreUint32 must be delayed until after f returns.
|
||||
|
||||
if atomic.LoadUint32(&o.done) == 0 {
|
||||
// Outlined slow-path to allow inlining of the fast-path.
|
||||
o.doSlow(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Once) doSlow(f func()) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
if o.done == 0 {
|
||||
defer atomic.StoreUint32(&o.done, 1)
|
||||
f()
|
||||
}
|
||||
}
|
||||
200
stdlib/generic/go1_21_sync_atomic.go.txt
Normal file
200
stdlib/generic/go1_21_sync_atomic.go.txt
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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{}
|
||||
71
stdlib/generic/go1_22_cmp_cmp.go.txt
Normal file
71
stdlib/generic/go1_22_cmp_cmp.go.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2023 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 cmp provides types and functions related to comparing
|
||||
// ordered values.
|
||||
package cmp
|
||||
|
||||
// Ordered is a constraint that permits any ordered type: any type
|
||||
// that supports the operators < <= >= >.
|
||||
// If future releases of Go add new ordered types,
|
||||
// this constraint will be modified to include them.
|
||||
//
|
||||
// Note that floating-point types may contain NaN ("not-a-number") values.
|
||||
// An operator such as == or < will always report false when
|
||||
// comparing a NaN value with any other value, NaN or not.
|
||||
// See the [Compare] function for a consistent way to compare NaN values.
|
||||
type Ordered interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
||||
~float32 | ~float64 |
|
||||
~string
|
||||
}
|
||||
|
||||
// Less reports whether x is less than y.
|
||||
// For floating-point types, a NaN is considered less than any non-NaN,
|
||||
// and -0.0 is not less than (is equal to) 0.0.
|
||||
func Less[T Ordered](x, y T) bool {
|
||||
return (isNaN(x) && !isNaN(y)) || x < y
|
||||
}
|
||||
|
||||
// Compare returns
|
||||
//
|
||||
// -1 if x is less than y,
|
||||
// 0 if x equals y,
|
||||
// +1 if x is greater than y.
|
||||
//
|
||||
// For floating-point types, a NaN is considered less than any non-NaN,
|
||||
// a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.
|
||||
func Compare[T Ordered](x, y T) int {
|
||||
xNaN := isNaN(x)
|
||||
yNaN := isNaN(y)
|
||||
if xNaN && yNaN {
|
||||
return 0
|
||||
}
|
||||
if xNaN || x < y {
|
||||
return -1
|
||||
}
|
||||
if yNaN || x > y {
|
||||
return +1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// isNaN reports whether x is a NaN without requiring the math package.
|
||||
// This will always return false if T is not floating-point.
|
||||
func isNaN[T Ordered](x T) bool {
|
||||
return x != x
|
||||
}
|
||||
|
||||
// Or returns the first of its arguments that is not equal to the zero value.
|
||||
// If no argument is non-zero, it returns the zero value.
|
||||
func Or[T comparable](vals ...T) T {
|
||||
var zero T
|
||||
for _, val := range vals {
|
||||
if val != zero {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return zero
|
||||
}
|
||||
41
stdlib/generic/go1_22_generic.go
Normal file
41
stdlib/generic/go1_22_generic.go
Normal file
@@ -0,0 +1,41 @@
|
||||
//go:build go1.22
|
||||
// +build go1.22
|
||||
|
||||
package generic
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed go1_22_cmp_cmp.go.txt
|
||||
var cmpSource string
|
||||
|
||||
//go:embed go1_22_maps_maps.go.txt
|
||||
var mapsSource string
|
||||
|
||||
//go:embed go1_22_slices_slices.go.txt
|
||||
var slicesSource string
|
||||
|
||||
/*
|
||||
//go:embed go1_22_slices_sort.go.txt
|
||||
var slicesSource1 string
|
||||
|
||||
//go:embed go1_22_slices_zsortanyfunc.go.txt
|
||||
var slicesSource2 string
|
||||
|
||||
//go:embed go1_22_sync_oncefunc.go.txt
|
||||
var syncSource string
|
||||
|
||||
//go:embed go1_22_sync_atomic_type.go.txt
|
||||
var syncAtomicSource string
|
||||
*/
|
||||
|
||||
// Sources contains the list of generic packages source strings.
|
||||
var Sources = [...]string{
|
||||
cmpSource,
|
||||
mapsSource,
|
||||
slicesSource,
|
||||
// FIXME(marc): support the following.
|
||||
// slicesSource1,
|
||||
// slicesSource2,
|
||||
// syncAtomicSource,
|
||||
// syncSource,
|
||||
}
|
||||
68
stdlib/generic/go1_22_maps_maps.go.txt
Normal file
68
stdlib/generic/go1_22_maps_maps.go.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2021 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 maps defines various functions useful with maps of any type.
|
||||
package maps
|
||||
|
||||
// Equal reports whether two maps contain the same key/value pairs.
|
||||
// Values are compared using ==.
|
||||
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool {
|
||||
if len(m1) != len(m2) {
|
||||
return false
|
||||
}
|
||||
for k, v1 := range m1 {
|
||||
if v2, ok := m2[k]; !ok || v1 != v2 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualFunc is like Equal, but compares values using eq.
|
||||
// Keys are still compared with ==.
|
||||
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool {
|
||||
if len(m1) != len(m2) {
|
||||
return false
|
||||
}
|
||||
for k, v1 := range m1 {
|
||||
if v2, ok := m2[k]; !ok || !eq(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// clone is implemented in the runtime package.
|
||||
func clone(m any) any {
|
||||
return m
|
||||
}
|
||||
|
||||
// Clone returns a copy of m. This is a shallow clone:
|
||||
// the new keys and values are set using ordinary assignment.
|
||||
func Clone[M ~map[K]V, K comparable, V any](m M) M {
|
||||
// Preserve nil in case it matters.
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return clone(m).(M)
|
||||
}
|
||||
|
||||
// Copy copies all key/value pairs in src adding them to dst.
|
||||
// When a key in src is already present in dst,
|
||||
// the value in dst will be overwritten by the value associated
|
||||
// with the key in src.
|
||||
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) {
|
||||
for k, v := range src {
|
||||
dst[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteFunc deletes any key/value pairs from m for which del returns true.
|
||||
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) {
|
||||
for k, v := range m {
|
||||
if del(k, v) {
|
||||
delete(m, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
518
stdlib/generic/go1_22_slices_slices.go.txt
Normal file
518
stdlib/generic/go1_22_slices_slices.go.txt
Normal file
@@ -0,0 +1,518 @@
|
||||
// Copyright 2021 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 defines various functions useful with slices of any type.
|
||||
package slices
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
// TODO(marc) fix this. "unsafe"
|
||||
)
|
||||
|
||||
// Equal reports whether two slices are equal: the same length and all
|
||||
// elements equal. If the lengths are different, Equal returns false.
|
||||
// Otherwise, the elements are compared in increasing index order, and the
|
||||
// comparison stops at the first unequal pair.
|
||||
// Floating point NaNs are not considered equal.
|
||||
func Equal[S ~[]E, E comparable](s1, s2 S) bool {
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
for i := range s1 {
|
||||
if s1[i] != s2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualFunc reports whether two slices are equal using an equality
|
||||
// function on each pair of elements. If the lengths are different,
|
||||
// EqualFunc returns false. Otherwise, the elements are compared in
|
||||
// increasing index order, and the comparison stops at the first index
|
||||
// for which eq returns false.
|
||||
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
for i, v1 := range s1 {
|
||||
v2 := s2[i]
|
||||
if !eq(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
|
||||
// of elements. The elements are compared sequentially, starting at index 0,
|
||||
// until one element is not equal to the other.
|
||||
// The result of comparing the first non-matching elements is returned.
|
||||
// If both slices are equal until one of them ends, the shorter slice is
|
||||
// considered less than the longer one.
|
||||
// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
|
||||
func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
|
||||
for i, v1 := range s1 {
|
||||
if i >= len(s2) {
|
||||
return +1
|
||||
}
|
||||
v2 := s2[i]
|
||||
if c := cmp.Compare(v1, v2); c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
if len(s1) < len(s2) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// CompareFunc is like [Compare] but uses a custom comparison function on each
|
||||
// pair of elements.
|
||||
// The result is the first non-zero result of cmp; if cmp always
|
||||
// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
|
||||
// and +1 if len(s1) > len(s2).
|
||||
func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
|
||||
for i, v1 := range s1 {
|
||||
if i >= len(s2) {
|
||||
return +1
|
||||
}
|
||||
v2 := s2[i]
|
||||
if c := cmp(v1, v2); c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
if len(s1) < len(s2) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Index returns the index of the first occurrence of v in s,
|
||||
// or -1 if not present.
|
||||
func Index[S ~[]E, E comparable](s S, v E) int {
|
||||
for i := range s {
|
||||
if v == s[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// IndexFunc returns the first index i satisfying f(s[i]),
|
||||
// or -1 if none do.
|
||||
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
|
||||
for i := range s {
|
||||
if f(s[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Contains reports whether v is present in s.
|
||||
func Contains[S ~[]E, E comparable](s S, v E) bool {
|
||||
return Index(s, v) >= 0
|
||||
}
|
||||
|
||||
// ContainsFunc reports whether at least one
|
||||
// element e of s satisfies f(e).
|
||||
func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
|
||||
return IndexFunc(s, f) >= 0
|
||||
}
|
||||
|
||||
// Insert inserts the values v... into s at index i,
|
||||
// returning the modified slice.
|
||||
// The elements at s[i:] are shifted up to make room.
|
||||
// In the returned slice r, r[i] == v[0],
|
||||
// and r[i+len(v)] == value originally at r[i].
|
||||
// Insert panics if i is out of range.
|
||||
// This function is O(len(s) + len(v)).
|
||||
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
|
||||
_ = s[i:] // bounds check
|
||||
|
||||
m := len(v)
|
||||
if m == 0 {
|
||||
return s
|
||||
}
|
||||
n := len(s)
|
||||
if i == n {
|
||||
return append(s, v...)
|
||||
}
|
||||
if n+m > cap(s) {
|
||||
// Use append rather than make so that we bump the size of
|
||||
// the slice up to the next storage class.
|
||||
// This is what Grow does but we don't call Grow because
|
||||
// that might copy the values twice.
|
||||
s2 := append(s[:i], make(S, n+m-i)...)
|
||||
copy(s2[i:], v)
|
||||
copy(s2[i+m:], s[i:])
|
||||
return s2
|
||||
}
|
||||
s = s[:n+m]
|
||||
|
||||
// before:
|
||||
// s: aaaaaaaabbbbccccccccdddd
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
// after:
|
||||
// s: aaaaaaaavvvvbbbbcccccccc
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
//
|
||||
// a are the values that don't move in s.
|
||||
// v are the values copied in from v.
|
||||
// b and c are the values from s that are shifted up in index.
|
||||
// d are the values that get overwritten, never to be seen again.
|
||||
|
||||
if !overlaps(v, s[i+m:]) {
|
||||
// Easy case - v does not overlap either the c or d regions.
|
||||
// (It might be in some of a or b, or elsewhere entirely.)
|
||||
// The data we copy up doesn't write to v at all, so just do it.
|
||||
|
||||
copy(s[i+m:], s[i:])
|
||||
|
||||
// Now we have
|
||||
// s: aaaaaaaabbbbbbbbcccccccc
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
// Note the b values are duplicated.
|
||||
|
||||
copy(s[i:], v)
|
||||
|
||||
// Now we have
|
||||
// s: aaaaaaaavvvvbbbbcccccccc
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
// That's the result we want.
|
||||
return s
|
||||
}
|
||||
|
||||
// The hard case - v overlaps c or d. We can't just shift up
|
||||
// the data because we'd move or clobber the values we're trying
|
||||
// to insert.
|
||||
// So instead, write v on top of d, then rotate.
|
||||
copy(s[n:], v)
|
||||
|
||||
// Now we have
|
||||
// s: aaaaaaaabbbbccccccccvvvv
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
|
||||
rotateRight(s[i:], m)
|
||||
|
||||
// Now we have
|
||||
// s: aaaaaaaavvvvbbbbcccccccc
|
||||
// ^ ^ ^ ^
|
||||
// i i+m n n+m
|
||||
// That's the result we want.
|
||||
return s
|
||||
}
|
||||
|
||||
// Delete removes the elements s[i:j] from s, returning the modified slice.
|
||||
// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
|
||||
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
|
||||
// make a single call deleting them all together than to delete one at a time.
|
||||
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
|
||||
func Delete[S ~[]E, E any](s S, i, j int) S {
|
||||
_ = s[i:j:len(s)] // bounds check
|
||||
|
||||
if i == j {
|
||||
return s
|
||||
}
|
||||
|
||||
oldlen := len(s)
|
||||
s = append(s[:i], s[j:]...)
|
||||
clear(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
|
||||
return s
|
||||
}
|
||||
|
||||
// DeleteFunc removes any elements from s for which del returns true,
|
||||
// returning the modified slice.
|
||||
// DeleteFunc zeroes the elements between the new length and the original length.
|
||||
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
|
||||
i := IndexFunc(s, del)
|
||||
if i == -1 {
|
||||
return s
|
||||
}
|
||||
// Don't start copying elements until we find one to delete.
|
||||
for j := i + 1; j < len(s); j++ {
|
||||
if v := s[j]; !del(v) {
|
||||
s[i] = v
|
||||
i++
|
||||
}
|
||||
}
|
||||
clear(s[i:]) // zero/nil out the obsolete elements, for GC
|
||||
return s[:i]
|
||||
}
|
||||
|
||||
// Replace replaces the elements s[i:j] by the given v, and returns the
|
||||
// modified slice.
|
||||
// Replace panics if j > len(s) or s[i:j] is not a valid slice of s.
|
||||
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
|
||||
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
|
||||
_ = s[i:j] // bounds check
|
||||
|
||||
if i == j {
|
||||
return Insert(s, i, v...)
|
||||
}
|
||||
if j == len(s) {
|
||||
return append(s[:i], v...)
|
||||
}
|
||||
|
||||
tot := len(s[:i]) + len(v) + len(s[j:])
|
||||
if tot > cap(s) {
|
||||
// Too big to fit, allocate and copy over.
|
||||
s2 := append(s[:i], make(S, tot-i)...) // See Insert
|
||||
copy(s2[i:], v)
|
||||
copy(s2[i+len(v):], s[j:])
|
||||
return s2
|
||||
}
|
||||
|
||||
r := s[:tot]
|
||||
|
||||
if i+len(v) <= j {
|
||||
// Easy, as v fits in the deleted portion.
|
||||
copy(r[i:], v)
|
||||
copy(r[i+len(v):], s[j:])
|
||||
clear(s[tot:]) // zero/nil out the obsolete elements, for GC
|
||||
return r
|
||||
}
|
||||
|
||||
// We are expanding (v is bigger than j-i).
|
||||
// The situation is something like this:
|
||||
// (example has i=4,j=8,len(s)=16,len(v)=6)
|
||||
// s: aaaaxxxxbbbbbbbbyy
|
||||
// ^ ^ ^ ^
|
||||
// i j len(s) tot
|
||||
// a: prefix of s
|
||||
// x: deleted range
|
||||
// b: more of s
|
||||
// y: area to expand into
|
||||
|
||||
if !overlaps(r[i+len(v):], v) {
|
||||
// Easy, as v is not clobbered by the first copy.
|
||||
copy(r[i+len(v):], s[j:])
|
||||
copy(r[i:], v)
|
||||
return r
|
||||
}
|
||||
|
||||
// This is a situation where we don't have a single place to which
|
||||
// we can copy v. Parts of it need to go to two different places.
|
||||
// We want to copy the prefix of v into y and the suffix into x, then
|
||||
// rotate |y| spots to the right.
|
||||
//
|
||||
// v[2:] v[:2]
|
||||
// | |
|
||||
// s: aaaavvvvbbbbbbbbvv
|
||||
// ^ ^ ^ ^
|
||||
// i j len(s) tot
|
||||
//
|
||||
// If either of those two destinations don't alias v, then we're good.
|
||||
y := len(v) - (j - i) // length of y portion
|
||||
|
||||
if !overlaps(r[i:j], v) {
|
||||
copy(r[i:j], v[y:])
|
||||
copy(r[len(s):], v[:y])
|
||||
rotateRight(r[i:], y)
|
||||
return r
|
||||
}
|
||||
if !overlaps(r[len(s):], v) {
|
||||
copy(r[len(s):], v[:y])
|
||||
copy(r[i:j], v[y:])
|
||||
rotateRight(r[i:], y)
|
||||
return r
|
||||
}
|
||||
|
||||
// Now we know that v overlaps both x and y.
|
||||
// That means that the entirety of b is *inside* v.
|
||||
// So we don't need to preserve b at all; instead we
|
||||
// can copy v first, then copy the b part of v out of
|
||||
// v to the right destination.
|
||||
k := startIdx(v, s[j:])
|
||||
copy(r[i:], v)
|
||||
copy(r[i+len(v):], r[i+k:])
|
||||
return r
|
||||
}
|
||||
|
||||
// Clone returns a copy of the slice.
|
||||
// The elements are copied using assignment, so this is a shallow clone.
|
||||
func Clone[S ~[]E, E any](s S) S {
|
||||
// The s[:0:0] preserves nil in case it matters.
|
||||
return append(s[:0:0], s...)
|
||||
}
|
||||
|
||||
// Compact replaces consecutive runs of equal elements with a single copy.
|
||||
// This is like the uniq command found on Unix.
|
||||
// Compact modifies the contents of the slice s and returns the modified slice,
|
||||
// which may have a smaller length.
|
||||
// Compact zeroes the elements between the new length and the original length.
|
||||
func Compact[S ~[]E, E comparable](s S) S {
|
||||
if len(s) < 2 {
|
||||
return s
|
||||
}
|
||||
i := 1
|
||||
for k := 1; k < len(s); k++ {
|
||||
if s[k] != s[k-1] {
|
||||
if i != k {
|
||||
s[i] = s[k]
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
clear(s[i:]) // zero/nil out the obsolete elements, for GC
|
||||
return s[:i]
|
||||
}
|
||||
|
||||
// CompactFunc is like [Compact] but uses an equality function to compare elements.
|
||||
// For runs of elements that compare equal, CompactFunc keeps the first one.
|
||||
// CompactFunc zeroes the elements between the new length and the original length.
|
||||
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
|
||||
if len(s) < 2 {
|
||||
return s
|
||||
}
|
||||
i := 1
|
||||
for k := 1; k < len(s); k++ {
|
||||
if !eq(s[k], s[k-1]) {
|
||||
if i != k {
|
||||
s[i] = s[k]
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
clear(s[i:]) // zero/nil out the obsolete elements, for GC
|
||||
return s[:i]
|
||||
}
|
||||
|
||||
// Grow increases the slice's capacity, if necessary, to guarantee space for
|
||||
// another n elements. After Grow(n), at least n elements can be appended
|
||||
// to the slice without another allocation. If n is negative or too large to
|
||||
// allocate the memory, Grow panics.
|
||||
func Grow[S ~[]E, E any](s S, n int) S {
|
||||
if n < 0 {
|
||||
panic("cannot be negative")
|
||||
}
|
||||
if n -= cap(s) - len(s); n > 0 {
|
||||
s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
|
||||
func Clip[S ~[]E, E any](s S) S {
|
||||
return s[:len(s):len(s)]
|
||||
}
|
||||
|
||||
// Rotation algorithm explanation:
|
||||
//
|
||||
// rotate left by 2
|
||||
// start with
|
||||
// 0123456789
|
||||
// split up like this
|
||||
// 01 234567 89
|
||||
// swap first 2 and last 2
|
||||
// 89 234567 01
|
||||
// join first parts
|
||||
// 89234567 01
|
||||
// recursively rotate first left part by 2
|
||||
// 23456789 01
|
||||
// join at the end
|
||||
// 2345678901
|
||||
//
|
||||
// rotate left by 8
|
||||
// start with
|
||||
// 0123456789
|
||||
// split up like this
|
||||
// 01 234567 89
|
||||
// swap first 2 and last 2
|
||||
// 89 234567 01
|
||||
// join last parts
|
||||
// 89 23456701
|
||||
// recursively rotate second part left by 6
|
||||
// 89 01234567
|
||||
// join at the end
|
||||
// 8901234567
|
||||
|
||||
// TODO: There are other rotate algorithms.
|
||||
// This algorithm has the desirable property that it moves each element exactly twice.
|
||||
// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes.
|
||||
// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
|
||||
|
||||
// rotateLeft rotates b left by n spaces.
|
||||
// s_final[i] = s_orig[i+r], wrapping around.
|
||||
func rotateLeft[E any](s []E, r int) {
|
||||
for r != 0 && r != len(s) {
|
||||
if r*2 <= len(s) {
|
||||
swap(s[:r], s[len(s)-r:])
|
||||
s = s[:len(s)-r]
|
||||
} else {
|
||||
swap(s[:len(s)-r], s[r:])
|
||||
s, r = s[len(s)-r:], r*2-len(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
func rotateRight[E any](s []E, r int) {
|
||||
rotateLeft(s, len(s)-r)
|
||||
}
|
||||
|
||||
// swap swaps the contents of x and y. x and y must be equal length and disjoint.
|
||||
func swap[E any](x, y []E) {
|
||||
for i := 0; i < len(x); i++ {
|
||||
x[i], y[i] = y[i], x[i]
|
||||
}
|
||||
}
|
||||
|
||||
// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
|
||||
func overlaps[E any](a, b []E) bool {
|
||||
return false
|
||||
/* TODO(marc): restore the following
|
||||
if len(a) == 0 || len(b) == 0 {
|
||||
return false
|
||||
}
|
||||
elemSize := unsafe.Sizeof(a[0])
|
||||
if elemSize == 0 {
|
||||
return false
|
||||
}
|
||||
// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
|
||||
// Also see crypto/internal/alias/alias.go:AnyOverlap
|
||||
return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
|
||||
uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
|
||||
*/
|
||||
}
|
||||
|
||||
// startIdx returns the index in haystack where the needle starts.
|
||||
// prerequisite: the needle must be aliased entirely inside the haystack.
|
||||
func startIdx[E any](haystack, needle []E) int {
|
||||
p := &needle[0]
|
||||
for i := range haystack {
|
||||
if p == &haystack[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
// TODO: what if the overlap is by a non-integral number of Es?
|
||||
panic("needle not found")
|
||||
}
|
||||
|
||||
// Reverse reverses the elements of the slice in place.
|
||||
func Reverse[S ~[]E, E any](s S) {
|
||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Concat returns a new slice concatenating the passed in slices.
|
||||
func Concat[S ~[]E, E any](slices ...S) S {
|
||||
size := 0
|
||||
for _, s := range slices {
|
||||
size += len(s)
|
||||
if size < 0 {
|
||||
panic("len out of range")
|
||||
}
|
||||
}
|
||||
newslice := Grow[S](nil, size)
|
||||
for _, s := range slices {
|
||||
newslice = append(newslice, s...)
|
||||
}
|
||||
return newslice
|
||||
}
|
||||
194
stdlib/generic/go1_22_slices_sort.go.txt
Normal file
194
stdlib/generic/go1_22_slices_sort.go.txt
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -generic
|
||||
|
||||
package slices
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// Sort sorts a slice of any ordered type in ascending order.
|
||||
// When sorting floating-point numbers, NaNs are ordered before other values.
|
||||
func Sort[S ~[]E, E cmp.Ordered](x S) {
|
||||
n := len(x)
|
||||
pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
|
||||
}
|
||||
|
||||
// SortFunc sorts the slice x in ascending order as determined by the cmp
|
||||
// function. This sort is not guaranteed to be stable.
|
||||
// cmp(a, b) should return a negative number when a < b, a positive number when
|
||||
// a > b and zero when a == b.
|
||||
//
|
||||
// SortFunc requires that cmp is a strict weak ordering.
|
||||
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
|
||||
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
|
||||
n := len(x)
|
||||
pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
|
||||
}
|
||||
|
||||
// SortStableFunc sorts the slice x while keeping the original order of equal
|
||||
// elements, using cmp to compare elements in the same way as [SortFunc].
|
||||
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
|
||||
stableCmpFunc(x, len(x), cmp)
|
||||
}
|
||||
|
||||
// IsSorted reports whether x is sorted in ascending order.
|
||||
func IsSorted[S ~[]E, E cmp.Ordered](x S) bool {
|
||||
for i := len(x) - 1; i > 0; i-- {
|
||||
if cmp.Less(x[i], x[i-1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
|
||||
// comparison function as defined by [SortFunc].
|
||||
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
|
||||
for i := len(x) - 1; i > 0; i-- {
|
||||
if cmp(x[i], x[i-1]) < 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Min returns the minimal value in x. It panics if x is empty.
|
||||
// For floating-point numbers, Min propagates NaNs (any NaN value in x
|
||||
// forces the output to be NaN).
|
||||
func Min[S ~[]E, E cmp.Ordered](x S) E {
|
||||
if len(x) < 1 {
|
||||
panic("slices.Min: empty list")
|
||||
}
|
||||
m := x[0]
|
||||
for i := 1; i < len(x); i++ {
|
||||
m = min(m, x[i])
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// MinFunc returns the minimal value in x, using cmp to compare elements.
|
||||
// It panics if x is empty. If there is more than one minimal element
|
||||
// according to the cmp function, MinFunc returns the first one.
|
||||
func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
|
||||
if len(x) < 1 {
|
||||
panic("slices.MinFunc: empty list")
|
||||
}
|
||||
m := x[0]
|
||||
for i := 1; i < len(x); i++ {
|
||||
if cmp(x[i], m) < 0 {
|
||||
m = x[i]
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Max returns the maximal value in x. It panics if x is empty.
|
||||
// For floating-point E, Max propagates NaNs (any NaN value in x
|
||||
// forces the output to be NaN).
|
||||
func Max[S ~[]E, E cmp.Ordered](x S) E {
|
||||
if len(x) < 1 {
|
||||
panic("slices.Max: empty list")
|
||||
}
|
||||
m := x[0]
|
||||
for i := 1; i < len(x); i++ {
|
||||
m = max(m, x[i])
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// MaxFunc returns the maximal value in x, using cmp to compare elements.
|
||||
// It panics if x is empty. If there is more than one maximal element
|
||||
// according to the cmp function, MaxFunc returns the first one.
|
||||
func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
|
||||
if len(x) < 1 {
|
||||
panic("slices.MaxFunc: empty list")
|
||||
}
|
||||
m := x[0]
|
||||
for i := 1; i < len(x); i++ {
|
||||
if cmp(x[i], m) > 0 {
|
||||
m = x[i]
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// BinarySearch searches for target in a sorted slice and returns the position
|
||||
// where target is found, or the position where target would appear in the
|
||||
// sort order; it also returns a bool saying whether the target is really found
|
||||
// in the slice. The slice must be sorted in increasing order.
|
||||
func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) {
|
||||
// Inlining is faster than calling BinarySearchFunc with a lambda.
|
||||
n := len(x)
|
||||
// Define x[-1] < target and x[n] >= target.
|
||||
// Invariant: x[i-1] < target, x[j] >= target.
|
||||
i, j := 0, n
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
||||
// i ≤ h < j
|
||||
if cmp.Less(x[h], target) {
|
||||
i = h + 1 // preserves x[i-1] < target
|
||||
} else {
|
||||
j = h // preserves x[j] >= target
|
||||
}
|
||||
}
|
||||
// i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i.
|
||||
return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
|
||||
}
|
||||
|
||||
// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
|
||||
// function. The slice must be sorted in increasing order, where "increasing"
|
||||
// is defined by cmp. cmp should return 0 if the slice element matches
|
||||
// the target, a negative number if the slice element precedes the target,
|
||||
// or a positive number if the slice element follows the target.
|
||||
// cmp must implement the same ordering as the slice, such that if
|
||||
// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
|
||||
func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
|
||||
n := len(x)
|
||||
// Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 .
|
||||
// Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0.
|
||||
i, j := 0, n
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
||||
// i ≤ h < j
|
||||
if cmp(x[h], target) < 0 {
|
||||
i = h + 1 // preserves cmp(x[i - 1], target) < 0
|
||||
} else {
|
||||
j = h // preserves cmp(x[j], target) >= 0
|
||||
}
|
||||
}
|
||||
// i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i.
|
||||
return i, i < n && cmp(x[i], target) == 0
|
||||
}
|
||||
|
||||
type sortedHint int // hint for pdqsort when choosing the pivot
|
||||
|
||||
const (
|
||||
unknownHint sortedHint = iota
|
||||
increasingHint
|
||||
decreasingHint
|
||||
)
|
||||
|
||||
// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
|
||||
type xorshift uint64
|
||||
|
||||
func (r *xorshift) Next() uint64 {
|
||||
*r ^= *r << 13
|
||||
*r ^= *r >> 17
|
||||
*r ^= *r << 5
|
||||
return uint64(*r)
|
||||
}
|
||||
|
||||
func nextPowerOfTwo(length int) uint {
|
||||
return 1 << bits.Len(uint(length))
|
||||
}
|
||||
|
||||
// isNaN reports whether x is a NaN without requiring the math package.
|
||||
// This will always return false if T is not floating-point.
|
||||
func isNaN[T cmp.Ordered](x T) bool {
|
||||
return x != x
|
||||
}
|
||||
479
stdlib/generic/go1_22_slices_zsortanyfunc.go.txt
Normal file
479
stdlib/generic/go1_22_slices_zsortanyfunc.go.txt
Normal file
@@ -0,0 +1,479 @@
|
||||
// Code generated by gen_sort_variants.go; DO NOT EDIT.
|
||||
|
||||
// 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 slices
|
||||
|
||||
// insertionSortCmpFunc sorts data[a:b] using insertion sort.
|
||||
func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
||||
for i := a + 1; i < b; i++ {
|
||||
for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
|
||||
data[j], data[j-1] = data[j-1], data[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// siftDownCmpFunc implements the heap property on data[lo:hi].
|
||||
// first is an offset into the array where the root of the heap lies.
|
||||
func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
|
||||
child++
|
||||
}
|
||||
if !(cmp(data[first+root], data[first+child]) < 0) {
|
||||
return
|
||||
}
|
||||
data[first+root], data[first+child] = data[first+child], data[first+root]
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
||||
first := a
|
||||
lo := 0
|
||||
hi := b - a
|
||||
|
||||
// Build heap with greatest element at top.
|
||||
for i := (hi - 1) / 2; i >= 0; i-- {
|
||||
siftDownCmpFunc(data, i, hi, first, cmp)
|
||||
}
|
||||
|
||||
// Pop elements, largest first, into end of data.
|
||||
for i := hi - 1; i >= 0; i-- {
|
||||
data[first], data[first+i] = data[first+i], data[first]
|
||||
siftDownCmpFunc(data, lo, i, first, cmp)
|
||||
}
|
||||
}
|
||||
|
||||
// pdqsortCmpFunc sorts data[a:b].
|
||||
// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
|
||||
// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
|
||||
// C++ implementation: https://github.com/orlp/pdqsort
|
||||
// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
|
||||
// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
|
||||
func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
|
||||
const maxInsertion = 12
|
||||
|
||||
var (
|
||||
wasBalanced = true // whether the last partitioning was reasonably balanced
|
||||
wasPartitioned = true // whether the slice was already partitioned
|
||||
)
|
||||
|
||||
for {
|
||||
length := b - a
|
||||
|
||||
if length <= maxInsertion {
|
||||
insertionSortCmpFunc(data, a, b, cmp)
|
||||
return
|
||||
}
|
||||
|
||||
// Fall back to heapsort if too many bad choices were made.
|
||||
if limit == 0 {
|
||||
heapSortCmpFunc(data, a, b, cmp)
|
||||
return
|
||||
}
|
||||
|
||||
// If the last partitioning was imbalanced, we need to breaking patterns.
|
||||
if !wasBalanced {
|
||||
breakPatternsCmpFunc(data, a, b, cmp)
|
||||
limit--
|
||||
}
|
||||
|
||||
pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
|
||||
if hint == decreasingHint {
|
||||
reverseRangeCmpFunc(data, a, b, cmp)
|
||||
// The chosen pivot was pivot-a elements after the start of the array.
|
||||
// After reversing it is pivot-a elements before the end of the array.
|
||||
// The idea came from Rust's implementation.
|
||||
pivot = (b - 1) - (pivot - a)
|
||||
hint = increasingHint
|
||||
}
|
||||
|
||||
// The slice is likely already sorted.
|
||||
if wasBalanced && wasPartitioned && hint == increasingHint {
|
||||
if partialInsertionSortCmpFunc(data, a, b, cmp) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Probably the slice contains many duplicate elements, partition the slice into
|
||||
// elements equal to and elements greater than the pivot.
|
||||
if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
|
||||
mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
|
||||
a = mid
|
||||
continue
|
||||
}
|
||||
|
||||
mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
|
||||
wasPartitioned = alreadyPartitioned
|
||||
|
||||
leftLen, rightLen := mid-a, b-mid
|
||||
balanceThreshold := length / 8
|
||||
if leftLen < rightLen {
|
||||
wasBalanced = leftLen >= balanceThreshold
|
||||
pdqsortCmpFunc(data, a, mid, limit, cmp)
|
||||
a = mid + 1
|
||||
} else {
|
||||
wasBalanced = rightLen >= balanceThreshold
|
||||
pdqsortCmpFunc(data, mid+1, b, limit, cmp)
|
||||
b = mid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// partitionCmpFunc does one quicksort partition.
|
||||
// Let p = data[pivot]
|
||||
// Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot.
|
||||
// On return, data[newpivot] = p
|
||||
func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) {
|
||||
data[a], data[pivot] = data[pivot], data[a]
|
||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
||||
|
||||
for i <= j && (cmp(data[i], data[a]) < 0) {
|
||||
i++
|
||||
}
|
||||
for i <= j && !(cmp(data[j], data[a]) < 0) {
|
||||
j--
|
||||
}
|
||||
if i > j {
|
||||
data[j], data[a] = data[a], data[j]
|
||||
return j, true
|
||||
}
|
||||
data[i], data[j] = data[j], data[i]
|
||||
i++
|
||||
j--
|
||||
|
||||
for {
|
||||
for i <= j && (cmp(data[i], data[a]) < 0) {
|
||||
i++
|
||||
}
|
||||
for i <= j && !(cmp(data[j], data[a]) < 0) {
|
||||
j--
|
||||
}
|
||||
if i > j {
|
||||
break
|
||||
}
|
||||
data[i], data[j] = data[j], data[i]
|
||||
i++
|
||||
j--
|
||||
}
|
||||
data[j], data[a] = data[a], data[j]
|
||||
return j, false
|
||||
}
|
||||
|
||||
// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot].
|
||||
// It assumed that data[a:b] does not contain elements smaller than the data[pivot].
|
||||
func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) {
|
||||
data[a], data[pivot] = data[pivot], data[a]
|
||||
i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
|
||||
|
||||
for {
|
||||
for i <= j && !(cmp(data[a], data[i]) < 0) {
|
||||
i++
|
||||
}
|
||||
for i <= j && (cmp(data[a], data[j]) < 0) {
|
||||
j--
|
||||
}
|
||||
if i > j {
|
||||
break
|
||||
}
|
||||
data[i], data[j] = data[j], data[i]
|
||||
i++
|
||||
j--
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end.
|
||||
func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool {
|
||||
const (
|
||||
maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted
|
||||
shortestShifting = 50 // don't shift any elements on short arrays
|
||||
)
|
||||
i := a + 1
|
||||
for j := 0; j < maxSteps; j++ {
|
||||
for i < b && !(cmp(data[i], data[i-1]) < 0) {
|
||||
i++
|
||||
}
|
||||
|
||||
if i == b {
|
||||
return true
|
||||
}
|
||||
|
||||
if b-a < shortestShifting {
|
||||
return false
|
||||
}
|
||||
|
||||
data[i], data[i-1] = data[i-1], data[i]
|
||||
|
||||
// Shift the smaller one to the left.
|
||||
if i-a >= 2 {
|
||||
for j := i - 1; j >= 1; j-- {
|
||||
if !(cmp(data[j], data[j-1]) < 0) {
|
||||
break
|
||||
}
|
||||
data[j], data[j-1] = data[j-1], data[j]
|
||||
}
|
||||
}
|
||||
// Shift the greater one to the right.
|
||||
if b-i >= 2 {
|
||||
for j := i + 1; j < b; j++ {
|
||||
if !(cmp(data[j], data[j-1]) < 0) {
|
||||
break
|
||||
}
|
||||
data[j], data[j-1] = data[j-1], data[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns
|
||||
// that might cause imbalanced partitions in quicksort.
|
||||
func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
||||
length := b - a
|
||||
if length >= 8 {
|
||||
random := xorshift(length)
|
||||
modulus := nextPowerOfTwo(length)
|
||||
|
||||
for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ {
|
||||
other := int(uint(random.Next()) & (modulus - 1))
|
||||
if other >= length {
|
||||
other -= length
|
||||
}
|
||||
data[idx], data[a+other] = data[a+other], data[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// choosePivotCmpFunc chooses a pivot in data[a:b].
|
||||
//
|
||||
// [0,8): chooses a static pivot.
|
||||
// [8,shortestNinther): uses the simple median-of-three method.
|
||||
// [shortestNinther,∞): uses the Tukey ninther method.
|
||||
func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) {
|
||||
const (
|
||||
shortestNinther = 50
|
||||
maxSwaps = 4 * 3
|
||||
)
|
||||
|
||||
l := b - a
|
||||
|
||||
var (
|
||||
swaps int
|
||||
i = a + l/4*1
|
||||
j = a + l/4*2
|
||||
k = a + l/4*3
|
||||
)
|
||||
|
||||
if l >= 8 {
|
||||
if l >= shortestNinther {
|
||||
// Tukey ninther method, the idea came from Rust's implementation.
|
||||
i = medianAdjacentCmpFunc(data, i, &swaps, cmp)
|
||||
j = medianAdjacentCmpFunc(data, j, &swaps, cmp)
|
||||
k = medianAdjacentCmpFunc(data, k, &swaps, cmp)
|
||||
}
|
||||
// Find the median among i, j, k and stores it into j.
|
||||
j = medianCmpFunc(data, i, j, k, &swaps, cmp)
|
||||
}
|
||||
|
||||
switch swaps {
|
||||
case 0:
|
||||
return j, increasingHint
|
||||
case maxSwaps:
|
||||
return j, decreasingHint
|
||||
default:
|
||||
return j, unknownHint
|
||||
}
|
||||
}
|
||||
|
||||
// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a.
|
||||
func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) {
|
||||
if cmp(data[b], data[a]) < 0 {
|
||||
*swaps++
|
||||
return b, a
|
||||
}
|
||||
return a, b
|
||||
}
|
||||
|
||||
// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c.
|
||||
func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int {
|
||||
a, b = order2CmpFunc(data, a, b, swaps, cmp)
|
||||
b, c = order2CmpFunc(data, b, c, swaps, cmp)
|
||||
a, b = order2CmpFunc(data, a, b, swaps, cmp)
|
||||
return b
|
||||
}
|
||||
|
||||
// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a.
|
||||
func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int {
|
||||
return medianCmpFunc(data, a-1, a, a+1, swaps, cmp)
|
||||
}
|
||||
|
||||
func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
|
||||
i := a
|
||||
j := b - 1
|
||||
for i < j {
|
||||
data[i], data[j] = data[j], data[i]
|
||||
i++
|
||||
j--
|
||||
}
|
||||
}
|
||||
|
||||
func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) {
|
||||
for i := 0; i < n; i++ {
|
||||
data[a+i], data[b+i] = data[b+i], data[a+i]
|
||||
}
|
||||
}
|
||||
|
||||
func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) {
|
||||
blockSize := 20 // must be > 0
|
||||
a, b := 0, blockSize
|
||||
for b <= n {
|
||||
insertionSortCmpFunc(data, a, b, cmp)
|
||||
a = b
|
||||
b += blockSize
|
||||
}
|
||||
insertionSortCmpFunc(data, a, n, cmp)
|
||||
|
||||
for blockSize < n {
|
||||
a, b = 0, 2*blockSize
|
||||
for b <= n {
|
||||
symMergeCmpFunc(data, a, a+blockSize, b, cmp)
|
||||
a = b
|
||||
b += 2 * blockSize
|
||||
}
|
||||
if m := a + blockSize; m < n {
|
||||
symMergeCmpFunc(data, a, m, n, cmp)
|
||||
}
|
||||
blockSize *= 2
|
||||
}
|
||||
}
|
||||
|
||||
// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using
|
||||
// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
|
||||
// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
|
||||
// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
|
||||
// Computer Science, pages 714-723. Springer, 2004.
|
||||
//
|
||||
// Let M = m-a and N = b-n. Wolog M < N.
|
||||
// The recursion depth is bound by ceil(log(N+M)).
|
||||
// The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
|
||||
// The algorithm needs O((M+N)*log(M)) calls to data.Swap.
|
||||
//
|
||||
// The paper gives O((M+N)*log(M)) as the number of assignments assuming a
|
||||
// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
|
||||
// in the paper carries through for Swap operations, especially as the block
|
||||
// swapping rotate uses only O(M+N) Swaps.
|
||||
//
|
||||
// symMerge assumes non-degenerate arguments: a < m && m < b.
|
||||
// Having the caller check this condition eliminates many leaf recursion calls,
|
||||
// which improves performance.
|
||||
func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
|
||||
// Avoid unnecessary recursions of symMerge
|
||||
// by direct insertion of data[a] into data[m:b]
|
||||
// if data[a:m] only contains one element.
|
||||
if m-a == 1 {
|
||||
// Use binary search to find the lowest index i
|
||||
// such that data[i] >= data[a] for m <= i < b.
|
||||
// Exit the search loop with i == b in case no such index exists.
|
||||
i := m
|
||||
j := b
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1)
|
||||
if cmp(data[h], data[a]) < 0 {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
// Swap values until data[a] reaches the position before i.
|
||||
for k := a; k < i-1; k++ {
|
||||
data[k], data[k+1] = data[k+1], data[k]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Avoid unnecessary recursions of symMerge
|
||||
// by direct insertion of data[m] into data[a:m]
|
||||
// if data[m:b] only contains one element.
|
||||
if b-m == 1 {
|
||||
// Use binary search to find the lowest index i
|
||||
// such that data[i] > data[m] for a <= i < m.
|
||||
// Exit the search loop with i == m in case no such index exists.
|
||||
i := a
|
||||
j := m
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1)
|
||||
if !(cmp(data[m], data[h]) < 0) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
// Swap values until data[m] reaches the position i.
|
||||
for k := m; k > i; k-- {
|
||||
data[k], data[k-1] = data[k-1], data[k]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
mid := int(uint(a+b) >> 1)
|
||||
n := mid + m
|
||||
var start, r int
|
||||
if m > mid {
|
||||
start = n - b
|
||||
r = mid
|
||||
} else {
|
||||
start = a
|
||||
r = m
|
||||
}
|
||||
p := n - 1
|
||||
|
||||
for start < r {
|
||||
c := int(uint(start+r) >> 1)
|
||||
if !(cmp(data[p-c], data[c]) < 0) {
|
||||
start = c + 1
|
||||
} else {
|
||||
r = c
|
||||
}
|
||||
}
|
||||
|
||||
end := n - start
|
||||
if start < m && m < end {
|
||||
rotateCmpFunc(data, start, m, end, cmp)
|
||||
}
|
||||
if a < start && start < mid {
|
||||
symMergeCmpFunc(data, a, start, mid, cmp)
|
||||
}
|
||||
if mid < end && end < b {
|
||||
symMergeCmpFunc(data, mid, end, b, cmp)
|
||||
}
|
||||
}
|
||||
|
||||
// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
|
||||
// Data of the form 'x u v y' is changed to 'x v u y'.
|
||||
// rotate performs at most b-a many calls to data.Swap,
|
||||
// and it assumes non-degenerate arguments: a < m && m < b.
|
||||
func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) {
|
||||
i := m - a
|
||||
j := b - m
|
||||
|
||||
for i != j {
|
||||
if i > j {
|
||||
swapRangeCmpFunc(data, m-i, m, j, cmp)
|
||||
i -= j
|
||||
} else {
|
||||
swapRangeCmpFunc(data, m-i, m+j-i, i, cmp)
|
||||
j -= i
|
||||
}
|
||||
}
|
||||
// i == j
|
||||
swapRangeCmpFunc(data, m-i, m, i, cmp)
|
||||
}
|
||||
200
stdlib/generic/go1_22_sync_atomic_type.go.txt
Normal file
200
stdlib/generic/go1_22_sync_atomic_type.go.txt
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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{}
|
||||
100
stdlib/generic/go1_22_sync_oncefunc.go.txt
Normal file
100
stdlib/generic/go1_22_sync_oncefunc.go.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
// 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 sync
|
||||
|
||||
// OnceFunc returns a function that invokes f only once. The returned function
|
||||
// may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceFunc(f func()) func() {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
)
|
||||
// Construct the inner closure just once to reduce costs on the fast path.
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
// Re-panic immediately so on the first call the user gets a
|
||||
// complete stack trace into f.
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
f = nil // Do not keep f alive after invoking it.
|
||||
valid = true // Set only if f does not panic.
|
||||
}
|
||||
return func() {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OnceValue returns a function that invokes f only once and returns the value
|
||||
// returned by f. The returned function may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceValue[T any](f func() T) func() T {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
result T
|
||||
)
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
result = f()
|
||||
f = nil
|
||||
valid = true
|
||||
}
|
||||
return func() T {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// OnceValues returns a function that invokes f only once and returns the values
|
||||
// returned by f. The returned function may be called concurrently.
|
||||
//
|
||||
// If f panics, the returned function will panic with the same value on every call.
|
||||
func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
|
||||
var (
|
||||
once Once
|
||||
valid bool
|
||||
p any
|
||||
r1 T1
|
||||
r2 T2
|
||||
)
|
||||
g := func() {
|
||||
defer func() {
|
||||
p = recover()
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
r1, r2 = f()
|
||||
f = nil
|
||||
valid = true
|
||||
}
|
||||
return func() (T1, T2) {
|
||||
once.Do(g)
|
||||
if !valid {
|
||||
panic(p)
|
||||
}
|
||||
return r1, r2
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Code generated by 'yaegi extract context'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["context/context"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"Background": reflect.ValueOf(context.Background),
|
||||
"Canceled": reflect.ValueOf(&context.Canceled).Elem(),
|
||||
"DeadlineExceeded": reflect.ValueOf(&context.DeadlineExceeded).Elem(),
|
||||
"TODO": reflect.ValueOf(context.TODO),
|
||||
"WithCancel": reflect.ValueOf(context.WithCancel),
|
||||
"WithDeadline": reflect.ValueOf(context.WithDeadline),
|
||||
"WithTimeout": reflect.ValueOf(context.WithTimeout),
|
||||
"WithValue": reflect.ValueOf(context.WithValue),
|
||||
|
||||
// type definitions
|
||||
"CancelFunc": reflect.ValueOf((*context.CancelFunc)(nil)),
|
||||
"Context": reflect.ValueOf((*context.Context)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_Context": reflect.ValueOf((*_context_Context)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _context_Context is an interface wrapper for Context type
|
||||
type _context_Context struct {
|
||||
IValue interface{}
|
||||
WDeadline func() (deadline time.Time, ok bool)
|
||||
WDone func() <-chan struct{}
|
||||
WErr func() error
|
||||
WValue func(key any) any
|
||||
}
|
||||
|
||||
func (W _context_Context) Deadline() (deadline time.Time, ok bool) {
|
||||
return W.WDeadline()
|
||||
}
|
||||
func (W _context_Context) Done() <-chan struct{} {
|
||||
return W.WDone()
|
||||
}
|
||||
func (W _context_Context) Err() error {
|
||||
return W.WErr()
|
||||
}
|
||||
func (W _context_Context) Value(key any) any {
|
||||
return W.WValue(key)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Code generated by 'yaegi extract crypto/ed25519'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/ed25519/ed25519"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"GenerateKey": reflect.ValueOf(ed25519.GenerateKey),
|
||||
"NewKeyFromSeed": reflect.ValueOf(ed25519.NewKeyFromSeed),
|
||||
"PrivateKeySize": reflect.ValueOf(constant.MakeFromLiteral("64", token.INT, 0)),
|
||||
"PublicKeySize": reflect.ValueOf(constant.MakeFromLiteral("32", token.INT, 0)),
|
||||
"SeedSize": reflect.ValueOf(constant.MakeFromLiteral("32", token.INT, 0)),
|
||||
"Sign": reflect.ValueOf(ed25519.Sign),
|
||||
"SignatureSize": reflect.ValueOf(constant.MakeFromLiteral("64", token.INT, 0)),
|
||||
"Verify": reflect.ValueOf(ed25519.Verify),
|
||||
|
||||
// type definitions
|
||||
"PrivateKey": reflect.ValueOf((*ed25519.PrivateKey)(nil)),
|
||||
"PublicKey": reflect.ValueOf((*ed25519.PublicKey)(nil)),
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Code generated by 'yaegi extract crypto/tls'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/tls/tls"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"CipherSuiteName": reflect.ValueOf(tls.CipherSuiteName),
|
||||
"CipherSuites": reflect.ValueOf(tls.CipherSuites),
|
||||
"Client": reflect.ValueOf(tls.Client),
|
||||
"CurveP256": reflect.ValueOf(tls.CurveP256),
|
||||
"CurveP384": reflect.ValueOf(tls.CurveP384),
|
||||
"CurveP521": reflect.ValueOf(tls.CurveP521),
|
||||
"Dial": reflect.ValueOf(tls.Dial),
|
||||
"DialWithDialer": reflect.ValueOf(tls.DialWithDialer),
|
||||
"ECDSAWithP256AndSHA256": reflect.ValueOf(tls.ECDSAWithP256AndSHA256),
|
||||
"ECDSAWithP384AndSHA384": reflect.ValueOf(tls.ECDSAWithP384AndSHA384),
|
||||
"ECDSAWithP521AndSHA512": reflect.ValueOf(tls.ECDSAWithP521AndSHA512),
|
||||
"ECDSAWithSHA1": reflect.ValueOf(tls.ECDSAWithSHA1),
|
||||
"Ed25519": reflect.ValueOf(tls.Ed25519),
|
||||
"InsecureCipherSuites": reflect.ValueOf(tls.InsecureCipherSuites),
|
||||
"Listen": reflect.ValueOf(tls.Listen),
|
||||
"LoadX509KeyPair": reflect.ValueOf(tls.LoadX509KeyPair),
|
||||
"NewLRUClientSessionCache": reflect.ValueOf(tls.NewLRUClientSessionCache),
|
||||
"NewListener": reflect.ValueOf(tls.NewListener),
|
||||
"NoClientCert": reflect.ValueOf(tls.NoClientCert),
|
||||
"PKCS1WithSHA1": reflect.ValueOf(tls.PKCS1WithSHA1),
|
||||
"PKCS1WithSHA256": reflect.ValueOf(tls.PKCS1WithSHA256),
|
||||
"PKCS1WithSHA384": reflect.ValueOf(tls.PKCS1WithSHA384),
|
||||
"PKCS1WithSHA512": reflect.ValueOf(tls.PKCS1WithSHA512),
|
||||
"PSSWithSHA256": reflect.ValueOf(tls.PSSWithSHA256),
|
||||
"PSSWithSHA384": reflect.ValueOf(tls.PSSWithSHA384),
|
||||
"PSSWithSHA512": reflect.ValueOf(tls.PSSWithSHA512),
|
||||
"RenegotiateFreelyAsClient": reflect.ValueOf(tls.RenegotiateFreelyAsClient),
|
||||
"RenegotiateNever": reflect.ValueOf(tls.RenegotiateNever),
|
||||
"RenegotiateOnceAsClient": reflect.ValueOf(tls.RenegotiateOnceAsClient),
|
||||
"RequestClientCert": reflect.ValueOf(tls.RequestClientCert),
|
||||
"RequireAndVerifyClientCert": reflect.ValueOf(tls.RequireAndVerifyClientCert),
|
||||
"RequireAnyClientCert": reflect.ValueOf(tls.RequireAnyClientCert),
|
||||
"Server": reflect.ValueOf(tls.Server),
|
||||
"TLS_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_AES_128_GCM_SHA256),
|
||||
"TLS_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_AES_256_GCM_SHA384),
|
||||
"TLS_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA),
|
||||
"TLS_FALLBACK_SCSV": reflect.ValueOf(tls.TLS_FALLBACK_SCSV),
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_RC4_128_SHA),
|
||||
"VerifyClientCertIfGiven": reflect.ValueOf(tls.VerifyClientCertIfGiven),
|
||||
"VersionSSL30": reflect.ValueOf(constant.MakeFromLiteral("768", token.INT, 0)),
|
||||
"VersionTLS10": reflect.ValueOf(constant.MakeFromLiteral("769", token.INT, 0)),
|
||||
"VersionTLS11": reflect.ValueOf(constant.MakeFromLiteral("770", token.INT, 0)),
|
||||
"VersionTLS12": reflect.ValueOf(constant.MakeFromLiteral("771", token.INT, 0)),
|
||||
"VersionTLS13": reflect.ValueOf(constant.MakeFromLiteral("772", token.INT, 0)),
|
||||
"X25519": reflect.ValueOf(tls.X25519),
|
||||
"X509KeyPair": reflect.ValueOf(tls.X509KeyPair),
|
||||
|
||||
// type definitions
|
||||
"Certificate": reflect.ValueOf((*tls.Certificate)(nil)),
|
||||
"CertificateRequestInfo": reflect.ValueOf((*tls.CertificateRequestInfo)(nil)),
|
||||
"CipherSuite": reflect.ValueOf((*tls.CipherSuite)(nil)),
|
||||
"ClientAuthType": reflect.ValueOf((*tls.ClientAuthType)(nil)),
|
||||
"ClientHelloInfo": reflect.ValueOf((*tls.ClientHelloInfo)(nil)),
|
||||
"ClientSessionCache": reflect.ValueOf((*tls.ClientSessionCache)(nil)),
|
||||
"ClientSessionState": reflect.ValueOf((*tls.ClientSessionState)(nil)),
|
||||
"Config": reflect.ValueOf((*tls.Config)(nil)),
|
||||
"Conn": reflect.ValueOf((*tls.Conn)(nil)),
|
||||
"ConnectionState": reflect.ValueOf((*tls.ConnectionState)(nil)),
|
||||
"CurveID": reflect.ValueOf((*tls.CurveID)(nil)),
|
||||
"Dialer": reflect.ValueOf((*tls.Dialer)(nil)),
|
||||
"RecordHeaderError": reflect.ValueOf((*tls.RecordHeaderError)(nil)),
|
||||
"RenegotiationSupport": reflect.ValueOf((*tls.RenegotiationSupport)(nil)),
|
||||
"SignatureScheme": reflect.ValueOf((*tls.SignatureScheme)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_ClientSessionCache": reflect.ValueOf((*_crypto_tls_ClientSessionCache)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _crypto_tls_ClientSessionCache is an interface wrapper for ClientSessionCache type
|
||||
type _crypto_tls_ClientSessionCache struct {
|
||||
IValue interface{}
|
||||
WGet func(sessionKey string) (session *tls.ClientSessionState, ok bool)
|
||||
WPut func(sessionKey string, cs *tls.ClientSessionState)
|
||||
}
|
||||
|
||||
func (W _crypto_tls_ClientSessionCache) Get(sessionKey string) (session *tls.ClientSessionState, ok bool) {
|
||||
return W.WGet(sessionKey)
|
||||
}
|
||||
func (W _crypto_tls_ClientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
|
||||
W.WPut(sessionKey, cs)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Code generated by 'yaegi extract embed'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["embed/embed"] = map[string]reflect.Value{
|
||||
// type definitions
|
||||
"FS": reflect.ValueOf((*embed.FS)(nil)),
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Code generated by 'yaegi extract errors'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["errors/errors"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"As": reflect.ValueOf(errors.As),
|
||||
"Is": reflect.ValueOf(errors.Is),
|
||||
"New": reflect.ValueOf(errors.New),
|
||||
"Unwrap": reflect.ValueOf(errors.Unwrap),
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated by 'yaegi extract net/netip'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["net/netip/netip"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"AddrFrom16": reflect.ValueOf(netip.AddrFrom16),
|
||||
"AddrFrom4": reflect.ValueOf(netip.AddrFrom4),
|
||||
"AddrFromSlice": reflect.ValueOf(netip.AddrFromSlice),
|
||||
"AddrPortFrom": reflect.ValueOf(netip.AddrPortFrom),
|
||||
"IPv4Unspecified": reflect.ValueOf(netip.IPv4Unspecified),
|
||||
"IPv6LinkLocalAllNodes": reflect.ValueOf(netip.IPv6LinkLocalAllNodes),
|
||||
"IPv6Unspecified": reflect.ValueOf(netip.IPv6Unspecified),
|
||||
"MustParseAddr": reflect.ValueOf(netip.MustParseAddr),
|
||||
"MustParseAddrPort": reflect.ValueOf(netip.MustParseAddrPort),
|
||||
"MustParsePrefix": reflect.ValueOf(netip.MustParsePrefix),
|
||||
"ParseAddr": reflect.ValueOf(netip.ParseAddr),
|
||||
"ParseAddrPort": reflect.ValueOf(netip.ParseAddrPort),
|
||||
"ParsePrefix": reflect.ValueOf(netip.ParsePrefix),
|
||||
"PrefixFrom": reflect.ValueOf(netip.PrefixFrom),
|
||||
|
||||
// type definitions
|
||||
"Addr": reflect.ValueOf((*netip.Addr)(nil)),
|
||||
"AddrPort": reflect.ValueOf((*netip.AddrPort)(nil)),
|
||||
"Prefix": reflect.ValueOf((*netip.Prefix)(nil)),
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
// Code generated by 'yaegi extract crypto/tls'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.20
|
||||
// +build go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/tls/tls"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"CipherSuiteName": reflect.ValueOf(tls.CipherSuiteName),
|
||||
"CipherSuites": reflect.ValueOf(tls.CipherSuites),
|
||||
"Client": reflect.ValueOf(tls.Client),
|
||||
"CurveP256": reflect.ValueOf(tls.CurveP256),
|
||||
"CurveP384": reflect.ValueOf(tls.CurveP384),
|
||||
"CurveP521": reflect.ValueOf(tls.CurveP521),
|
||||
"Dial": reflect.ValueOf(tls.Dial),
|
||||
"DialWithDialer": reflect.ValueOf(tls.DialWithDialer),
|
||||
"ECDSAWithP256AndSHA256": reflect.ValueOf(tls.ECDSAWithP256AndSHA256),
|
||||
"ECDSAWithP384AndSHA384": reflect.ValueOf(tls.ECDSAWithP384AndSHA384),
|
||||
"ECDSAWithP521AndSHA512": reflect.ValueOf(tls.ECDSAWithP521AndSHA512),
|
||||
"ECDSAWithSHA1": reflect.ValueOf(tls.ECDSAWithSHA1),
|
||||
"Ed25519": reflect.ValueOf(tls.Ed25519),
|
||||
"InsecureCipherSuites": reflect.ValueOf(tls.InsecureCipherSuites),
|
||||
"Listen": reflect.ValueOf(tls.Listen),
|
||||
"LoadX509KeyPair": reflect.ValueOf(tls.LoadX509KeyPair),
|
||||
"NewLRUClientSessionCache": reflect.ValueOf(tls.NewLRUClientSessionCache),
|
||||
"NewListener": reflect.ValueOf(tls.NewListener),
|
||||
"NoClientCert": reflect.ValueOf(tls.NoClientCert),
|
||||
"PKCS1WithSHA1": reflect.ValueOf(tls.PKCS1WithSHA1),
|
||||
"PKCS1WithSHA256": reflect.ValueOf(tls.PKCS1WithSHA256),
|
||||
"PKCS1WithSHA384": reflect.ValueOf(tls.PKCS1WithSHA384),
|
||||
"PKCS1WithSHA512": reflect.ValueOf(tls.PKCS1WithSHA512),
|
||||
"PSSWithSHA256": reflect.ValueOf(tls.PSSWithSHA256),
|
||||
"PSSWithSHA384": reflect.ValueOf(tls.PSSWithSHA384),
|
||||
"PSSWithSHA512": reflect.ValueOf(tls.PSSWithSHA512),
|
||||
"RenegotiateFreelyAsClient": reflect.ValueOf(tls.RenegotiateFreelyAsClient),
|
||||
"RenegotiateNever": reflect.ValueOf(tls.RenegotiateNever),
|
||||
"RenegotiateOnceAsClient": reflect.ValueOf(tls.RenegotiateOnceAsClient),
|
||||
"RequestClientCert": reflect.ValueOf(tls.RequestClientCert),
|
||||
"RequireAndVerifyClientCert": reflect.ValueOf(tls.RequireAndVerifyClientCert),
|
||||
"RequireAnyClientCert": reflect.ValueOf(tls.RequireAnyClientCert),
|
||||
"Server": reflect.ValueOf(tls.Server),
|
||||
"TLS_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_AES_128_GCM_SHA256),
|
||||
"TLS_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_AES_256_GCM_SHA384),
|
||||
"TLS_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA),
|
||||
"TLS_FALLBACK_SCSV": reflect.ValueOf(tls.TLS_FALLBACK_SCSV),
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_RC4_128_SHA),
|
||||
"VerifyClientCertIfGiven": reflect.ValueOf(tls.VerifyClientCertIfGiven),
|
||||
"VersionSSL30": reflect.ValueOf(constant.MakeFromLiteral("768", token.INT, 0)),
|
||||
"VersionTLS10": reflect.ValueOf(constant.MakeFromLiteral("769", token.INT, 0)),
|
||||
"VersionTLS11": reflect.ValueOf(constant.MakeFromLiteral("770", token.INT, 0)),
|
||||
"VersionTLS12": reflect.ValueOf(constant.MakeFromLiteral("771", token.INT, 0)),
|
||||
"VersionTLS13": reflect.ValueOf(constant.MakeFromLiteral("772", token.INT, 0)),
|
||||
"X25519": reflect.ValueOf(tls.X25519),
|
||||
"X509KeyPair": reflect.ValueOf(tls.X509KeyPair),
|
||||
|
||||
// type definitions
|
||||
"Certificate": reflect.ValueOf((*tls.Certificate)(nil)),
|
||||
"CertificateRequestInfo": reflect.ValueOf((*tls.CertificateRequestInfo)(nil)),
|
||||
"CertificateVerificationError": reflect.ValueOf((*tls.CertificateVerificationError)(nil)),
|
||||
"CipherSuite": reflect.ValueOf((*tls.CipherSuite)(nil)),
|
||||
"ClientAuthType": reflect.ValueOf((*tls.ClientAuthType)(nil)),
|
||||
"ClientHelloInfo": reflect.ValueOf((*tls.ClientHelloInfo)(nil)),
|
||||
"ClientSessionCache": reflect.ValueOf((*tls.ClientSessionCache)(nil)),
|
||||
"ClientSessionState": reflect.ValueOf((*tls.ClientSessionState)(nil)),
|
||||
"Config": reflect.ValueOf((*tls.Config)(nil)),
|
||||
"Conn": reflect.ValueOf((*tls.Conn)(nil)),
|
||||
"ConnectionState": reflect.ValueOf((*tls.ConnectionState)(nil)),
|
||||
"CurveID": reflect.ValueOf((*tls.CurveID)(nil)),
|
||||
"Dialer": reflect.ValueOf((*tls.Dialer)(nil)),
|
||||
"RecordHeaderError": reflect.ValueOf((*tls.RecordHeaderError)(nil)),
|
||||
"RenegotiationSupport": reflect.ValueOf((*tls.RenegotiationSupport)(nil)),
|
||||
"SignatureScheme": reflect.ValueOf((*tls.SignatureScheme)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_ClientSessionCache": reflect.ValueOf((*_crypto_tls_ClientSessionCache)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _crypto_tls_ClientSessionCache is an interface wrapper for ClientSessionCache type
|
||||
type _crypto_tls_ClientSessionCache struct {
|
||||
IValue interface{}
|
||||
WGet func(sessionKey string) (session *tls.ClientSessionState, ok bool)
|
||||
WPut func(sessionKey string, cs *tls.ClientSessionState)
|
||||
}
|
||||
|
||||
func (W _crypto_tls_ClientSessionCache) Get(sessionKey string) (session *tls.ClientSessionState, ok bool) {
|
||||
return W.WGet(sessionKey)
|
||||
}
|
||||
func (W _crypto_tls_ClientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
|
||||
W.WPut(sessionKey, cs)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Code generated by 'yaegi extract embed'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.20
|
||||
// +build go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["embed/embed"] = map[string]reflect.Value{
|
||||
// type definitions
|
||||
"FS": reflect.ValueOf((*embed.FS)(nil)),
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Code generated by 'yaegi extract errors'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.20
|
||||
// +build go1.20
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["errors/errors"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"As": reflect.ValueOf(errors.As),
|
||||
"Is": reflect.ValueOf(errors.Is),
|
||||
"Join": reflect.ValueOf(errors.Join),
|
||||
"New": reflect.ValueOf(errors.New),
|
||||
"Unwrap": reflect.ValueOf(errors.Unwrap),
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract archive/tar'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -17,6 +17,7 @@ func init() {
|
||||
// function, constant and variable definitions
|
||||
"ErrFieldTooLong": reflect.ValueOf(&tar.ErrFieldTooLong).Elem(),
|
||||
"ErrHeader": reflect.ValueOf(&tar.ErrHeader).Elem(),
|
||||
"ErrInsecurePath": reflect.ValueOf(&tar.ErrInsecurePath).Elem(),
|
||||
"ErrWriteAfterClose": reflect.ValueOf(&tar.ErrWriteAfterClose).Elem(),
|
||||
"ErrWriteTooLong": reflect.ValueOf(&tar.ErrWriteTooLong).Elem(),
|
||||
"FileInfoHeader": reflect.ValueOf(tar.FileInfoHeader),
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract archive/zip'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -17,6 +17,7 @@ func init() {
|
||||
"ErrAlgorithm": reflect.ValueOf(&zip.ErrAlgorithm).Elem(),
|
||||
"ErrChecksum": reflect.ValueOf(&zip.ErrChecksum).Elem(),
|
||||
"ErrFormat": reflect.ValueOf(&zip.ErrFormat).Elem(),
|
||||
"ErrInsecurePath": reflect.ValueOf(&zip.ErrInsecurePath).Elem(),
|
||||
"FileInfoHeader": reflect.ValueOf(zip.FileInfoHeader),
|
||||
"NewReader": reflect.ValueOf(zip.NewReader),
|
||||
"NewWriter": reflect.ValueOf(zip.NewWriter),
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract bufio'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract bytes'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -15,12 +15,16 @@ import (
|
||||
func init() {
|
||||
Symbols["bytes/bytes"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"Clone": reflect.ValueOf(bytes.Clone),
|
||||
"Compare": reflect.ValueOf(bytes.Compare),
|
||||
"Contains": reflect.ValueOf(bytes.Contains),
|
||||
"ContainsAny": reflect.ValueOf(bytes.ContainsAny),
|
||||
"ContainsFunc": reflect.ValueOf(bytes.ContainsFunc),
|
||||
"ContainsRune": reflect.ValueOf(bytes.ContainsRune),
|
||||
"Count": reflect.ValueOf(bytes.Count),
|
||||
"Cut": reflect.ValueOf(bytes.Cut),
|
||||
"CutPrefix": reflect.ValueOf(bytes.CutPrefix),
|
||||
"CutSuffix": reflect.ValueOf(bytes.CutSuffix),
|
||||
"Equal": reflect.ValueOf(bytes.Equal),
|
||||
"EqualFold": reflect.ValueOf(bytes.EqualFold),
|
||||
"ErrTooLarge": reflect.ValueOf(&bytes.ErrTooLarge).Elem(),
|
||||
14
stdlib/go1_21_cmp.go
Normal file
14
stdlib/go1_21_cmp.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Code generated by 'yaegi extract cmp'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["cmp/cmp"] = map[string]reflect.Value{}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract compress/bzip2'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract compress/flate'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract compress/gzip'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract compress/lzw'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract compress/zlib'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract container/heap'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract container/list'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract container/ring'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
62
stdlib/go1_21_context.go
Normal file
62
stdlib/go1_21_context.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Code generated by 'yaegi extract context'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["context/context"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"AfterFunc": reflect.ValueOf(context.AfterFunc),
|
||||
"Background": reflect.ValueOf(context.Background),
|
||||
"Canceled": reflect.ValueOf(&context.Canceled).Elem(),
|
||||
"Cause": reflect.ValueOf(context.Cause),
|
||||
"DeadlineExceeded": reflect.ValueOf(&context.DeadlineExceeded).Elem(),
|
||||
"TODO": reflect.ValueOf(context.TODO),
|
||||
"WithCancel": reflect.ValueOf(context.WithCancel),
|
||||
"WithCancelCause": reflect.ValueOf(context.WithCancelCause),
|
||||
"WithDeadline": reflect.ValueOf(context.WithDeadline),
|
||||
"WithDeadlineCause": reflect.ValueOf(context.WithDeadlineCause),
|
||||
"WithTimeout": reflect.ValueOf(context.WithTimeout),
|
||||
"WithTimeoutCause": reflect.ValueOf(context.WithTimeoutCause),
|
||||
"WithValue": reflect.ValueOf(context.WithValue),
|
||||
"WithoutCancel": reflect.ValueOf(context.WithoutCancel),
|
||||
|
||||
// type definitions
|
||||
"CancelCauseFunc": reflect.ValueOf((*context.CancelCauseFunc)(nil)),
|
||||
"CancelFunc": reflect.ValueOf((*context.CancelFunc)(nil)),
|
||||
"Context": reflect.ValueOf((*context.Context)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_Context": reflect.ValueOf((*_context_Context)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _context_Context is an interface wrapper for Context type
|
||||
type _context_Context struct {
|
||||
IValue interface{}
|
||||
WDeadline func() (deadline time.Time, ok bool)
|
||||
WDone func() <-chan struct{}
|
||||
WErr func() error
|
||||
WValue func(key any) any
|
||||
}
|
||||
|
||||
func (W _context_Context) Deadline() (deadline time.Time, ok bool) {
|
||||
return W.WDeadline()
|
||||
}
|
||||
func (W _context_Context) Done() <-chan struct{} {
|
||||
return W.WDone()
|
||||
}
|
||||
func (W _context_Context) Err() error {
|
||||
return W.WErr()
|
||||
}
|
||||
func (W _context_Context) Value(key any) any {
|
||||
return W.WValue(key)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/aes'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/cipher'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/des'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/dsa'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
48
stdlib/go1_21_crypto_ecdh.go
Normal file
48
stdlib/go1_21_crypto_ecdh.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Code generated by 'yaegi extract crypto/ecdh'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/ecdh"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/ecdh/ecdh"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"P256": reflect.ValueOf(ecdh.P256),
|
||||
"P384": reflect.ValueOf(ecdh.P384),
|
||||
"P521": reflect.ValueOf(ecdh.P521),
|
||||
"X25519": reflect.ValueOf(ecdh.X25519),
|
||||
|
||||
// type definitions
|
||||
"Curve": reflect.ValueOf((*ecdh.Curve)(nil)),
|
||||
"PrivateKey": reflect.ValueOf((*ecdh.PrivateKey)(nil)),
|
||||
"PublicKey": reflect.ValueOf((*ecdh.PublicKey)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_Curve": reflect.ValueOf((*_crypto_ecdh_Curve)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _crypto_ecdh_Curve is an interface wrapper for Curve type
|
||||
type _crypto_ecdh_Curve struct {
|
||||
IValue interface{}
|
||||
WGenerateKey func(rand io.Reader) (*ecdh.PrivateKey, error)
|
||||
WNewPrivateKey func(key []byte) (*ecdh.PrivateKey, error)
|
||||
WNewPublicKey func(key []byte) (*ecdh.PublicKey, error)
|
||||
}
|
||||
|
||||
func (W _crypto_ecdh_Curve) GenerateKey(rand io.Reader) (*ecdh.PrivateKey, error) {
|
||||
return W.WGenerateKey(rand)
|
||||
}
|
||||
func (W _crypto_ecdh_Curve) NewPrivateKey(key []byte) (*ecdh.PrivateKey, error) {
|
||||
return W.WNewPrivateKey(key)
|
||||
}
|
||||
func (W _crypto_ecdh_Curve) NewPublicKey(key []byte) (*ecdh.PublicKey, error) {
|
||||
return W.WNewPublicKey(key)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/ecdsa'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
33
stdlib/go1_21_crypto_ed25519.go
Normal file
33
stdlib/go1_21_crypto_ed25519.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Code generated by 'yaegi extract crypto/ed25519'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/ed25519/ed25519"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"GenerateKey": reflect.ValueOf(ed25519.GenerateKey),
|
||||
"NewKeyFromSeed": reflect.ValueOf(ed25519.NewKeyFromSeed),
|
||||
"PrivateKeySize": reflect.ValueOf(constant.MakeFromLiteral("64", token.INT, 0)),
|
||||
"PublicKeySize": reflect.ValueOf(constant.MakeFromLiteral("32", token.INT, 0)),
|
||||
"SeedSize": reflect.ValueOf(constant.MakeFromLiteral("32", token.INT, 0)),
|
||||
"Sign": reflect.ValueOf(ed25519.Sign),
|
||||
"SignatureSize": reflect.ValueOf(constant.MakeFromLiteral("64", token.INT, 0)),
|
||||
"Verify": reflect.ValueOf(ed25519.Verify),
|
||||
"VerifyWithOptions": reflect.ValueOf(ed25519.VerifyWithOptions),
|
||||
|
||||
// type definitions
|
||||
"Options": reflect.ValueOf((*ed25519.Options)(nil)),
|
||||
"PrivateKey": reflect.ValueOf((*ed25519.PrivateKey)(nil)),
|
||||
"PublicKey": reflect.ValueOf((*ed25519.PublicKey)(nil)),
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/elliptic'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/hmac'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/md5'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/rand'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/rc4'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/rsa'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/sha1'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/sha256'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/sha512'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/subtle'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -19,5 +19,6 @@ func init() {
|
||||
"ConstantTimeEq": reflect.ValueOf(subtle.ConstantTimeEq),
|
||||
"ConstantTimeLessOrEq": reflect.ValueOf(subtle.ConstantTimeLessOrEq),
|
||||
"ConstantTimeSelect": reflect.ValueOf(subtle.ConstantTimeSelect),
|
||||
"XORBytes": reflect.ValueOf(subtle.XORBytes),
|
||||
}
|
||||
}
|
||||
148
stdlib/go1_21_crypto_tls.go
Normal file
148
stdlib/go1_21_crypto_tls.go
Normal file
@@ -0,0 +1,148 @@
|
||||
// Code generated by 'yaegi extract crypto/tls'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Symbols["crypto/tls/tls"] = map[string]reflect.Value{
|
||||
// function, constant and variable definitions
|
||||
"CipherSuiteName": reflect.ValueOf(tls.CipherSuiteName),
|
||||
"CipherSuites": reflect.ValueOf(tls.CipherSuites),
|
||||
"Client": reflect.ValueOf(tls.Client),
|
||||
"CurveP256": reflect.ValueOf(tls.CurveP256),
|
||||
"CurveP384": reflect.ValueOf(tls.CurveP384),
|
||||
"CurveP521": reflect.ValueOf(tls.CurveP521),
|
||||
"Dial": reflect.ValueOf(tls.Dial),
|
||||
"DialWithDialer": reflect.ValueOf(tls.DialWithDialer),
|
||||
"ECDSAWithP256AndSHA256": reflect.ValueOf(tls.ECDSAWithP256AndSHA256),
|
||||
"ECDSAWithP384AndSHA384": reflect.ValueOf(tls.ECDSAWithP384AndSHA384),
|
||||
"ECDSAWithP521AndSHA512": reflect.ValueOf(tls.ECDSAWithP521AndSHA512),
|
||||
"ECDSAWithSHA1": reflect.ValueOf(tls.ECDSAWithSHA1),
|
||||
"Ed25519": reflect.ValueOf(tls.Ed25519),
|
||||
"InsecureCipherSuites": reflect.ValueOf(tls.InsecureCipherSuites),
|
||||
"Listen": reflect.ValueOf(tls.Listen),
|
||||
"LoadX509KeyPair": reflect.ValueOf(tls.LoadX509KeyPair),
|
||||
"NewLRUClientSessionCache": reflect.ValueOf(tls.NewLRUClientSessionCache),
|
||||
"NewListener": reflect.ValueOf(tls.NewListener),
|
||||
"NewResumptionState": reflect.ValueOf(tls.NewResumptionState),
|
||||
"NoClientCert": reflect.ValueOf(tls.NoClientCert),
|
||||
"PKCS1WithSHA1": reflect.ValueOf(tls.PKCS1WithSHA1),
|
||||
"PKCS1WithSHA256": reflect.ValueOf(tls.PKCS1WithSHA256),
|
||||
"PKCS1WithSHA384": reflect.ValueOf(tls.PKCS1WithSHA384),
|
||||
"PKCS1WithSHA512": reflect.ValueOf(tls.PKCS1WithSHA512),
|
||||
"PSSWithSHA256": reflect.ValueOf(tls.PSSWithSHA256),
|
||||
"PSSWithSHA384": reflect.ValueOf(tls.PSSWithSHA384),
|
||||
"PSSWithSHA512": reflect.ValueOf(tls.PSSWithSHA512),
|
||||
"ParseSessionState": reflect.ValueOf(tls.ParseSessionState),
|
||||
"QUICClient": reflect.ValueOf(tls.QUICClient),
|
||||
"QUICEncryptionLevelApplication": reflect.ValueOf(tls.QUICEncryptionLevelApplication),
|
||||
"QUICEncryptionLevelEarly": reflect.ValueOf(tls.QUICEncryptionLevelEarly),
|
||||
"QUICEncryptionLevelHandshake": reflect.ValueOf(tls.QUICEncryptionLevelHandshake),
|
||||
"QUICEncryptionLevelInitial": reflect.ValueOf(tls.QUICEncryptionLevelInitial),
|
||||
"QUICHandshakeDone": reflect.ValueOf(tls.QUICHandshakeDone),
|
||||
"QUICNoEvent": reflect.ValueOf(tls.QUICNoEvent),
|
||||
"QUICRejectedEarlyData": reflect.ValueOf(tls.QUICRejectedEarlyData),
|
||||
"QUICServer": reflect.ValueOf(tls.QUICServer),
|
||||
"QUICSetReadSecret": reflect.ValueOf(tls.QUICSetReadSecret),
|
||||
"QUICSetWriteSecret": reflect.ValueOf(tls.QUICSetWriteSecret),
|
||||
"QUICTransportParameters": reflect.ValueOf(tls.QUICTransportParameters),
|
||||
"QUICTransportParametersRequired": reflect.ValueOf(tls.QUICTransportParametersRequired),
|
||||
"QUICWriteData": reflect.ValueOf(tls.QUICWriteData),
|
||||
"RenegotiateFreelyAsClient": reflect.ValueOf(tls.RenegotiateFreelyAsClient),
|
||||
"RenegotiateNever": reflect.ValueOf(tls.RenegotiateNever),
|
||||
"RenegotiateOnceAsClient": reflect.ValueOf(tls.RenegotiateOnceAsClient),
|
||||
"RequestClientCert": reflect.ValueOf(tls.RequestClientCert),
|
||||
"RequireAndVerifyClientCert": reflect.ValueOf(tls.RequireAndVerifyClientCert),
|
||||
"RequireAnyClientCert": reflect.ValueOf(tls.RequireAnyClientCert),
|
||||
"Server": reflect.ValueOf(tls.Server),
|
||||
"TLS_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_AES_128_GCM_SHA256),
|
||||
"TLS_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_AES_256_GCM_SHA384),
|
||||
"TLS_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305),
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA),
|
||||
"TLS_FALLBACK_SCSV": reflect.ValueOf(tls.TLS_FALLBACK_SCSV),
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_CBC_SHA256),
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": reflect.ValueOf(tls.TLS_RSA_WITH_AES_128_GCM_SHA256),
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_CBC_SHA),
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": reflect.ValueOf(tls.TLS_RSA_WITH_AES_256_GCM_SHA384),
|
||||
"TLS_RSA_WITH_RC4_128_SHA": reflect.ValueOf(tls.TLS_RSA_WITH_RC4_128_SHA),
|
||||
"VerifyClientCertIfGiven": reflect.ValueOf(tls.VerifyClientCertIfGiven),
|
||||
"VersionName": reflect.ValueOf(tls.VersionName),
|
||||
"VersionSSL30": reflect.ValueOf(constant.MakeFromLiteral("768", token.INT, 0)),
|
||||
"VersionTLS10": reflect.ValueOf(constant.MakeFromLiteral("769", token.INT, 0)),
|
||||
"VersionTLS11": reflect.ValueOf(constant.MakeFromLiteral("770", token.INT, 0)),
|
||||
"VersionTLS12": reflect.ValueOf(constant.MakeFromLiteral("771", token.INT, 0)),
|
||||
"VersionTLS13": reflect.ValueOf(constant.MakeFromLiteral("772", token.INT, 0)),
|
||||
"X25519": reflect.ValueOf(tls.X25519),
|
||||
"X509KeyPair": reflect.ValueOf(tls.X509KeyPair),
|
||||
|
||||
// type definitions
|
||||
"AlertError": reflect.ValueOf((*tls.AlertError)(nil)),
|
||||
"Certificate": reflect.ValueOf((*tls.Certificate)(nil)),
|
||||
"CertificateRequestInfo": reflect.ValueOf((*tls.CertificateRequestInfo)(nil)),
|
||||
"CertificateVerificationError": reflect.ValueOf((*tls.CertificateVerificationError)(nil)),
|
||||
"CipherSuite": reflect.ValueOf((*tls.CipherSuite)(nil)),
|
||||
"ClientAuthType": reflect.ValueOf((*tls.ClientAuthType)(nil)),
|
||||
"ClientHelloInfo": reflect.ValueOf((*tls.ClientHelloInfo)(nil)),
|
||||
"ClientSessionCache": reflect.ValueOf((*tls.ClientSessionCache)(nil)),
|
||||
"ClientSessionState": reflect.ValueOf((*tls.ClientSessionState)(nil)),
|
||||
"Config": reflect.ValueOf((*tls.Config)(nil)),
|
||||
"Conn": reflect.ValueOf((*tls.Conn)(nil)),
|
||||
"ConnectionState": reflect.ValueOf((*tls.ConnectionState)(nil)),
|
||||
"CurveID": reflect.ValueOf((*tls.CurveID)(nil)),
|
||||
"Dialer": reflect.ValueOf((*tls.Dialer)(nil)),
|
||||
"QUICConfig": reflect.ValueOf((*tls.QUICConfig)(nil)),
|
||||
"QUICConn": reflect.ValueOf((*tls.QUICConn)(nil)),
|
||||
"QUICEncryptionLevel": reflect.ValueOf((*tls.QUICEncryptionLevel)(nil)),
|
||||
"QUICEvent": reflect.ValueOf((*tls.QUICEvent)(nil)),
|
||||
"QUICEventKind": reflect.ValueOf((*tls.QUICEventKind)(nil)),
|
||||
"QUICSessionTicketOptions": reflect.ValueOf((*tls.QUICSessionTicketOptions)(nil)),
|
||||
"RecordHeaderError": reflect.ValueOf((*tls.RecordHeaderError)(nil)),
|
||||
"RenegotiationSupport": reflect.ValueOf((*tls.RenegotiationSupport)(nil)),
|
||||
"SessionState": reflect.ValueOf((*tls.SessionState)(nil)),
|
||||
"SignatureScheme": reflect.ValueOf((*tls.SignatureScheme)(nil)),
|
||||
|
||||
// interface wrapper definitions
|
||||
"_ClientSessionCache": reflect.ValueOf((*_crypto_tls_ClientSessionCache)(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
// _crypto_tls_ClientSessionCache is an interface wrapper for ClientSessionCache type
|
||||
type _crypto_tls_ClientSessionCache struct {
|
||||
IValue interface{}
|
||||
WGet func(sessionKey string) (session *tls.ClientSessionState, ok bool)
|
||||
WPut func(sessionKey string, cs *tls.ClientSessionState)
|
||||
}
|
||||
|
||||
func (W _crypto_tls_ClientSessionCache) Get(sessionKey string) (session *tls.ClientSessionState, ok bool) {
|
||||
return W.WGet(sessionKey)
|
||||
}
|
||||
func (W _crypto_tls_ClientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
|
||||
W.WPut(sessionKey, cs)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/x509'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.20
|
||||
// +build go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -115,6 +115,7 @@ func init() {
|
||||
"PEMCipher": reflect.ValueOf((*x509.PEMCipher)(nil)),
|
||||
"PublicKeyAlgorithm": reflect.ValueOf((*x509.PublicKeyAlgorithm)(nil)),
|
||||
"RevocationList": reflect.ValueOf((*x509.RevocationList)(nil)),
|
||||
"RevocationListEntry": reflect.ValueOf((*x509.RevocationListEntry)(nil)),
|
||||
"SignatureAlgorithm": reflect.ValueOf((*x509.SignatureAlgorithm)(nil)),
|
||||
"SystemRootsError": reflect.ValueOf((*x509.SystemRootsError)(nil)),
|
||||
"UnhandledCriticalExtension": reflect.ValueOf((*x509.UnhandledCriticalExtension)(nil)),
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract crypto/x509/pkix'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract database/sql'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract database/sql/driver'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract debug/buildinfo'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract debug/dwarf'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract debug/elf'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.20
|
||||
// +build go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -21,6 +21,38 @@ func init() {
|
||||
"COMPRESS_LOOS": reflect.ValueOf(elf.COMPRESS_LOOS),
|
||||
"COMPRESS_LOPROC": reflect.ValueOf(elf.COMPRESS_LOPROC),
|
||||
"COMPRESS_ZLIB": reflect.ValueOf(elf.COMPRESS_ZLIB),
|
||||
"COMPRESS_ZSTD": reflect.ValueOf(elf.COMPRESS_ZSTD),
|
||||
"DF_1_CONFALT": reflect.ValueOf(elf.DF_1_CONFALT),
|
||||
"DF_1_DIRECT": reflect.ValueOf(elf.DF_1_DIRECT),
|
||||
"DF_1_DISPRELDNE": reflect.ValueOf(elf.DF_1_DISPRELDNE),
|
||||
"DF_1_DISPRELPND": reflect.ValueOf(elf.DF_1_DISPRELPND),
|
||||
"DF_1_EDITED": reflect.ValueOf(elf.DF_1_EDITED),
|
||||
"DF_1_ENDFILTEE": reflect.ValueOf(elf.DF_1_ENDFILTEE),
|
||||
"DF_1_GLOBAL": reflect.ValueOf(elf.DF_1_GLOBAL),
|
||||
"DF_1_GLOBAUDIT": reflect.ValueOf(elf.DF_1_GLOBAUDIT),
|
||||
"DF_1_GROUP": reflect.ValueOf(elf.DF_1_GROUP),
|
||||
"DF_1_IGNMULDEF": reflect.ValueOf(elf.DF_1_IGNMULDEF),
|
||||
"DF_1_INITFIRST": reflect.ValueOf(elf.DF_1_INITFIRST),
|
||||
"DF_1_INTERPOSE": reflect.ValueOf(elf.DF_1_INTERPOSE),
|
||||
"DF_1_KMOD": reflect.ValueOf(elf.DF_1_KMOD),
|
||||
"DF_1_LOADFLTR": reflect.ValueOf(elf.DF_1_LOADFLTR),
|
||||
"DF_1_NOCOMMON": reflect.ValueOf(elf.DF_1_NOCOMMON),
|
||||
"DF_1_NODEFLIB": reflect.ValueOf(elf.DF_1_NODEFLIB),
|
||||
"DF_1_NODELETE": reflect.ValueOf(elf.DF_1_NODELETE),
|
||||
"DF_1_NODIRECT": reflect.ValueOf(elf.DF_1_NODIRECT),
|
||||
"DF_1_NODUMP": reflect.ValueOf(elf.DF_1_NODUMP),
|
||||
"DF_1_NOHDR": reflect.ValueOf(elf.DF_1_NOHDR),
|
||||
"DF_1_NOKSYMS": reflect.ValueOf(elf.DF_1_NOKSYMS),
|
||||
"DF_1_NOOPEN": reflect.ValueOf(elf.DF_1_NOOPEN),
|
||||
"DF_1_NORELOC": reflect.ValueOf(elf.DF_1_NORELOC),
|
||||
"DF_1_NOW": reflect.ValueOf(elf.DF_1_NOW),
|
||||
"DF_1_ORIGIN": reflect.ValueOf(elf.DF_1_ORIGIN),
|
||||
"DF_1_PIE": reflect.ValueOf(elf.DF_1_PIE),
|
||||
"DF_1_SINGLETON": reflect.ValueOf(elf.DF_1_SINGLETON),
|
||||
"DF_1_STUB": reflect.ValueOf(elf.DF_1_STUB),
|
||||
"DF_1_SYMINTPOSE": reflect.ValueOf(elf.DF_1_SYMINTPOSE),
|
||||
"DF_1_TRANS": reflect.ValueOf(elf.DF_1_TRANS),
|
||||
"DF_1_WEAKFILTER": reflect.ValueOf(elf.DF_1_WEAKFILTER),
|
||||
"DF_BIND_NOW": reflect.ValueOf(elf.DF_BIND_NOW),
|
||||
"DF_ORIGIN": reflect.ValueOf(elf.DF_ORIGIN),
|
||||
"DF_STATIC_TLS": reflect.ValueOf(elf.DF_STATIC_TLS),
|
||||
@@ -1097,6 +1129,7 @@ func init() {
|
||||
"R_PPC64_REL16_LO": reflect.ValueOf(elf.R_PPC64_REL16_LO),
|
||||
"R_PPC64_REL24": reflect.ValueOf(elf.R_PPC64_REL24),
|
||||
"R_PPC64_REL24_NOTOC": reflect.ValueOf(elf.R_PPC64_REL24_NOTOC),
|
||||
"R_PPC64_REL24_P9NOTOC": reflect.ValueOf(elf.R_PPC64_REL24_P9NOTOC),
|
||||
"R_PPC64_REL30": reflect.ValueOf(elf.R_PPC64_REL30),
|
||||
"R_PPC64_REL32": reflect.ValueOf(elf.R_PPC64_REL32),
|
||||
"R_PPC64_REL64": reflect.ValueOf(elf.R_PPC64_REL64),
|
||||
@@ -1460,6 +1493,7 @@ func init() {
|
||||
"Dyn32": reflect.ValueOf((*elf.Dyn32)(nil)),
|
||||
"Dyn64": reflect.ValueOf((*elf.Dyn64)(nil)),
|
||||
"DynFlag": reflect.ValueOf((*elf.DynFlag)(nil)),
|
||||
"DynFlag1": reflect.ValueOf((*elf.DynFlag1)(nil)),
|
||||
"DynTag": reflect.ValueOf((*elf.DynTag)(nil)),
|
||||
"File": reflect.ValueOf((*elf.File)(nil)),
|
||||
"FileHeader": reflect.ValueOf((*elf.FileHeader)(nil)),
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract debug/gosym'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by 'yaegi extract debug/macho'. DO NOT EDIT.
|
||||
|
||||
//go:build go1.19 && !go1.20
|
||||
// +build go1.19,!go1.20
|
||||
//go:build go1.21 && !go1.22
|
||||
// +build go1.21,!go1.22
|
||||
|
||||
package stdlib
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user