mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-02-04 20:05:05 +00:00
bumps our fork of modernc.org/sqlite to v1.34.5 (#3731)
This commit is contained in:
parent
053d820845
commit
a24048fc05
6
go.mod
6
go.mod
|
@ -6,7 +6,7 @@ go 1.23
|
||||||
replace github.com/go-swagger/go-swagger => github.com/superseriousbusiness/go-swagger v0.31.0-gts-go1.23-fix
|
replace github.com/go-swagger/go-swagger => github.com/superseriousbusiness/go-swagger v0.31.0-gts-go1.23-fix
|
||||||
|
|
||||||
// Replace modernc/sqlite with our version that fixes the concurrency INTERRUPT issue
|
// Replace modernc/sqlite with our version that fixes the concurrency INTERRUPT issue
|
||||||
replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.2-concurrency-workaround
|
replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.5-concurrency-workaround
|
||||||
|
|
||||||
// Below pin otel libraries to v1.29.0 until we can figure out issues
|
// Below pin otel libraries to v1.29.0 until we can figure out issues
|
||||||
replace go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.29.0
|
replace go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.29.0
|
||||||
|
@ -161,7 +161,6 @@ require (
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/gorilla/sessions v1.2.2 // indirect
|
github.com/gorilla/sessions v1.2.2 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/huandu/xstrings v1.4.0 // indirect
|
github.com/huandu/xstrings v1.4.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
|
@ -235,10 +234,7 @@ require (
|
||||||
google.golang.org/protobuf v1.36.2 // indirect
|
google.golang.org/protobuf v1.36.2 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
|
||||||
modernc.org/libc v1.55.3 // indirect
|
modernc.org/libc v1.55.3 // indirect
|
||||||
modernc.org/mathutil v1.6.0 // indirect
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
modernc.org/memory v1.8.0 // indirect
|
modernc.org/memory v1.8.0 // indirect
|
||||||
modernc.org/strutil v1.2.0 // indirect
|
|
||||||
modernc.org/token v1.1.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
generated
8
go.sum
generated
|
@ -328,8 +328,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjw
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
@ -615,8 +613,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.2-concurrency-workaround h1:Z/9vgdPNZm8ZDANnIJ7ZGeYKJ5biqPY1OQbN+DLCtec=
|
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.5-concurrency-workaround h1:BLmmUkkZ2KiS8k2lePZRQo7Z5puFrfxuFq9BrJQmS9o=
|
||||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.2-concurrency-workaround/go.mod h1:dnR723UrTtjKpoHCAMN0Q/gZ9MT4r+iRvIBb9umWFkU=
|
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.5-concurrency-workaround/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE=
|
||||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -1012,8 +1010,6 @@ modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
|
||||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
|
||||||
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
||||||
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
||||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
|
23
vendor/github.com/hashicorp/golang-lru/v2/.gitignore
generated
vendored
23
vendor/github.com/hashicorp/golang-lru/v2/.gitignore
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
46
vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml
generated
vendored
46
vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
# Copyright (c) HashiCorp, Inc.
|
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
linters:
|
|
||||||
fast: false
|
|
||||||
disable-all: true
|
|
||||||
enable:
|
|
||||||
- revive
|
|
||||||
- megacheck
|
|
||||||
- govet
|
|
||||||
- unconvert
|
|
||||||
- gas
|
|
||||||
- gocyclo
|
|
||||||
- dupl
|
|
||||||
- misspell
|
|
||||||
- unparam
|
|
||||||
- unused
|
|
||||||
- typecheck
|
|
||||||
- ineffassign
|
|
||||||
# - stylecheck
|
|
||||||
- exportloopref
|
|
||||||
- gocritic
|
|
||||||
- nakedret
|
|
||||||
- gosimple
|
|
||||||
- prealloc
|
|
||||||
|
|
||||||
# golangci-lint configuration file
|
|
||||||
linters-settings:
|
|
||||||
revive:
|
|
||||||
ignore-generated-header: true
|
|
||||||
severity: warning
|
|
||||||
rules:
|
|
||||||
- name: package-comments
|
|
||||||
severity: warning
|
|
||||||
disabled: true
|
|
||||||
- name: exported
|
|
||||||
severity: warning
|
|
||||||
disabled: false
|
|
||||||
arguments: ["checkPrivateReceivers", "disableStutteringCheck"]
|
|
||||||
|
|
||||||
issues:
|
|
||||||
exclude-use-default: false
|
|
||||||
exclude-rules:
|
|
||||||
- path: _test\.go
|
|
||||||
linters:
|
|
||||||
- dupl
|
|
267
vendor/github.com/hashicorp/golang-lru/v2/2q.go
generated
vendored
267
vendor/github.com/hashicorp/golang-lru/v2/2q.go
generated
vendored
|
@ -1,267 +0,0 @@
|
||||||
// Copyright (c) HashiCorp, Inc.
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package lru
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru/v2/simplelru"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Default2QRecentRatio is the ratio of the 2Q cache dedicated
|
|
||||||
// to recently added entries that have only been accessed once.
|
|
||||||
Default2QRecentRatio = 0.25
|
|
||||||
|
|
||||||
// Default2QGhostEntries is the default ratio of ghost
|
|
||||||
// entries kept to track entries recently evicted
|
|
||||||
Default2QGhostEntries = 0.50
|
|
||||||
)
|
|
||||||
|
|
||||||
// TwoQueueCache is a thread-safe fixed size 2Q cache.
|
|
||||||
// 2Q is an enhancement over the standard LRU cache
|
|
||||||
// in that it tracks both frequently and recently used
|
|
||||||
// entries separately. This avoids a burst in access to new
|
|
||||||
// entries from evicting frequently used entries. It adds some
|
|
||||||
// additional tracking overhead to the standard LRU cache, and is
|
|
||||||
// computationally about 2x the cost, and adds some metadata over
|
|
||||||
// head. The ARCCache is similar, but does not require setting any
|
|
||||||
// parameters.
|
|
||||||
type TwoQueueCache[K comparable, V any] struct {
|
|
||||||
size int
|
|
||||||
recentSize int
|
|
||||||
recentRatio float64
|
|
||||||
ghostRatio float64
|
|
||||||
|
|
||||||
recent simplelru.LRUCache[K, V]
|
|
||||||
frequent simplelru.LRUCache[K, V]
|
|
||||||
recentEvict simplelru.LRUCache[K, struct{}]
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// New2Q creates a new TwoQueueCache using the default
|
|
||||||
// values for the parameters.
|
|
||||||
func New2Q[K comparable, V any](size int) (*TwoQueueCache[K, V], error) {
|
|
||||||
return New2QParams[K, V](size, Default2QRecentRatio, Default2QGhostEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New2QParams creates a new TwoQueueCache using the provided
|
|
||||||
// parameter values.
|
|
||||||
func New2QParams[K comparable, V any](size int, recentRatio, ghostRatio float64) (*TwoQueueCache[K, V], error) {
|
|
||||||
if size <= 0 {
|
|
||||||
return nil, errors.New("invalid size")
|
|
||||||
}
|
|
||||||
if recentRatio < 0.0 || recentRatio > 1.0 {
|
|
||||||
return nil, errors.New("invalid recent ratio")
|
|
||||||
}
|
|
||||||
if ghostRatio < 0.0 || ghostRatio > 1.0 {
|
|
||||||
return nil, errors.New("invalid ghost ratio")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the sub-sizes
|
|
||||||
recentSize := int(float64(size) * recentRatio)
|
|
||||||
evictSize := int(float64(size) * ghostRatio)
|
|
||||||
|
|
||||||
// Allocate the LRUs
|
|
||||||
recent, err := simplelru.NewLRU[K, V](size, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
frequent, err := simplelru.NewLRU[K, V](size, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
recentEvict, err := simplelru.NewLRU[K, struct{}](evictSize, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the cache
|
|
||||||
c := &TwoQueueCache[K, V]{
|
|
||||||
size: size,
|
|
||||||
recentSize: recentSize,
|
|
||||||
recentRatio: recentRatio,
|
|
||||||
ghostRatio: ghostRatio,
|
|
||||||
recent: recent,
|
|
||||||
frequent: frequent,
|
|
||||||
recentEvict: recentEvict,
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
|
||||||
func (c *TwoQueueCache[K, V]) Get(key K) (value V, ok bool) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
// Check if this is a frequent value
|
|
||||||
if val, ok := c.frequent.Get(key); ok {
|
|
||||||
return val, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the value is contained in recent, then we
|
|
||||||
// promote it to frequent
|
|
||||||
if val, ok := c.recent.Peek(key); ok {
|
|
||||||
c.recent.Remove(key)
|
|
||||||
c.frequent.Add(key, val)
|
|
||||||
return val, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// No hit
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add adds a value to the cache.
|
|
||||||
func (c *TwoQueueCache[K, V]) Add(key K, value V) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
// Check if the value is frequently used already,
|
|
||||||
// and just update the value
|
|
||||||
if c.frequent.Contains(key) {
|
|
||||||
c.frequent.Add(key, value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the value is recently used, and promote
|
|
||||||
// the value into the frequent list
|
|
||||||
if c.recent.Contains(key) {
|
|
||||||
c.recent.Remove(key)
|
|
||||||
c.frequent.Add(key, value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the value was recently evicted, add it to the
|
|
||||||
// frequently used list
|
|
||||||
if c.recentEvict.Contains(key) {
|
|
||||||
c.ensureSpace(true)
|
|
||||||
c.recentEvict.Remove(key)
|
|
||||||
c.frequent.Add(key, value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to the recently seen list
|
|
||||||
c.ensureSpace(false)
|
|
||||||
c.recent.Add(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensureSpace is used to ensure we have space in the cache
|
|
||||||
func (c *TwoQueueCache[K, V]) ensureSpace(recentEvict bool) {
|
|
||||||
// If we have space, nothing to do
|
|
||||||
recentLen := c.recent.Len()
|
|
||||||
freqLen := c.frequent.Len()
|
|
||||||
if recentLen+freqLen < c.size {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the recent buffer is larger than
|
|
||||||
// the target, evict from there
|
|
||||||
if recentLen > 0 && (recentLen > c.recentSize || (recentLen == c.recentSize && !recentEvict)) {
|
|
||||||
k, _, _ := c.recent.RemoveOldest()
|
|
||||||
c.recentEvict.Add(k, struct{}{})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove from the frequent list otherwise
|
|
||||||
c.frequent.RemoveOldest()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of items in the cache.
|
|
||||||
func (c *TwoQueueCache[K, V]) Len() int {
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
return c.recent.Len() + c.frequent.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize changes the cache size.
|
|
||||||
func (c *TwoQueueCache[K, V]) Resize(size int) (evicted int) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
// Recalculate the sub-sizes
|
|
||||||
recentSize := int(float64(size) * c.recentRatio)
|
|
||||||
evictSize := int(float64(size) * c.ghostRatio)
|
|
||||||
c.size = size
|
|
||||||
c.recentSize = recentSize
|
|
||||||
|
|
||||||
// ensureSpace
|
|
||||||
diff := c.recent.Len() + c.frequent.Len() - size
|
|
||||||
if diff < 0 {
|
|
||||||
diff = 0
|
|
||||||
}
|
|
||||||
for i := 0; i < diff; i++ {
|
|
||||||
c.ensureSpace(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reallocate the LRUs
|
|
||||||
c.recent.Resize(size)
|
|
||||||
c.frequent.Resize(size)
|
|
||||||
c.recentEvict.Resize(evictSize)
|
|
||||||
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns a slice of the keys in the cache.
|
|
||||||
// The frequently used keys are first in the returned slice.
|
|
||||||
func (c *TwoQueueCache[K, V]) Keys() []K {
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
k1 := c.frequent.Keys()
|
|
||||||
k2 := c.recent.Keys()
|
|
||||||
return append(k1, k2...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns a slice of the values in the cache.
|
|
||||||
// The frequently used values are first in the returned slice.
|
|
||||||
func (c *TwoQueueCache[K, V]) Values() []V {
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
v1 := c.frequent.Values()
|
|
||||||
v2 := c.recent.Values()
|
|
||||||
return append(v1, v2...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
|
||||||
func (c *TwoQueueCache[K, V]) Remove(key K) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
if c.frequent.Remove(key) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.recent.Remove(key) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.recentEvict.Remove(key) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
|
||||||
func (c *TwoQueueCache[K, V]) Purge() {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
c.recent.Purge()
|
|
||||||
c.frequent.Purge()
|
|
||||||
c.recentEvict.Purge()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains is used to check if the cache contains a key
|
|
||||||
// without updating recency or frequency.
|
|
||||||
func (c *TwoQueueCache[K, V]) Contains(key K) bool {
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
return c.frequent.Contains(key) || c.recent.Contains(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Peek is used to inspect the cache value of a key
|
|
||||||
// without updating recency or frequency.
|
|
||||||
func (c *TwoQueueCache[K, V]) Peek(key K) (value V, ok bool) {
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
if val, ok := c.frequent.Peek(key); ok {
|
|
||||||
return val, ok
|
|
||||||
}
|
|
||||||
return c.recent.Peek(key)
|
|
||||||
}
|
|
364
vendor/github.com/hashicorp/golang-lru/v2/LICENSE
generated
vendored
364
vendor/github.com/hashicorp/golang-lru/v2/LICENSE
generated
vendored
|
@ -1,364 +0,0 @@
|
||||||
Copyright (c) 2014 HashiCorp, Inc.
|
|
||||||
|
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
79
vendor/github.com/hashicorp/golang-lru/v2/README.md
generated
vendored
79
vendor/github.com/hashicorp/golang-lru/v2/README.md
generated
vendored
|
@ -1,79 +0,0 @@
|
||||||
golang-lru
|
|
||||||
==========
|
|
||||||
|
|
||||||
This provides the `lru` package which implements a fixed-size
|
|
||||||
thread safe LRU cache. It is based on the cache in Groupcache.
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
=============
|
|
||||||
|
|
||||||
Full docs are available on [Go Packages](https://pkg.go.dev/github.com/hashicorp/golang-lru/v2)
|
|
||||||
|
|
||||||
LRU cache example
|
|
||||||
=================
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/hashicorp/golang-lru/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
l, _ := lru.New[int, any](128)
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
l.Add(i, nil)
|
|
||||||
}
|
|
||||||
if l.Len() != 128 {
|
|
||||||
panic(fmt.Sprintf("bad len: %v", l.Len()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Expirable LRU cache example
|
|
||||||
===========================
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru/v2/expirable"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// make cache with 10ms TTL and 5 max keys
|
|
||||||
cache := expirable.NewLRU[string, string](5, nil, time.Millisecond*10)
|
|
||||||
|
|
||||||
|
|
||||||
// set value under key1.
|
|
||||||
cache.Add("key1", "val1")
|
|
||||||
|
|
||||||
// get value under key1
|
|
||||||
r, ok := cache.Get("key1")
|
|
||||||
|
|
||||||
// check for OK value
|
|
||||||
if ok {
|
|
||||||
fmt.Printf("value before expiration is found: %v, value: %q\n", ok, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for cache to expire
|
|
||||||
time.Sleep(time.Millisecond * 12)
|
|
||||||
|
|
||||||
// get value under key1 after key expiration
|
|
||||||
r, ok = cache.Get("key1")
|
|
||||||
fmt.Printf("value after expiration is found: %v, value: %q\n", ok, r)
|
|
||||||
|
|
||||||
// set value under key2, would evict old entry because it is already expired.
|
|
||||||
cache.Add("key2", "val2")
|
|
||||||
|
|
||||||
fmt.Printf("Cache len: %d\n", cache.Len())
|
|
||||||
// Output:
|
|
||||||
// value before expiration is found: true, value: "val1"
|
|
||||||
// value after expiration is found: false, value: ""
|
|
||||||
// Cache len: 1
|
|
||||||
}
|
|
||||||
```
|
|
24
vendor/github.com/hashicorp/golang-lru/v2/doc.go
generated
vendored
24
vendor/github.com/hashicorp/golang-lru/v2/doc.go
generated
vendored
|
@ -1,24 +0,0 @@
|
||||||
// Copyright (c) HashiCorp, Inc.
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Package lru provides three different LRU caches of varying sophistication.
|
|
||||||
//
|
|
||||||
// Cache is a simple LRU cache. It is based on the LRU implementation in
|
|
||||||
// groupcache: https://github.com/golang/groupcache/tree/master/lru
|
|
||||||
//
|
|
||||||
// TwoQueueCache tracks frequently used and recently used entries separately.
|
|
||||||
// This avoids a burst of accesses from taking out frequently used entries, at
|
|
||||||
// the cost of about 2x computational overhead and some extra bookkeeping.
|
|
||||||
//
|
|
||||||
// ARCCache is an adaptive replacement cache. It tracks recent evictions as well
|
|
||||||
// as recent usage in both the frequent and recent caches. Its computational
|
|
||||||
// overhead is comparable to TwoQueueCache, but the memory overhead is linear
|
|
||||||
// with the size of the cache.
|
|
||||||
//
|
|
||||||
// ARC has been patented by IBM, so do not use it if that is problematic for
|
|
||||||
// your program. For this reason, it is in a separate go module contained within
|
|
||||||
// this repository.
|
|
||||||
//
|
|
||||||
// All caches in this package take locks while operating, and are therefore
|
|
||||||
// thread-safe for consumers.
|
|
||||||
package lru
|
|
142
vendor/github.com/hashicorp/golang-lru/v2/internal/list.go
generated
vendored
142
vendor/github.com/hashicorp/golang-lru/v2/internal/list.go
generated
vendored
|
@ -1,142 +0,0 @@
|
||||||
// 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_list file.
|
|
||||||
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// Entry is an LRU Entry
|
|
||||||
type Entry[K comparable, V any] struct {
|
|
||||||
// Next and previous pointers in the doubly-linked list of elements.
|
|
||||||
// To simplify the implementation, internally a list l is implemented
|
|
||||||
// as a ring, such that &l.root is both the next element of the last
|
|
||||||
// list element (l.Back()) and the previous element of the first list
|
|
||||||
// element (l.Front()).
|
|
||||||
next, prev *Entry[K, V]
|
|
||||||
|
|
||||||
// The list to which this element belongs.
|
|
||||||
list *LruList[K, V]
|
|
||||||
|
|
||||||
// The LRU Key of this element.
|
|
||||||
Key K
|
|
||||||
|
|
||||||
// The Value stored with this element.
|
|
||||||
Value V
|
|
||||||
|
|
||||||
// The time this element would be cleaned up, optional
|
|
||||||
ExpiresAt time.Time
|
|
||||||
|
|
||||||
// The expiry bucket item was put in, optional
|
|
||||||
ExpireBucket uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrevEntry returns the previous list element or nil.
|
|
||||||
func (e *Entry[K, V]) PrevEntry() *Entry[K, V] {
|
|
||||||
if p := e.prev; e.list != nil && p != &e.list.root {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LruList represents a doubly linked list.
|
|
||||||
// The zero Value for LruList is an empty list ready to use.
|
|
||||||
type LruList[K comparable, V any] struct {
|
|
||||||
root Entry[K, V] // sentinel list element, only &root, root.prev, and root.next are used
|
|
||||||
len int // current list Length excluding (this) sentinel element
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes or clears list l.
|
|
||||||
func (l *LruList[K, V]) Init() *LruList[K, V] {
|
|
||||||
l.root.next = &l.root
|
|
||||||
l.root.prev = &l.root
|
|
||||||
l.len = 0
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewList returns an initialized list.
|
|
||||||
func NewList[K comparable, V any]() *LruList[K, V] { return new(LruList[K, V]).Init() }
|
|
||||||
|
|
||||||
// Length returns the number of elements of list l.
|
|
||||||
// The complexity is O(1).
|
|
||||||
func (l *LruList[K, V]) Length() int { return l.len }
|
|
||||||
|
|
||||||
// Back returns the last element of list l or nil if the list is empty.
|
|
||||||
func (l *LruList[K, V]) Back() *Entry[K, V] {
|
|
||||||
if l.len == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return l.root.prev
|
|
||||||
}
|
|
||||||
|
|
||||||
// lazyInit lazily initializes a zero List Value.
|
|
||||||
func (l *LruList[K, V]) lazyInit() {
|
|
||||||
if l.root.next == nil {
|
|
||||||
l.Init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert inserts e after at, increments l.len, and returns e.
|
|
||||||
func (l *LruList[K, V]) insert(e, at *Entry[K, V]) *Entry[K, V] {
|
|
||||||
e.prev = at
|
|
||||||
e.next = at.next
|
|
||||||
e.prev.next = e
|
|
||||||
e.next.prev = e
|
|
||||||
e.list = l
|
|
||||||
l.len++
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertValue is a convenience wrapper for insert(&Entry{Value: v, ExpiresAt: ExpiresAt}, at).
|
|
||||||
func (l *LruList[K, V]) insertValue(k K, v V, expiresAt time.Time, at *Entry[K, V]) *Entry[K, V] {
|
|
||||||
return l.insert(&Entry[K, V]{Value: v, Key: k, ExpiresAt: expiresAt}, at)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes e from its list, decrements l.len
|
|
||||||
func (l *LruList[K, V]) Remove(e *Entry[K, V]) V {
|
|
||||||
e.prev.next = e.next
|
|
||||||
e.next.prev = e.prev
|
|
||||||
e.next = nil // avoid memory leaks
|
|
||||||
e.prev = nil // avoid memory leaks
|
|
||||||
e.list = nil
|
|
||||||
l.len--
|
|
||||||
|
|
||||||
return e.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// move moves e to next to at.
|
|
||||||
func (l *LruList[K, V]) move(e, at *Entry[K, V]) {
|
|
||||||
if e == at {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.prev.next = e.next
|
|
||||||
e.next.prev = e.prev
|
|
||||||
|
|
||||||
e.prev = at
|
|
||||||
e.next = at.next
|
|
||||||
e.prev.next = e
|
|
||||||
e.next.prev = e
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushFront inserts a new element e with value v at the front of list l and returns e.
|
|
||||||
func (l *LruList[K, V]) PushFront(k K, v V) *Entry[K, V] {
|
|
||||||
l.lazyInit()
|
|
||||||
return l.insertValue(k, v, time.Time{}, &l.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushFrontExpirable inserts a new expirable element e with Value v at the front of list l and returns e.
|
|
||||||
func (l *LruList[K, V]) PushFrontExpirable(k K, v V, expiresAt time.Time) *Entry[K, V] {
|
|
||||||
l.lazyInit()
|
|
||||||
return l.insertValue(k, v, expiresAt, &l.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MoveToFront moves element e to the front of list l.
|
|
||||||
// If e is not an element of l, the list is not modified.
|
|
||||||
// The element must not be nil.
|
|
||||||
func (l *LruList[K, V]) MoveToFront(e *Entry[K, V]) {
|
|
||||||
if e.list != l || l.root.next == e {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// see comment in List.Remove about initialization of l
|
|
||||||
l.move(e, &l.root)
|
|
||||||
}
|
|
250
vendor/github.com/hashicorp/golang-lru/v2/lru.go
generated
vendored
250
vendor/github.com/hashicorp/golang-lru/v2/lru.go
generated
vendored
|
@ -1,250 +0,0 @@
|
||||||
// Copyright (c) HashiCorp, Inc.
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package lru
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru/v2/simplelru"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
|
|
||||||
DefaultEvictedBufferSize = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
|
||||||
type Cache[K comparable, V any] struct {
|
|
||||||
lru *simplelru.LRU[K, V]
|
|
||||||
evictedKeys []K
|
|
||||||
evictedVals []V
|
|
||||||
onEvictedCB func(k K, v V)
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates an LRU of the given size.
|
|
||||||
func New[K comparable, V any](size int) (*Cache[K, V], error) {
|
|
||||||
return NewWithEvict[K, V](size, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWithEvict constructs a fixed size cache with the given eviction
|
|
||||||
// callback.
|
|
||||||
func NewWithEvict[K comparable, V any](size int, onEvicted func(key K, value V)) (c *Cache[K, V], err error) {
|
|
||||||
// create a cache with default settings
|
|
||||||
c = &Cache[K, V]{
|
|
||||||
onEvictedCB: onEvicted,
|
|
||||||
}
|
|
||||||
if onEvicted != nil {
|
|
||||||
c.initEvictBuffers()
|
|
||||||
onEvicted = c.onEvicted
|
|
||||||
}
|
|
||||||
c.lru, err = simplelru.NewLRU(size, onEvicted)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache[K, V]) initEvictBuffers() {
|
|
||||||
c.evictedKeys = make([]K, 0, DefaultEvictedBufferSize)
|
|
||||||
c.evictedVals = make([]V, 0, DefaultEvictedBufferSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// onEvicted save evicted key/val and sent in externally registered callback
|
|
||||||
// outside of critical section
|
|
||||||
func (c *Cache[K, V]) onEvicted(k K, v V) {
|
|
||||||
c.evictedKeys = append(c.evictedKeys, k)
|
|
||||||
c.evictedVals = append(c.evictedVals, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
|
||||||
func (c *Cache[K, V]) Purge() {
|
|
||||||
var ks []K
|
|
||||||
var vs []V
|
|
||||||
c.lock.Lock()
|
|
||||||
c.lru.Purge()
|
|
||||||
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
|
|
||||||
ks, vs = c.evictedKeys, c.evictedVals
|
|
||||||
c.initEvictBuffers()
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
// invoke callback outside of critical section
|
|
||||||
if c.onEvictedCB != nil {
|
|
||||||
for i := 0; i < len(ks); i++ {
|
|
||||||
c.onEvictedCB(ks[i], vs[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
|
||||||
func (c *Cache[K, V]) Add(key K, value V) (evicted bool) {
|
|
||||||
var k K
|
|
||||||
var v V
|
|
||||||
c.lock.Lock()
|
|
||||||
evicted = c.lru.Add(key, value)
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
k, v = c.evictedKeys[0], c.evictedVals[0]
|
|
||||||
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
c.onEvictedCB(k, v)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
|
||||||
func (c *Cache[K, V]) Get(key K) (value V, ok bool) {
|
|
||||||
c.lock.Lock()
|
|
||||||
value, ok = c.lru.Get(key)
|
|
||||||
c.lock.Unlock()
|
|
||||||
return value, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains checks if a key is in the cache, without updating the
|
|
||||||
// recent-ness or deleting it for being stale.
|
|
||||||
func (c *Cache[K, V]) Contains(key K) bool {
|
|
||||||
c.lock.RLock()
|
|
||||||
containKey := c.lru.Contains(key)
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return containKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Peek returns the key value (or undefined if not found) without updating
|
|
||||||
// the "recently used"-ness of the key.
|
|
||||||
func (c *Cache[K, V]) Peek(key K) (value V, ok bool) {
|
|
||||||
c.lock.RLock()
|
|
||||||
value, ok = c.lru.Peek(key)
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return value, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainsOrAdd checks if a key is in the cache without updating the
|
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
|
||||||
// Returns whether found and whether an eviction occurred.
|
|
||||||
func (c *Cache[K, V]) ContainsOrAdd(key K, value V) (ok, evicted bool) {
|
|
||||||
var k K
|
|
||||||
var v V
|
|
||||||
c.lock.Lock()
|
|
||||||
if c.lru.Contains(key) {
|
|
||||||
c.lock.Unlock()
|
|
||||||
return true, false
|
|
||||||
}
|
|
||||||
evicted = c.lru.Add(key, value)
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
k, v = c.evictedKeys[0], c.evictedVals[0]
|
|
||||||
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
c.onEvictedCB(k, v)
|
|
||||||
}
|
|
||||||
return false, evicted
|
|
||||||
}
|
|
||||||
|
|
||||||
// PeekOrAdd checks if a key is in the cache without updating the
|
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
|
||||||
// Returns whether found and whether an eviction occurred.
|
|
||||||
func (c *Cache[K, V]) PeekOrAdd(key K, value V) (previous V, ok, evicted bool) {
|
|
||||||
var k K
|
|
||||||
var v V
|
|
||||||
c.lock.Lock()
|
|
||||||
previous, ok = c.lru.Peek(key)
|
|
||||||
if ok {
|
|
||||||
c.lock.Unlock()
|
|
||||||
return previous, true, false
|
|
||||||
}
|
|
||||||
evicted = c.lru.Add(key, value)
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
k, v = c.evictedKeys[0], c.evictedVals[0]
|
|
||||||
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && evicted {
|
|
||||||
c.onEvictedCB(k, v)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
|
||||||
func (c *Cache[K, V]) Remove(key K) (present bool) {
|
|
||||||
var k K
|
|
||||||
var v V
|
|
||||||
c.lock.Lock()
|
|
||||||
present = c.lru.Remove(key)
|
|
||||||
if c.onEvictedCB != nil && present {
|
|
||||||
k, v = c.evictedKeys[0], c.evictedVals[0]
|
|
||||||
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && present {
|
|
||||||
c.onEvictedCB(k, v)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize changes the cache size.
|
|
||||||
func (c *Cache[K, V]) Resize(size int) (evicted int) {
|
|
||||||
var ks []K
|
|
||||||
var vs []V
|
|
||||||
c.lock.Lock()
|
|
||||||
evicted = c.lru.Resize(size)
|
|
||||||
if c.onEvictedCB != nil && evicted > 0 {
|
|
||||||
ks, vs = c.evictedKeys, c.evictedVals
|
|
||||||
c.initEvictBuffers()
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && evicted > 0 {
|
|
||||||
for i := 0; i < len(ks); i++ {
|
|
||||||
c.onEvictedCB(ks[i], vs[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return evicted
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
|
||||||
func (c *Cache[K, V]) RemoveOldest() (key K, value V, ok bool) {
|
|
||||||
var k K
|
|
||||||
var v V
|
|
||||||
c.lock.Lock()
|
|
||||||
key, value, ok = c.lru.RemoveOldest()
|
|
||||||
if c.onEvictedCB != nil && ok {
|
|
||||||
k, v = c.evictedKeys[0], c.evictedVals[0]
|
|
||||||
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
if c.onEvictedCB != nil && ok {
|
|
||||||
c.onEvictedCB(k, v)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
|
||||||
func (c *Cache[K, V]) GetOldest() (key K, value V, ok bool) {
|
|
||||||
c.lock.RLock()
|
|
||||||
key, value, ok = c.lru.GetOldest()
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
|
||||||
func (c *Cache[K, V]) Keys() []K {
|
|
||||||
c.lock.RLock()
|
|
||||||
keys := c.lru.Keys()
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns a slice of the values in the cache, from oldest to newest.
|
|
||||||
func (c *Cache[K, V]) Values() []V {
|
|
||||||
c.lock.RLock()
|
|
||||||
values := c.lru.Values()
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of items in the cache.
|
|
||||||
func (c *Cache[K, V]) Len() int {
|
|
||||||
c.lock.RLock()
|
|
||||||
length := c.lru.Len()
|
|
||||||
c.lock.RUnlock()
|
|
||||||
return length
|
|
||||||
}
|
|
29
vendor/github.com/hashicorp/golang-lru/v2/simplelru/LICENSE_list
generated
vendored
29
vendor/github.com/hashicorp/golang-lru/v2/simplelru/LICENSE_list
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
This license applies to simplelru/list.go
|
|
||||||
|
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
177
vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go
generated
vendored
177
vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go
generated
vendored
|
@ -1,177 +0,0 @@
|
||||||
// Copyright (c) HashiCorp, Inc.
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package simplelru
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru/v2/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EvictCallback is used to get a callback when a cache entry is evicted
|
|
||||||
type EvictCallback[K comparable, V any] func(key K, value V)
|
|
||||||
|
|
||||||
// LRU implements a non-thread safe fixed size LRU cache
|
|
||||||
type LRU[K comparable, V any] struct {
|
|
||||||
size int
|
|
||||||
evictList *internal.LruList[K, V]
|
|
||||||
items map[K]*internal.Entry[K, V]
|
|
||||||
onEvict EvictCallback[K, V]
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLRU constructs an LRU of the given size
|
|
||||||
func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V]) (*LRU[K, V], error) {
|
|
||||||
if size <= 0 {
|
|
||||||
return nil, errors.New("must provide a positive size")
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &LRU[K, V]{
|
|
||||||
size: size,
|
|
||||||
evictList: internal.NewList[K, V](),
|
|
||||||
items: make(map[K]*internal.Entry[K, V]),
|
|
||||||
onEvict: onEvict,
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
|
||||||
func (c *LRU[K, V]) Purge() {
|
|
||||||
for k, v := range c.items {
|
|
||||||
if c.onEvict != nil {
|
|
||||||
c.onEvict(k, v.Value)
|
|
||||||
}
|
|
||||||
delete(c.items, k)
|
|
||||||
}
|
|
||||||
c.evictList.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
|
||||||
func (c *LRU[K, V]) Add(key K, value V) (evicted bool) {
|
|
||||||
// Check for existing item
|
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.evictList.MoveToFront(ent)
|
|
||||||
ent.Value = value
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new item
|
|
||||||
ent := c.evictList.PushFront(key, value)
|
|
||||||
c.items[key] = ent
|
|
||||||
|
|
||||||
evict := c.evictList.Length() > c.size
|
|
||||||
// Verify size not exceeded
|
|
||||||
if evict {
|
|
||||||
c.removeOldest()
|
|
||||||
}
|
|
||||||
return evict
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
|
||||||
func (c *LRU[K, V]) Get(key K) (value V, ok bool) {
|
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.evictList.MoveToFront(ent)
|
|
||||||
return ent.Value, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains checks if a key is in the cache, without updating the recent-ness
|
|
||||||
// or deleting it for being stale.
|
|
||||||
func (c *LRU[K, V]) Contains(key K) (ok bool) {
|
|
||||||
_, ok = c.items[key]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Peek returns the key value (or undefined if not found) without updating
|
|
||||||
// the "recently used"-ness of the key.
|
|
||||||
func (c *LRU[K, V]) Peek(key K) (value V, ok bool) {
|
|
||||||
var ent *internal.Entry[K, V]
|
|
||||||
if ent, ok = c.items[key]; ok {
|
|
||||||
return ent.Value, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the provided key from the cache, returning if the
|
|
||||||
// key was contained.
|
|
||||||
func (c *LRU[K, V]) Remove(key K) (present bool) {
|
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.removeElement(ent)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
|
||||||
func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
|
|
||||||
if ent := c.evictList.Back(); ent != nil {
|
|
||||||
c.removeElement(ent)
|
|
||||||
return ent.Key, ent.Value, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
|
||||||
func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
|
|
||||||
if ent := c.evictList.Back(); ent != nil {
|
|
||||||
return ent.Key, ent.Value, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
|
||||||
func (c *LRU[K, V]) Keys() []K {
|
|
||||||
keys := make([]K, c.evictList.Length())
|
|
||||||
i := 0
|
|
||||||
for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() {
|
|
||||||
keys[i] = ent.Key
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns a slice of the values in the cache, from oldest to newest.
|
|
||||||
func (c *LRU[K, V]) Values() []V {
|
|
||||||
values := make([]V, len(c.items))
|
|
||||||
i := 0
|
|
||||||
for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() {
|
|
||||||
values[i] = ent.Value
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of items in the cache.
|
|
||||||
func (c *LRU[K, V]) Len() int {
|
|
||||||
return c.evictList.Length()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize changes the cache size.
|
|
||||||
func (c *LRU[K, V]) Resize(size int) (evicted int) {
|
|
||||||
diff := c.Len() - size
|
|
||||||
if diff < 0 {
|
|
||||||
diff = 0
|
|
||||||
}
|
|
||||||
for i := 0; i < diff; i++ {
|
|
||||||
c.removeOldest()
|
|
||||||
}
|
|
||||||
c.size = size
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeOldest removes the oldest item from the cache.
|
|
||||||
func (c *LRU[K, V]) removeOldest() {
|
|
||||||
if ent := c.evictList.Back(); ent != nil {
|
|
||||||
c.removeElement(ent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeElement is used to remove a given list element from the cache
|
|
||||||
func (c *LRU[K, V]) removeElement(e *internal.Entry[K, V]) {
|
|
||||||
c.evictList.Remove(e)
|
|
||||||
delete(c.items, e.Key)
|
|
||||||
if c.onEvict != nil {
|
|
||||||
c.onEvict(e.Key, e.Value)
|
|
||||||
}
|
|
||||||
}
|
|
46
vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go
generated
vendored
46
vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
// Copyright (c) HashiCorp, Inc.
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Package simplelru provides simple LRU implementation based on build-in container/list.
|
|
||||||
package simplelru
|
|
||||||
|
|
||||||
// LRUCache is the interface for simple LRU cache.
|
|
||||||
type LRUCache[K comparable, V any] interface {
|
|
||||||
// Adds a value to the cache, returns true if an eviction occurred and
|
|
||||||
// updates the "recently used"-ness of the key.
|
|
||||||
Add(key K, value V) bool
|
|
||||||
|
|
||||||
// Returns key's value from the cache and
|
|
||||||
// updates the "recently used"-ness of the key. #value, isFound
|
|
||||||
Get(key K) (value V, ok bool)
|
|
||||||
|
|
||||||
// Checks if a key exists in cache without updating the recent-ness.
|
|
||||||
Contains(key K) (ok bool)
|
|
||||||
|
|
||||||
// Returns key's value without updating the "recently used"-ness of the key.
|
|
||||||
Peek(key K) (value V, ok bool)
|
|
||||||
|
|
||||||
// Removes a key from the cache.
|
|
||||||
Remove(key K) bool
|
|
||||||
|
|
||||||
// Removes the oldest entry from cache.
|
|
||||||
RemoveOldest() (K, V, bool)
|
|
||||||
|
|
||||||
// Returns the oldest entry from the cache. #key, value, isFound
|
|
||||||
GetOldest() (K, V, bool)
|
|
||||||
|
|
||||||
// Returns a slice of the keys in the cache, from oldest to newest.
|
|
||||||
Keys() []K
|
|
||||||
|
|
||||||
// Values returns a slice of the values in the cache, from oldest to newest.
|
|
||||||
Values() []V
|
|
||||||
|
|
||||||
// Returns the number of items in the cache.
|
|
||||||
Len() int
|
|
||||||
|
|
||||||
// Clears all cache entries.
|
|
||||||
Purge()
|
|
||||||
|
|
||||||
// Resizes cache, returning number evicted
|
|
||||||
Resize(int) int
|
|
||||||
}
|
|
27
vendor/modernc.org/gc/v3/GO-LICENSE
generated
vendored
27
vendor/modernc.org/gc/v3/GO-LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
69
vendor/modernc.org/gc/v3/LICENSE
generated
vendored
69
vendor/modernc.org/gc/v3/LICENSE
generated
vendored
|
@ -1,69 +0,0 @@
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (c) 2016 The GC Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the names of the authors nor the names of the
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in this repository contains or may contain
|
|
||||||
|
|
||||||
- copied original code from
|
|
||||||
- code based on original code from
|
|
||||||
- code inspired by original code in
|
|
||||||
|
|
||||||
"The Go Programming Language" project at https://go.googlesource.com/go/.
|
|
||||||
|
|
||||||
Copy of the license of the original code follows below
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
-------------------------------------------------------------------------------
|
|
113
vendor/modernc.org/gc/v3/Makefile
generated
vendored
113
vendor/modernc.org/gc/v3/Makefile
generated
vendored
|
@ -1,113 +0,0 @@
|
||||||
.PHONY: all clean edit editor test test2 back report report2 parser2 benchmarks benchmarks2 mem memgo race nreport build_all_targets
|
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
build_all_targets:
|
|
||||||
GOOS=darwin GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=darwin GOARCH=arm64 go test -c -o /dev/null
|
|
||||||
GOOS=freebsd GOARCH=386 go test -c -o /dev/null
|
|
||||||
GOOS=freebsd GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=freebsd GOARCH=arm go test -c -o /dev/null
|
|
||||||
GOOS=freebsd GOARCH=arm64 go test -c -o /dev/null
|
|
||||||
GOOS=illumos GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=386 go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=arm go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=arm64 go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=ppc64le go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=riscv64 go test -c -o /dev/null
|
|
||||||
GOOS=linux GOARCH=s390x go test -c -o /dev/null
|
|
||||||
GOOS=netbsd GOARCH=386 go test -c -o /dev/null
|
|
||||||
GOOS=netbsd GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=netbsd GOARCH=arm go test -c -o /dev/null
|
|
||||||
GOOS=openbsd GOARCH=386 go test -c -o /dev/null
|
|
||||||
GOOS=openbsd GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=openbsd GOARCH=arm64 go test -c -o /dev/null
|
|
||||||
GOOS=windows GOARCH=386 go test -c -o /dev/null
|
|
||||||
GOOS=windows GOARCH=amd64 go test -c -o /dev/null
|
|
||||||
GOOS=windows GOARCH=arm64 go test -c -o /dev/null
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f cpu.test mem.test *.out
|
|
||||||
go clean
|
|
||||||
|
|
||||||
edit:
|
|
||||||
@touch log
|
|
||||||
@if [ -f "Session.vim" ]; then gvim -S & else gvim -p Makefile all_test.go gc.go & fi
|
|
||||||
|
|
||||||
editor:
|
|
||||||
gofmt -l -s -w *.go
|
|
||||||
go test -c -o /dev/null 2>&1 | tee log-editor
|
|
||||||
|
|
||||||
race:
|
|
||||||
go test -v -failfast -heap -race 2>&1 | tee log-test
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-test || true
|
|
||||||
grep 'FAIL\|TODO' log-test || true
|
|
||||||
|
|
||||||
test:
|
|
||||||
go test -v -failfast -trctodo -exterr -heap 2>&1 | tee log-test
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-test || true
|
|
||||||
grep 'FAIL\|TODO' log-test || true
|
|
||||||
|
|
||||||
test2:
|
|
||||||
go test -v -failfast -trctodo -exterr -src $$HOME/src 2>&1 | tee log-test2
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-test2 || true
|
|
||||||
grep 'FAIL\|TODO' log-test2 || true
|
|
||||||
|
|
||||||
parser2:
|
|
||||||
go test -v -failfast -run TestParser -src $$HOME/src 2>&1 | tee log-parser2
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-parser2 || true
|
|
||||||
grep 'FAIL\|TODO' log-parser2 || true
|
|
||||||
|
|
||||||
back:
|
|
||||||
go test -v -failfast -noback 2>&1 | tee log-back
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-back || true
|
|
||||||
grep 'FAIL\|TODO' log-back || true
|
|
||||||
|
|
||||||
nreport:
|
|
||||||
touch log-nreport
|
|
||||||
cp log-nreport log-nreport0
|
|
||||||
go test -v -failfast -run TestParser -heap -nreport 2>&1 | tee log-nreport
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-report || true
|
|
||||||
grep 'FAIL\|TODO' log-report || true
|
|
||||||
|
|
||||||
report:
|
|
||||||
go test -v -failfast -run TestParser -report 2>&1 | tee log-report
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-report || true
|
|
||||||
grep 'FAIL\|TODO' log-report || true
|
|
||||||
|
|
||||||
report2:
|
|
||||||
go test -v -failfast -run TestParser -src $$HOME/src -report 2>&1 | tee log-report2
|
|
||||||
@git diff testdata/ || true
|
|
||||||
@git status
|
|
||||||
@grep TOTAL log-report2 || true
|
|
||||||
grep 'FAIL\|TODO' log-report2 || true
|
|
||||||
|
|
||||||
|
|
||||||
benchmarks:
|
|
||||||
go test -v -run @ -bench . 2>&1 | tee log-benchmarks
|
|
||||||
|
|
||||||
benchmarks2:
|
|
||||||
go test -v -run @ -bench . -bsrc $$HOME/src 2>&1 | tee log-benchmarks2
|
|
||||||
|
|
||||||
mem:
|
|
||||||
go test -run @ -bench BenchmarkParser -memprofile mem.out
|
|
||||||
go tool pprof --lines --alloc_space *.test mem.out
|
|
||||||
|
|
||||||
memgo:
|
|
||||||
go test -run @ -bench BenchmarkGoParser -memprofile mem.out
|
|
||||||
go tool pprof --lines --alloc_space *.test mem.out
|
|
682
vendor/modernc.org/gc/v3/abi.go
generated
vendored
682
vendor/modernc.org/gc/v3/abi.go
generated
vendored
|
@ -1,682 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 gc // import "modernc.org/gc/v3"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
byteOrders = map[string]binary.ByteOrder{
|
|
||||||
"386": binary.LittleEndian,
|
|
||||||
"amd64": binary.LittleEndian,
|
|
||||||
"arm": binary.LittleEndian,
|
|
||||||
"arm64": binary.LittleEndian,
|
|
||||||
"ppc64le": binary.LittleEndian,
|
|
||||||
"riscv64": binary.LittleEndian,
|
|
||||||
"s390x": binary.BigEndian,
|
|
||||||
}
|
|
||||||
|
|
||||||
abiTypes = map[[2]string]map[Kind]ABIType{
|
|
||||||
// go1.19.1
|
|
||||||
{"freebsd", "386"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"freebsd", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.18.5
|
|
||||||
{"freebsd", "arm"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19
|
|
||||||
{"freebsd", "arm64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"darwin", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"darwin", "arm64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "386"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "arm"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "arm64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "s390x"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "ppc64le"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"linux", "riscv64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.18.3
|
|
||||||
{"netbsd", "386"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.18.3
|
|
||||||
{"netbsd", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.18.3
|
|
||||||
{"netbsd", "arm"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19
|
|
||||||
{"openbsd", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19
|
|
||||||
{"openbsd", "arm64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19
|
|
||||||
{"openbsd", "386"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"windows", "386"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {4, 4, 4},
|
|
||||||
Complex128: {16, 4, 4},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 4, 4},
|
|
||||||
Function: {4, 4, 4},
|
|
||||||
Int: {4, 4, 4},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 4, 4},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {8, 4, 4},
|
|
||||||
Map: {4, 4, 4},
|
|
||||||
Pointer: {4, 4, 4},
|
|
||||||
Slice: {12, 4, 4},
|
|
||||||
String: {8, 4, 4},
|
|
||||||
Uint: {4, 4, 4},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 4, 4},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {4, 4, 4},
|
|
||||||
UnsafePointer: {4, 4, 4},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"windows", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.1
|
|
||||||
{"windows", "arm64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
// go1.19.3
|
|
||||||
{"illumos", "amd64"}: {
|
|
||||||
Bool: {1, 1, 1},
|
|
||||||
Chan: {8, 8, 8},
|
|
||||||
Complex128: {16, 8, 8},
|
|
||||||
Complex64: {8, 4, 4},
|
|
||||||
Float32: {4, 4, 4},
|
|
||||||
Float64: {8, 8, 8},
|
|
||||||
Function: {8, 8, 8},
|
|
||||||
Int: {8, 8, 8},
|
|
||||||
Int16: {2, 2, 2},
|
|
||||||
Int32: {4, 4, 4},
|
|
||||||
Int64: {8, 8, 8},
|
|
||||||
Int8: {1, 1, 1},
|
|
||||||
Interface: {16, 8, 8},
|
|
||||||
Map: {8, 8, 8},
|
|
||||||
Pointer: {8, 8, 8},
|
|
||||||
Slice: {24, 8, 8},
|
|
||||||
String: {16, 8, 8},
|
|
||||||
Uint: {8, 8, 8},
|
|
||||||
Uint16: {2, 2, 2},
|
|
||||||
Uint32: {4, 4, 4},
|
|
||||||
Uint64: {8, 8, 8},
|
|
||||||
Uint8: {1, 1, 1},
|
|
||||||
Uintptr: {8, 8, 8},
|
|
||||||
UnsafePointer: {8, 8, 8},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ABI describes selected parts of the Application Binary Interface.
|
|
||||||
type ABI struct {
|
|
||||||
ByteOrder binary.ByteOrder
|
|
||||||
goarch string
|
|
||||||
goos string
|
|
||||||
Types map[Kind]ABIType
|
|
||||||
}
|
|
||||||
|
|
||||||
type ABIType struct {
|
|
||||||
Size int64
|
|
||||||
Align int64
|
|
||||||
FieldAlign int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewABI creates an ABI based on the os+arch pair.
|
|
||||||
func NewABI(os, arch string) (*ABI, error) {
|
|
||||||
byteOrder, ok := byteOrders[arch]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unsupported arch: %s", arch)
|
|
||||||
}
|
|
||||||
|
|
||||||
types0, ok := abiTypes[[2]string{os, arch}]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("unsupported os/arch: %s/%s", os, arch)
|
|
||||||
}
|
|
||||||
|
|
||||||
types := make(map[Kind]ABIType, len(types0))
|
|
||||||
for k, v := range types0 {
|
|
||||||
types[k] = v
|
|
||||||
}
|
|
||||||
return &ABI{
|
|
||||||
ByteOrder: byteOrder,
|
|
||||||
Types: types,
|
|
||||||
}, nil
|
|
||||||
}
|
|
598
vendor/modernc.org/gc/v3/check.go
generated
vendored
598
vendor/modernc.org/gc/v3/check.go
generated
vendored
|
@ -1,598 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 gc // modernc.org/gc/v3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/constant"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ctx struct {
|
|
||||||
ast *AST
|
|
||||||
cfg *Config
|
|
||||||
errs errList
|
|
||||||
iota int64
|
|
||||||
pkg *Package
|
|
||||||
|
|
||||||
int32 Type // Set by newCtx
|
|
||||||
untypedFloat Type // Set by newCtx
|
|
||||||
untypedInt Type // Set by newCtx
|
|
||||||
untypedString Type // Set by newCtx
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCtx(cfg *Config) (r *ctx) {
|
|
||||||
r = &ctx{
|
|
||||||
cfg: cfg,
|
|
||||||
iota: -1, // -> Invalid
|
|
||||||
}
|
|
||||||
r.int32 = r.newPredeclaredType(znode, Int32)
|
|
||||||
r.untypedFloat = r.newPredeclaredType(znode, UntypedFloat)
|
|
||||||
r.untypedInt = r.newPredeclaredType(znode, UntypedInt)
|
|
||||||
r.untypedString = r.newPredeclaredType(znode, UntypedString)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) err(n Node, msg string, args ...interface{}) {
|
|
||||||
var pos token.Position
|
|
||||||
if n != nil {
|
|
||||||
pos = n.Position()
|
|
||||||
}
|
|
||||||
s := fmt.Sprintf(msg, args...)
|
|
||||||
if trcTODOs && strings.HasPrefix(s, "TODO") {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v: %s (%v)\n", pos, s, origin(2))
|
|
||||||
os.Stderr.Sync()
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case extendedErrors:
|
|
||||||
c.errs.err(pos, "%s (%v: %v: %v)", s, origin(4), origin(3), origin(2))
|
|
||||||
default:
|
|
||||||
c.errs.err(pos, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) isBuiltin() bool { return c.pkg.Scope.kind == UniverseScope }
|
|
||||||
func (c *ctx) isUnsafe() bool { return c.pkg.isUnsafe }
|
|
||||||
|
|
||||||
func (c *ctx) lookup(sc *Scope, id Token) (pkg *Package, in *Scope, r named) {
|
|
||||||
sc0 := sc
|
|
||||||
pkg = c.pkg
|
|
||||||
for {
|
|
||||||
switch in, nm := sc.lookup(id); x := nm.n.(type) {
|
|
||||||
case *TypeDefNode:
|
|
||||||
if sc.kind == UniverseScope {
|
|
||||||
if sc0.kind != UniverseScope && token.IsExported(id.Src()) {
|
|
||||||
// trc("%v: %q %v %v", id.Position(), id.Src(), sc0.kind, sc.kind)
|
|
||||||
return nil, nil, r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return x.pkg, in, nm
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %q %T", id.Position(), id.Src(), x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Package) check(c *ctx) (err error) {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.pkg = n
|
|
||||||
// trc("PKG %q", n.ImportPath)
|
|
||||||
// defer func() { trc("PKG %q -> err: %v", n.ImportPath, err) }()
|
|
||||||
for _, v := range n.GoFiles {
|
|
||||||
path := filepath.Join(n.FSPath, v.Name())
|
|
||||||
n.AST[path].check(c)
|
|
||||||
}
|
|
||||||
return c.errs.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *AST) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ast = n
|
|
||||||
n.SourceFile.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *SourceFileNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.PackageClause.check(c)
|
|
||||||
for l := n.ImportDeclList; l != nil; l = l.List {
|
|
||||||
l.ImportDecl.check(c)
|
|
||||||
}
|
|
||||||
for l := n.TopLevelDeclList; l != nil; l = l.List {
|
|
||||||
switch x := l.TopLevelDecl.(type) {
|
|
||||||
case *TypeDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
case *ConstDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
case *VarDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
case *FunctionDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
case *MethodDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", x.Position(), x, x.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Receiver.check(c)
|
|
||||||
n.Signature.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.isBuiltin() {
|
|
||||||
switch nm := n.FunctionName.IDENT.Src(); nm {
|
|
||||||
case
|
|
||||||
"append",
|
|
||||||
"cap",
|
|
||||||
"close",
|
|
||||||
"complex",
|
|
||||||
"copy",
|
|
||||||
"delete",
|
|
||||||
"imag",
|
|
||||||
"len",
|
|
||||||
"make",
|
|
||||||
"new",
|
|
||||||
"panic",
|
|
||||||
"print",
|
|
||||||
"println",
|
|
||||||
"real",
|
|
||||||
"recover",
|
|
||||||
|
|
||||||
// Go 1.21
|
|
||||||
"max",
|
|
||||||
"min",
|
|
||||||
"clear":
|
|
||||||
|
|
||||||
n.Signature.t = c.newPredeclaredType(n, Function)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %q %s", n.Position(), nm, n.Source(false)))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Signature.check(c)
|
|
||||||
if n.TypeParameters != nil {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *SignatureNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
return n.Type()
|
|
||||||
}
|
|
||||||
|
|
||||||
in := n.Parameters.check(c)
|
|
||||||
out := n.Result.check(c)
|
|
||||||
return n.setType(newTupleType(n.Parameters, []Type{in, out}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ResultNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case n.Parameters != nil:
|
|
||||||
return n.Parameters.check(c)
|
|
||||||
case n.TypeNode != nil:
|
|
||||||
return n.TypeNode.check(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParametersNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
r := newTupleType(n, nil)
|
|
||||||
for l := n.ParameterDeclList; l != nil; l = l.List {
|
|
||||||
r.Types = append(r.Types, l.ParameterDecl.check(c)...)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParameterDeclNode) check(c *ctx) (r []Type) {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t := n.TypeNode.check(c)
|
|
||||||
for l := n.IdentifierList; l != nil; l = l.List {
|
|
||||||
r = append(r, t)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *VarDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x := n.VarSpec.(type) {
|
|
||||||
case *VarSpecNode:
|
|
||||||
x.check(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *VarSpecNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.isBuiltin() {
|
|
||||||
switch nm := n.IDENT.Src(); nm {
|
|
||||||
case "nil":
|
|
||||||
n.TypeNode = c.newPredeclaredType(n, UntypedNil)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %q", n.IDENT.Position(), nm))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.TypeNode != nil {
|
|
||||||
c.err(n, "TODO %v", n.TypeNode.Source(false))
|
|
||||||
}
|
|
||||||
var e []Expression
|
|
||||||
for l := n.ExpressionList; l != nil; l = l.List {
|
|
||||||
e = append(e, l.Expression.checkExpr(c))
|
|
||||||
}
|
|
||||||
switch len(e) {
|
|
||||||
default:
|
|
||||||
panic(todo("", len(e)))
|
|
||||||
c.err(n, "TODO %v", len(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ConstDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x := n.ConstSpec.(type) {
|
|
||||||
case *ConstSpecListNode:
|
|
||||||
var prev Node
|
|
||||||
for l := x; l != nil; l = l.List {
|
|
||||||
switch y := l.ConstSpec.(type) {
|
|
||||||
case *ConstSpecNode:
|
|
||||||
y.check(c, prev)
|
|
||||||
if y.Expression != nil || y.TypeNode != nil {
|
|
||||||
prev = y
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), y, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ConstSpecNode:
|
|
||||||
x.check(c, nil)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ConstSpecNode) check(c *ctx, prev Node) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
panic(todo("")) // report recursive
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
if c.isBuiltin() {
|
|
||||||
switch n.IDENT.Src() {
|
|
||||||
case "true":
|
|
||||||
switch x := n.Expression.(type) {
|
|
||||||
case *BinaryExpressionNode:
|
|
||||||
x.setValue(trueVal)
|
|
||||||
x.setType(c.newPredeclaredType(x, UntypedBool))
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
case "false":
|
|
||||||
switch x := n.Expression.(type) {
|
|
||||||
case *BinaryExpressionNode:
|
|
||||||
x.setValue(falseVal)
|
|
||||||
x.setType(c.newPredeclaredType(x, UntypedBool))
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
case "iota":
|
|
||||||
switch x := n.Expression.(type) {
|
|
||||||
case *BasicLitNode:
|
|
||||||
// ok
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("", n.Position(), n.Source(false)))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
save := c.iota
|
|
||||||
c.iota = n.iota
|
|
||||||
|
|
||||||
defer func() { c.iota = save }()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case n.Expression != nil:
|
|
||||||
n.Expression = n.Expression.checkExpr(c)
|
|
||||||
if n.TypeNode == nil {
|
|
||||||
n.TypeNode = n.Expression.Type()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t := n.TypeNode.check(c)
|
|
||||||
trc("", t)
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
default:
|
|
||||||
// var e Expression
|
|
||||||
// var pe *Expression
|
|
||||||
// switch {
|
|
||||||
// case n.Expression != nil:
|
|
||||||
// e = n.Expression
|
|
||||||
// pe = &n.Expression
|
|
||||||
// default:
|
|
||||||
// switch x := prev.(type) {
|
|
||||||
// case *ConstSpecNode:
|
|
||||||
// e = x.Expression.clone()
|
|
||||||
// pe = &e
|
|
||||||
// default:
|
|
||||||
// panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ev, et := e.checkExpr(c, pe)
|
|
||||||
// e = *pe
|
|
||||||
// if ev.Kind() == constant.Unknown {
|
|
||||||
// c.err(e, "%s is not a constant", e.Source(false))
|
|
||||||
// n.t = Invalid
|
|
||||||
// n.setValue(unknown)
|
|
||||||
// return Invalid
|
|
||||||
// }
|
|
||||||
// switch {
|
|
||||||
// case n.t == nil:
|
|
||||||
// n.t = et
|
|
||||||
// default:
|
|
||||||
|
|
||||||
// c.err(n.Expression, "cannot assign %v (type %v) to type %v", ev, et, n.Type())
|
|
||||||
// return Invalid
|
|
||||||
// } else {
|
|
||||||
// n.setValue(convertValue(c, e, ev, n.Type()))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return n.Type()
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for l := n.TypeSpecList; l != nil; l = l.List {
|
|
||||||
switch x := l.TypeSpec.(type) {
|
|
||||||
case *TypeDefNode:
|
|
||||||
switch {
|
|
||||||
case c.isBuiltin():
|
|
||||||
x.pkg = c.pkg
|
|
||||||
switch nm := x.IDENT.Src(); nm {
|
|
||||||
case "bool":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Bool)
|
|
||||||
case "int":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Int)
|
|
||||||
c.cfg.int = x.TypeNode
|
|
||||||
case "int8":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Int8)
|
|
||||||
case "int16":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Int16)
|
|
||||||
case "int32":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Int32)
|
|
||||||
case "int64":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Int64)
|
|
||||||
case "uint":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uint)
|
|
||||||
c.cfg.uint = x.TypeNode
|
|
||||||
case "uint8":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uint8)
|
|
||||||
case "uint16":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uint16)
|
|
||||||
case "uint32":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uint32)
|
|
||||||
case "uint64":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uint64)
|
|
||||||
case "uintptr":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Uintptr)
|
|
||||||
case "string":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, String)
|
|
||||||
case "float32":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Float32)
|
|
||||||
case "float64":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Float64)
|
|
||||||
case "complex64":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Complex64)
|
|
||||||
case "complex128":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Complex128)
|
|
||||||
case "comparable":
|
|
||||||
x.TypeNode = c.newPredeclaredType(x, Interface)
|
|
||||||
case "error":
|
|
||||||
x.check(c)
|
|
||||||
default:
|
|
||||||
if token.IsExported(nm) {
|
|
||||||
delete(c.pkg.Scope.nodes, nm)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(todo("%v: %T %s", x.Position(), x, x.Source(false)))
|
|
||||||
}
|
|
||||||
case c.isUnsafe():
|
|
||||||
switch nm := x.IDENT.Src(); nm {
|
|
||||||
case "ArbitraryType", "IntegerType", "Pointer":
|
|
||||||
x.TypeNode.check(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", x.Position(), x, x.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
switch {
|
|
||||||
case x.TypeParameters != nil:
|
|
||||||
panic(todo("%v: %T %s", x.Position(), x, x.Source(false)))
|
|
||||||
default:
|
|
||||||
x.check(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *AliasDeclNode:
|
|
||||||
x.check(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", x.Position(), x, x.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *AliasDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.TypeNode.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ImportDeclNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type result struct {
|
|
||||||
spec *ImportSpecNode
|
|
||||||
pkg *Package
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
var a []*result
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for l := n.ImportSpecList; l != nil; l = l.List {
|
|
||||||
r := &result{}
|
|
||||||
a = append(a, r)
|
|
||||||
wg.Add(1)
|
|
||||||
go func(isln *ImportSpecListNode, r *result) {
|
|
||||||
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
r.spec = isln.ImportSpec
|
|
||||||
r.pkg, r.err = r.spec.check(c)
|
|
||||||
r.spec.pkg = r.pkg
|
|
||||||
}(l, r)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
fileScope := c.ast.FileScope
|
|
||||||
pkgScope := c.pkg.Scope
|
|
||||||
for _, v := range a {
|
|
||||||
switch x := v.err.(type) {
|
|
||||||
case nil:
|
|
||||||
// ok
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T: %s", v.spec.Position(), x, x))
|
|
||||||
}
|
|
||||||
if c.pkg.ImportPath == "builtin" && v.spec.ImportPath.Src() == `"cmp"` {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ex := fileScope.declare(v.pkg.Name, v.spec, 0, nil, true); {
|
|
||||||
case ex.declTok.IsValid():
|
|
||||||
c.err(n, "%s redeclared, previous declaration at %v:", v.pkg.Name.Src(), ex.declTok.Position())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ex := pkgScope.declare(v.pkg.Name, v.spec, 0, nil, true); {
|
|
||||||
case ex.declTok.IsValid():
|
|
||||||
c.err(n, "%s redeclared, previous declaration at %v:", v.pkg.Name.Src(), ex.declTok.Position())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ImportSpecNode) check(c *ctx) (*Package, error) {
|
|
||||||
if n == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case n.PERIOD.IsValid():
|
|
||||||
panic(todo("", n.Position(), n.Source(false)))
|
|
||||||
case n.PackageName.IsValid():
|
|
||||||
//TODO version
|
|
||||||
check := c.pkg.typeCheck
|
|
||||||
switch check {
|
|
||||||
case TypeCheckAll:
|
|
||||||
// nop
|
|
||||||
default:
|
|
||||||
panic(todo("", check))
|
|
||||||
}
|
|
||||||
return c.cfg.newPackage(c.pkg.FSPath, constant.StringVal(n.ImportPath.Value()), "", nil, false, check, c.pkg.guard)
|
|
||||||
default:
|
|
||||||
//TODO version
|
|
||||||
check := c.pkg.typeCheck
|
|
||||||
switch check {
|
|
||||||
case TypeCheckAll:
|
|
||||||
// nop
|
|
||||||
default:
|
|
||||||
if c.pkg.ImportPath == "builtin" && n.ImportPath.Src() == `"cmp"` {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c.cfg.newPackage(c.pkg.FSPath, constant.StringVal(n.ImportPath.Value()), "", nil, false, check, c.pkg.guard)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PackageClauseNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nm := n.PackageName.Src()
|
|
||||||
if ex := c.pkg.Name; ex.IsValid() && ex.Src() != nm {
|
|
||||||
c.err(n.PackageName, "found different packages %q and %q", ex.Src(), nm)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.pkg.Name = n.PackageName
|
|
||||||
}
|
|
559
vendor/modernc.org/gc/v3/etc.go
generated
vendored
559
vendor/modernc.org/gc/v3/etc.go
generated
vendored
|
@ -1,559 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 gc // modernc.org/gc/v3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"math"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/dustin/go-humanize"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The list of tokens.
|
|
||||||
const (
|
|
||||||
// Special tokens
|
|
||||||
ILLEGAL = token.ILLEGAL
|
|
||||||
EOF = token.EOF
|
|
||||||
COMMENT = token.COMMENT
|
|
||||||
|
|
||||||
// Identifiers and basic type literals
|
|
||||||
// (these tokens stand for classes of literals)
|
|
||||||
IDENT = token.IDENT // main
|
|
||||||
INT = token.INT // 12345
|
|
||||||
FLOAT = token.FLOAT // 123.45
|
|
||||||
IMAG = token.IMAG // 123.45i
|
|
||||||
CHAR = token.CHAR // 'a'
|
|
||||||
STRING = token.STRING // "abc"
|
|
||||||
|
|
||||||
// Operators and delimiters
|
|
||||||
ADD = token.ADD // +
|
|
||||||
SUB = token.SUB // -
|
|
||||||
MUL = token.MUL // *
|
|
||||||
QUO = token.QUO // /
|
|
||||||
REM = token.REM // %
|
|
||||||
|
|
||||||
AND = token.AND // &
|
|
||||||
OR = token.OR // |
|
|
||||||
XOR = token.XOR // ^
|
|
||||||
SHL = token.SHL // <<
|
|
||||||
SHR = token.SHR // >>
|
|
||||||
AND_NOT = token.AND_NOT // &^
|
|
||||||
|
|
||||||
ADD_ASSIGN = token.ADD_ASSIGN // +=
|
|
||||||
SUB_ASSIGN = token.SUB_ASSIGN // -=
|
|
||||||
MUL_ASSIGN = token.MUL_ASSIGN // *=
|
|
||||||
QUO_ASSIGN = token.QUO_ASSIGN // /=
|
|
||||||
REM_ASSIGN = token.REM_ASSIGN // %=
|
|
||||||
|
|
||||||
AND_ASSIGN = token.AND_ASSIGN // &=
|
|
||||||
OR_ASSIGN = token.OR_ASSIGN // |=
|
|
||||||
XOR_ASSIGN = token.XOR_ASSIGN // ^=
|
|
||||||
SHL_ASSIGN = token.SHL_ASSIGN // <<=
|
|
||||||
SHR_ASSIGN = token.SHR_ASSIGN // >>=
|
|
||||||
AND_NOT_ASSIGN = token.AND_NOT_ASSIGN // &^=
|
|
||||||
|
|
||||||
LAND = token.LAND // &&
|
|
||||||
LOR = token.LOR // ||
|
|
||||||
ARROW = token.ARROW // <-
|
|
||||||
INC = token.INC // ++
|
|
||||||
DEC = token.DEC // --
|
|
||||||
|
|
||||||
EQL = token.EQL // ==
|
|
||||||
LSS = token.LSS // <
|
|
||||||
GTR = token.GTR // >
|
|
||||||
ASSIGN = token.ASSIGN // =
|
|
||||||
NOT = token.NOT // !
|
|
||||||
|
|
||||||
NEQ = token.NEQ // !=
|
|
||||||
LEQ = token.LEQ // <=
|
|
||||||
GEQ = token.GEQ // >=
|
|
||||||
DEFINE = token.DEFINE // :=
|
|
||||||
ELLIPSIS = token.ELLIPSIS // ...
|
|
||||||
|
|
||||||
LPAREN = token.LPAREN // (
|
|
||||||
LBRACK = token.LBRACK // [
|
|
||||||
LBRACE = token.LBRACE // {
|
|
||||||
COMMA = token.COMMA // ,
|
|
||||||
PERIOD = token.PERIOD // .
|
|
||||||
|
|
||||||
RPAREN = token.RPAREN // )
|
|
||||||
RBRACK = token.RBRACK // ]
|
|
||||||
RBRACE = token.RBRACE // }
|
|
||||||
SEMICOLON = token.SEMICOLON // ;
|
|
||||||
COLON = token.COLON // :
|
|
||||||
|
|
||||||
// Keywords
|
|
||||||
BREAK = token.BREAK
|
|
||||||
CASE = token.CASE
|
|
||||||
CHAN = token.CHAN
|
|
||||||
CONST = token.CONST
|
|
||||||
CONTINUE = token.CONTINUE
|
|
||||||
|
|
||||||
DEFAULT = token.DEFAULT
|
|
||||||
DEFER = token.DEFER
|
|
||||||
ELSE = token.ELSE
|
|
||||||
FALLTHROUGH = token.FALLTHROUGH
|
|
||||||
FOR = token.FOR
|
|
||||||
|
|
||||||
FUNC = token.FUNC
|
|
||||||
GO = token.GO
|
|
||||||
GOTO = token.GOTO
|
|
||||||
IF = token.IF
|
|
||||||
IMPORT = token.IMPORT
|
|
||||||
|
|
||||||
INTERFACE = token.INTERFACE
|
|
||||||
MAP = token.MAP
|
|
||||||
PACKAGE = token.PACKAGE
|
|
||||||
RANGE = token.RANGE
|
|
||||||
RETURN = token.RETURN
|
|
||||||
|
|
||||||
SELECT = token.SELECT
|
|
||||||
STRUCT = token.STRUCT
|
|
||||||
SWITCH = token.SWITCH
|
|
||||||
TYPE = token.TYPE
|
|
||||||
VAR = token.VAR
|
|
||||||
|
|
||||||
// additional tokens, handled in an ad-hoc manner
|
|
||||||
TILDE = token.TILDE
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
trcTODOs bool
|
|
||||||
extendedErrors bool
|
|
||||||
)
|
|
||||||
|
|
||||||
// origin returns caller's short position, skipping skip frames.
|
|
||||||
func origin(skip int) string {
|
|
||||||
pc, fn, fl, _ := runtime.Caller(skip)
|
|
||||||
f := runtime.FuncForPC(pc)
|
|
||||||
var fns string
|
|
||||||
if f != nil {
|
|
||||||
fns = f.Name()
|
|
||||||
if x := strings.LastIndex(fns, "."); x > 0 {
|
|
||||||
fns = fns[x+1:]
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(fns, "func") {
|
|
||||||
num := true
|
|
||||||
for _, c := range fns[len("func"):] {
|
|
||||||
if c < '0' || c > '9' {
|
|
||||||
num = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if num {
|
|
||||||
return origin(skip + 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s:%d:%s", filepath.Base(fn), fl, fns)
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo prints and returns caller's position and an optional message tagged with TODO. Output goes to stderr.
|
|
||||||
//
|
|
||||||
//lint:ignore U1000 whatever
|
|
||||||
func todo(s string, args ...interface{}) string {
|
|
||||||
switch {
|
|
||||||
case s == "":
|
|
||||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
|
||||||
default:
|
|
||||||
s = fmt.Sprintf(s, args...)
|
|
||||||
}
|
|
||||||
r := fmt.Sprintf("%s\n\tTODO (%s)", origin(2), s)
|
|
||||||
// fmt.Fprintf(os.Stderr, "%s\n", r)
|
|
||||||
// os.Stdout.Sync()
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// trc prints and returns caller's position and an optional message tagged with TRC. Output goes to stderr.
|
|
||||||
//
|
|
||||||
//lint:ignore U1000 whatever
|
|
||||||
func trc(s string, args ...interface{}) string {
|
|
||||||
switch {
|
|
||||||
case s == "":
|
|
||||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
|
||||||
default:
|
|
||||||
s = fmt.Sprintf(s, args...)
|
|
||||||
}
|
|
||||||
r := fmt.Sprintf("%s: TRC (%s)", origin(2), s)
|
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", r)
|
|
||||||
os.Stderr.Sync()
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractPos(s string) (p token.Position, ok bool) {
|
|
||||||
var prefix string
|
|
||||||
if len(s) > 1 && s[1] == ':' { // c:\foo
|
|
||||||
prefix = s[:2]
|
|
||||||
s = s[2:]
|
|
||||||
}
|
|
||||||
// "testdata/parser/bug/001.c:1193: ..."
|
|
||||||
a := strings.Split(s, ":")
|
|
||||||
// ["testdata/parser/bug/001.c" "1193" "..."]
|
|
||||||
if len(a) < 2 {
|
|
||||||
return p, false
|
|
||||||
}
|
|
||||||
|
|
||||||
line, err := strconv.Atoi(a[1])
|
|
||||||
if err != nil {
|
|
||||||
return p, false
|
|
||||||
}
|
|
||||||
|
|
||||||
col, err := strconv.Atoi(a[2])
|
|
||||||
if err != nil {
|
|
||||||
col = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return token.Position{Filename: prefix + a[0], Line: line, Column: col}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorf constructs an error value. If extendedErrors is true, the error will
|
|
||||||
// contain its origin.
|
|
||||||
func errorf(s string, args ...interface{}) error {
|
|
||||||
switch {
|
|
||||||
case s == "":
|
|
||||||
s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
|
|
||||||
default:
|
|
||||||
s = fmt.Sprintf(s, args...)
|
|
||||||
}
|
|
||||||
if trcTODOs && strings.HasPrefix(s, "TODO") {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s (%v)\n", s, origin(2))
|
|
||||||
os.Stderr.Sync()
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case extendedErrors:
|
|
||||||
return fmt.Errorf("%s (%v: %v: %v)", s, origin(4), origin(3), origin(2))
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("%s", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func tokSource(t token.Token) string {
|
|
||||||
switch t {
|
|
||||||
case ILLEGAL:
|
|
||||||
return "ILLEGAL"
|
|
||||||
case EOF:
|
|
||||||
return "EOF"
|
|
||||||
case COMMENT:
|
|
||||||
return "COMMENT"
|
|
||||||
case IDENT:
|
|
||||||
return "IDENT"
|
|
||||||
case INT:
|
|
||||||
return "INT"
|
|
||||||
case FLOAT:
|
|
||||||
return "FLOAT"
|
|
||||||
case IMAG:
|
|
||||||
return "IMAG"
|
|
||||||
case CHAR:
|
|
||||||
return "CHAR"
|
|
||||||
case STRING:
|
|
||||||
return "STRING"
|
|
||||||
case ADD:
|
|
||||||
return "ADD"
|
|
||||||
case SUB:
|
|
||||||
return "SUB"
|
|
||||||
case MUL:
|
|
||||||
return "MUL"
|
|
||||||
case QUO:
|
|
||||||
return "QUO"
|
|
||||||
case REM:
|
|
||||||
return "REM"
|
|
||||||
case AND:
|
|
||||||
return "AND"
|
|
||||||
case OR:
|
|
||||||
return "OR"
|
|
||||||
case XOR:
|
|
||||||
return "XOR"
|
|
||||||
case SHL:
|
|
||||||
return "SHL"
|
|
||||||
case SHR:
|
|
||||||
return "SHR"
|
|
||||||
case AND_NOT:
|
|
||||||
return "AND_NOT"
|
|
||||||
case ADD_ASSIGN:
|
|
||||||
return "ADD_ASSIGN"
|
|
||||||
case SUB_ASSIGN:
|
|
||||||
return "SUB_ASSIGN"
|
|
||||||
case MUL_ASSIGN:
|
|
||||||
return "MUL_ASSIGN"
|
|
||||||
case QUO_ASSIGN:
|
|
||||||
return "QUO_ASSIGN"
|
|
||||||
case REM_ASSIGN:
|
|
||||||
return "REM_ASSIGN"
|
|
||||||
case AND_ASSIGN:
|
|
||||||
return "AND_ASSIGN"
|
|
||||||
case OR_ASSIGN:
|
|
||||||
return "OR_ASSIGN"
|
|
||||||
case XOR_ASSIGN:
|
|
||||||
return "XOR_ASSIGN"
|
|
||||||
case SHL_ASSIGN:
|
|
||||||
return "SHL_ASSIGN"
|
|
||||||
case SHR_ASSIGN:
|
|
||||||
return "SHR_ASSIGN"
|
|
||||||
case AND_NOT_ASSIGN:
|
|
||||||
return "AND_NOT_ASSIGN"
|
|
||||||
case LAND:
|
|
||||||
return "LAND"
|
|
||||||
case LOR:
|
|
||||||
return "LOR"
|
|
||||||
case ARROW:
|
|
||||||
return "ARROW"
|
|
||||||
case INC:
|
|
||||||
return "INC"
|
|
||||||
case DEC:
|
|
||||||
return "DEC"
|
|
||||||
case EQL:
|
|
||||||
return "EQL"
|
|
||||||
case LSS:
|
|
||||||
return "LSS"
|
|
||||||
case GTR:
|
|
||||||
return "GTR"
|
|
||||||
case ASSIGN:
|
|
||||||
return "ASSIGN"
|
|
||||||
case NOT:
|
|
||||||
return "NOT"
|
|
||||||
case NEQ:
|
|
||||||
return "NEQ"
|
|
||||||
case LEQ:
|
|
||||||
return "LEQ"
|
|
||||||
case GEQ:
|
|
||||||
return "GEQ"
|
|
||||||
case DEFINE:
|
|
||||||
return "DEFINE"
|
|
||||||
case ELLIPSIS:
|
|
||||||
return "ELLIPSIS"
|
|
||||||
case LPAREN:
|
|
||||||
return "LPAREN"
|
|
||||||
case LBRACK:
|
|
||||||
return "LBRACK"
|
|
||||||
case LBRACE:
|
|
||||||
return "LBRACE"
|
|
||||||
case COMMA:
|
|
||||||
return "COMMA"
|
|
||||||
case PERIOD:
|
|
||||||
return "PERIOD"
|
|
||||||
case RPAREN:
|
|
||||||
return "RPAREN"
|
|
||||||
case RBRACK:
|
|
||||||
return "RBRACK"
|
|
||||||
case RBRACE:
|
|
||||||
return "RBRACE"
|
|
||||||
case SEMICOLON:
|
|
||||||
return "SEMICOLON"
|
|
||||||
case COLON:
|
|
||||||
return "COLON"
|
|
||||||
case BREAK:
|
|
||||||
return "BREAK"
|
|
||||||
case CASE:
|
|
||||||
return "CASE"
|
|
||||||
case CHAN:
|
|
||||||
return "CHAN"
|
|
||||||
case CONST:
|
|
||||||
return "CONST"
|
|
||||||
case CONTINUE:
|
|
||||||
return "CONTINUE"
|
|
||||||
case DEFAULT:
|
|
||||||
return "DEFAULT"
|
|
||||||
case DEFER:
|
|
||||||
return "DEFER"
|
|
||||||
case ELSE:
|
|
||||||
return "ELSE"
|
|
||||||
case FALLTHROUGH:
|
|
||||||
return "FALLTHROUGH"
|
|
||||||
case FOR:
|
|
||||||
return "FOR"
|
|
||||||
case FUNC:
|
|
||||||
return "FUNC"
|
|
||||||
case GO:
|
|
||||||
return "GO"
|
|
||||||
case GOTO:
|
|
||||||
return "GOTO"
|
|
||||||
case IF:
|
|
||||||
return "IF"
|
|
||||||
case IMPORT:
|
|
||||||
return "IMPORT"
|
|
||||||
case INTERFACE:
|
|
||||||
return "INTERFACE"
|
|
||||||
case MAP:
|
|
||||||
return "MAP"
|
|
||||||
case PACKAGE:
|
|
||||||
return "PACKAGE"
|
|
||||||
case RANGE:
|
|
||||||
return "RANGE"
|
|
||||||
case RETURN:
|
|
||||||
return "RETURN"
|
|
||||||
case SELECT:
|
|
||||||
return "SELECT"
|
|
||||||
case STRUCT:
|
|
||||||
return "STRUCT"
|
|
||||||
case SWITCH:
|
|
||||||
return "SWITCH"
|
|
||||||
case TYPE:
|
|
||||||
return "TYPE"
|
|
||||||
case VAR:
|
|
||||||
return "VAR"
|
|
||||||
case TILDE:
|
|
||||||
return "TILDE"
|
|
||||||
default:
|
|
||||||
panic(todo("", int(t), t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type data struct {
|
|
||||||
line int
|
|
||||||
cases int
|
|
||||||
cnt int
|
|
||||||
}
|
|
||||||
|
|
||||||
type analyzer struct {
|
|
||||||
sync.Mutex
|
|
||||||
m map[int]*data // line: data
|
|
||||||
}
|
|
||||||
|
|
||||||
func newAnalyzer() *analyzer {
|
|
||||||
return &analyzer{m: map[int]*data{}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *analyzer) record(line, cnt int) {
|
|
||||||
d := a.m[line]
|
|
||||||
if d == nil {
|
|
||||||
d = &data{line: line}
|
|
||||||
a.m[line] = d
|
|
||||||
}
|
|
||||||
d.cases++
|
|
||||||
d.cnt += cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *analyzer) merge(b *analyzer) {
|
|
||||||
a.Lock()
|
|
||||||
defer a.Unlock()
|
|
||||||
|
|
||||||
for k, v := range b.m {
|
|
||||||
d := a.m[k]
|
|
||||||
if d == nil {
|
|
||||||
d = &data{line: k}
|
|
||||||
a.m[k] = d
|
|
||||||
}
|
|
||||||
d.cases += v.cases
|
|
||||||
d.cnt += v.cnt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *analyzer) report() string {
|
|
||||||
var rows []*data
|
|
||||||
for _, v := range a.m {
|
|
||||||
rows = append(rows, v)
|
|
||||||
}
|
|
||||||
sort.Slice(rows, func(i, j int) bool {
|
|
||||||
a := rows[i]
|
|
||||||
b := rows[j]
|
|
||||||
if a.cases < b.cases {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.cases > b.cases {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// a.cases == b.cases
|
|
||||||
if a.cnt < b.cnt {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.cnt > b.cnt {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// a.cnt == b.cnt
|
|
||||||
return a.line < b.line
|
|
||||||
})
|
|
||||||
var b strings.Builder
|
|
||||||
var cases, cnt int
|
|
||||||
for _, row := range rows {
|
|
||||||
cases += row.cases
|
|
||||||
cnt += row.cnt
|
|
||||||
avg := float64(row.cnt) / float64(row.cases)
|
|
||||||
fmt.Fprintf(&b, "parser.go:%d:\t%16s %16s %8.1f\n", row.line, h(row.cases), h(row.cnt), avg)
|
|
||||||
}
|
|
||||||
avg := float64(cnt) / float64(cases)
|
|
||||||
fmt.Fprintf(&b, "<total>\t\t%16s %16s %8.1f\n", h(cases), h(cnt), avg)
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func h(v interface{}) string {
|
|
||||||
switch x := v.(type) {
|
|
||||||
case int:
|
|
||||||
return humanize.Comma(int64(x))
|
|
||||||
case int32:
|
|
||||||
return humanize.Comma(int64(x))
|
|
||||||
case int64:
|
|
||||||
return humanize.Comma(x)
|
|
||||||
case uint32:
|
|
||||||
return humanize.Comma(int64(x))
|
|
||||||
case uint64:
|
|
||||||
if x <= math.MaxInt64 {
|
|
||||||
return humanize.Comma(int64(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
return "-" + humanize.Comma(-int64(x))
|
|
||||||
}
|
|
||||||
return fmt.Sprint(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
type parallel struct {
|
|
||||||
limiter chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newParallel() *parallel {
|
|
||||||
return ¶llel{
|
|
||||||
limiter: make(chan struct{}, runtime.GOMAXPROCS(0)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parallel) throttle(f func()) {
|
|
||||||
p.limiter <- struct{}{}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
<-p.limiter
|
|
||||||
}()
|
|
||||||
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
|
|
||||||
func extraTags(verMajor, verMinor int, goos, goarch string) (r []string) {
|
|
||||||
// https://github.com/golang/go/commit/eeb7899137cda1c2cd60dab65ff41f627436db5b
|
|
||||||
//
|
|
||||||
// In Go 1.17 we added register ABI on AMD64 on Linux/macOS/Windows
|
|
||||||
// as a GOEXPERIMENT, on by default. In Go 1.18, we commit to always
|
|
||||||
// enabling register ABI on AMD64.
|
|
||||||
//
|
|
||||||
// Now "go build" for AMD64 always have goexperiment.regabi* tags
|
|
||||||
// set. However, at bootstrapping cmd/dist does not set the tags
|
|
||||||
// when building go_bootstrap. For this to work, unfortunately, we
|
|
||||||
// need to hard-code AMD64 to use register ABI in runtime code.
|
|
||||||
if verMajor == 1 {
|
|
||||||
switch {
|
|
||||||
case verMinor == 17:
|
|
||||||
switch goos {
|
|
||||||
case "linux", "darwin", "windows":
|
|
||||||
if goarch == "amd64" {
|
|
||||||
r = append(r, "goexperiment.regabiargs", "goexperiment.regabiwrappers")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case verMinor >= 18:
|
|
||||||
if goarch == "amd64" {
|
|
||||||
r = append(r, "goexperiment.regabiargs", "goexperiment.regabiwrappers")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
761
vendor/modernc.org/gc/v3/gc.go
generated
vendored
761
vendor/modernc.org/gc/v3/gc.go
generated
vendored
|
@ -1,761 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 stringer -output stringer.go -linecomment -type=Kind,ScopeKind,ChanDir,TypeCheck
|
|
||||||
|
|
||||||
package gc // modernc.org/gc/v3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"go/build/constraint"
|
|
||||||
"go/token"
|
|
||||||
"io"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/hashicorp/golang-lru/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
trcErrors bool
|
|
||||||
)
|
|
||||||
|
|
||||||
type FileFilter func(cfg *Config, importPath string, matchedFSPaths []string, withTestFiles bool) (pkgFiles []string, err error)
|
|
||||||
|
|
||||||
type TypeCheck int
|
|
||||||
|
|
||||||
const (
|
|
||||||
TypeCheckNone TypeCheck = iota
|
|
||||||
TypeCheckAll
|
|
||||||
)
|
|
||||||
|
|
||||||
type cacheKey struct {
|
|
||||||
buildTagsKey string
|
|
||||||
cfg *Config
|
|
||||||
fsPath string
|
|
||||||
goarch string
|
|
||||||
goos string
|
|
||||||
gopathKey string
|
|
||||||
goroot string
|
|
||||||
importPath string
|
|
||||||
typeCheck TypeCheck
|
|
||||||
|
|
||||||
withTestFiles bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type cacheItem struct {
|
|
||||||
pkg *Package
|
|
||||||
ch chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCacheItem() *cacheItem { return &cacheItem{ch: make(chan struct{})} }
|
|
||||||
|
|
||||||
func (c *cacheItem) set(pkg *Package) {
|
|
||||||
c.pkg = pkg
|
|
||||||
close(c.ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cacheItem) wait() *Package {
|
|
||||||
<-c.ch
|
|
||||||
return c.pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
type Cache struct {
|
|
||||||
sync.Mutex
|
|
||||||
lru *lru.TwoQueueCache[cacheKey, *cacheItem]
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCache(size int) (*Cache, error) {
|
|
||||||
c, err := lru.New2Q[cacheKey, *cacheItem](size)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Cache{lru: c}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func MustNewCache(size int) *Cache {
|
|
||||||
c, err := NewCache(size)
|
|
||||||
if err != nil {
|
|
||||||
panic(todo("", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigOption func(*Config) error
|
|
||||||
|
|
||||||
// Config configures NewPackage
|
|
||||||
//
|
|
||||||
// Config instances can be shared, they are not mutated once created and
|
|
||||||
// configured.
|
|
||||||
type Config struct {
|
|
||||||
abi *ABI
|
|
||||||
buildTagMap map[string]bool
|
|
||||||
buildTags []string
|
|
||||||
buildTagsKey string // Zero byte separated
|
|
||||||
builtin *Package
|
|
||||||
cache *Cache
|
|
||||||
cmp *Package // Go 1.21
|
|
||||||
env map[string]string
|
|
||||||
fs fs.FS
|
|
||||||
goarch string
|
|
||||||
gocompiler string // "gc", "gccgo"
|
|
||||||
goos string
|
|
||||||
gopath string
|
|
||||||
gopathKey string // Zero byte separated
|
|
||||||
goroot string
|
|
||||||
goversion string
|
|
||||||
lookup func(rel, importPath, version string) (fsPath string, err error)
|
|
||||||
parallel *parallel
|
|
||||||
searchGoPaths []string
|
|
||||||
searchGoroot []string
|
|
||||||
|
|
||||||
int Type // Set by NewConfig
|
|
||||||
uint Type // Set by NewConfig
|
|
||||||
|
|
||||||
arch32bit bool
|
|
||||||
configured bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewConfig returns a newly created config or an error, if any.
|
|
||||||
func NewConfig(opts ...ConfigOption) (r *Config, err error) {
|
|
||||||
r = &Config{
|
|
||||||
buildTagMap: map[string]bool{},
|
|
||||||
env: map[string]string{},
|
|
||||||
parallel: newParallel(),
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if r != nil {
|
|
||||||
r.configured = true
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
r.lookup = r.DefaultLookup
|
|
||||||
ctx := build.Default
|
|
||||||
r.goos = r.getenv("GOOS", ctx.GOOS)
|
|
||||||
r.goarch = r.getenv("GOARCH", ctx.GOARCH)
|
|
||||||
r.goroot = r.getenv("GOROOT", ctx.GOROOT)
|
|
||||||
r.gopath = r.getenv("GOPATH", ctx.GOPATH)
|
|
||||||
r.buildTags = append(r.buildTags, r.goos, r.goarch)
|
|
||||||
r.gocompiler = runtime.Compiler
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err := opt(r); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if r.abi, err = NewABI(r.goos, r.goarch); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch r.goarch {
|
|
||||||
case "386", "arm":
|
|
||||||
r.arch32bit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// During a particular build, the following build tags are satisfied:
|
|
||||||
//
|
|
||||||
// the target operating system, as spelled by runtime.GOOS, set with the GOOS environment variable.
|
|
||||||
// the target architecture, as spelled by runtime.GOARCH, set with the GOARCH environment variable.
|
|
||||||
// "unix", if GOOS is a Unix or Unix-like system.
|
|
||||||
// the compiler being used, either "gc" or "gccgo"
|
|
||||||
// "cgo", if the cgo command is supported (see CGO_ENABLED in 'go help environment').
|
|
||||||
// a term for each Go major release, through the current version: "go1.1" from Go version 1.1 onward, "go1.12" from Go 1.12, and so on.
|
|
||||||
// any additional tags given by the -tags flag (see 'go help build').
|
|
||||||
// There are no separate build tags for beta or minor releases.
|
|
||||||
if r.goversion == "" {
|
|
||||||
r.goversion = runtime.Version()
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(r.goversion, "go") || !strings.Contains(r.goversion, ".") {
|
|
||||||
return nil, fmt.Errorf("cannot parse Go version: %s", r.goversion)
|
|
||||||
}
|
|
||||||
|
|
||||||
ver := strings.SplitN(r.goversion[len("go"):], ".", 2)
|
|
||||||
verMajor, err := strconv.Atoi(ver[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot parse Go version %s: %v", r.goversion, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if verMajor != 1 {
|
|
||||||
return nil, fmt.Errorf("unsupported Go version: %s", r.goversion)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x, x2 := strings.IndexByte(ver[1], '.'), strings.Index(ver[1], "rc"); {
|
|
||||||
case x >= 0:
|
|
||||||
ver[1] = ver[1][:x]
|
|
||||||
case x2 >= 0:
|
|
||||||
ver[1] = ver[1][:x2]
|
|
||||||
}
|
|
||||||
verMinor, err := strconv.Atoi(ver[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot parse Go version %s: %v", r.goversion, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 1; i <= verMinor; i++ {
|
|
||||||
r.buildTags = append(r.buildTags, fmt.Sprintf("go%d.%d", verMajor, i))
|
|
||||||
}
|
|
||||||
r.buildTags = append(r.buildTags, r.gocompiler)
|
|
||||||
r.buildTags = append(r.buildTags, extraTags(verMajor, verMinor, r.goos, r.goarch)...)
|
|
||||||
if r.getenv("CGO_ENABLED", "1") == "1" {
|
|
||||||
r.buildTags = append(r.buildTags, "cgo")
|
|
||||||
}
|
|
||||||
for i, v := range r.buildTags {
|
|
||||||
tag := strings.TrimSpace(v)
|
|
||||||
r.buildTags[i] = tag
|
|
||||||
r.buildTagMap[tag] = true
|
|
||||||
}
|
|
||||||
sort.Strings(r.buildTags)
|
|
||||||
r.buildTagsKey = strings.Join(r.buildTags, "\x00")
|
|
||||||
r.searchGoroot = []string{filepath.Join(r.goroot, "src")}
|
|
||||||
r.searchGoPaths = filepath.SplitList(r.gopath)
|
|
||||||
r.gopathKey = strings.Join(r.searchGoPaths, "\x00")
|
|
||||||
for i, v := range r.searchGoPaths {
|
|
||||||
r.searchGoPaths[i] = filepath.Join(v, "src")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.cmp, err = r.NewPackage("", "cmp", "", nil, false, TypeCheckNone); {
|
|
||||||
case err != nil:
|
|
||||||
r.cmp = nil
|
|
||||||
default:
|
|
||||||
//TODO r.cmp.Scope.kind = UniverseScope
|
|
||||||
}
|
|
||||||
if r.builtin, err = r.NewPackage("", "builtin", "", nil, false, TypeCheckNone); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.builtin.Scope.kind = UniverseScope
|
|
||||||
if err := r.builtin.check(newCtx(r)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) universe() *Scope {
|
|
||||||
if c.builtin != nil {
|
|
||||||
return c.builtin.Scope
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) stat(name string) (fs.FileInfo, error) {
|
|
||||||
if c.fs == nil {
|
|
||||||
return os.Stat(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
name = filepath.ToSlash(name)
|
|
||||||
if x, ok := c.fs.(fs.StatFS); ok {
|
|
||||||
return x.Stat(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := c.fs.Open(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return f.Stat()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) open(name string) (fs.File, error) {
|
|
||||||
if c.fs == nil {
|
|
||||||
return os.Open(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
name = filepath.ToSlash(name)
|
|
||||||
return c.fs.Open(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) glob(pattern string) (matches []string, err error) {
|
|
||||||
if c.fs == nil {
|
|
||||||
return filepath.Glob(pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = filepath.ToSlash(pattern)
|
|
||||||
return fs.Glob(c.fs, pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) checkConstraints(pos token.Position, sep string) (r bool) {
|
|
||||||
if !strings.Contains(sep, "//go:build") && !strings.Contains(sep, "+build") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// defer func() { trc("", r) }()
|
|
||||||
|
|
||||||
lines := strings.Split(sep, "\n")
|
|
||||||
var build, plusBuild []string
|
|
||||||
for i, line := range lines {
|
|
||||||
if constraint.IsGoBuild(line) && i < len(lines)-1 && lines[i+1] == "" {
|
|
||||||
build = append(build, line)
|
|
||||||
}
|
|
||||||
if constraint.IsPlusBuild(line) {
|
|
||||||
plusBuild = append(plusBuild, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch len(build) {
|
|
||||||
case 0:
|
|
||||||
// ok
|
|
||||||
case 1:
|
|
||||||
expr, err := constraint.Parse(build[0])
|
|
||||||
if err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return expr.Eval(func(tag string) (r bool) {
|
|
||||||
// defer func() { trc("%q: %v", tag, r) }()
|
|
||||||
switch tag {
|
|
||||||
case "unix":
|
|
||||||
return unixOS[c.goos]
|
|
||||||
default:
|
|
||||||
return c.buildTagMap[tag]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %q", pos, build))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, line := range plusBuild {
|
|
||||||
expr, err := constraint.Parse(line)
|
|
||||||
if err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !expr.Eval(func(tag string) (r bool) {
|
|
||||||
// defer func() { trc("%q: %v", tag, r) }()
|
|
||||||
switch tag {
|
|
||||||
case "unix":
|
|
||||||
return unixOS[c.goos]
|
|
||||||
default:
|
|
||||||
return c.buildTagMap[tag]
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default lookup translates import paths, possibly relative to rel, to file system paths.
|
|
||||||
func (c *Config) DefaultLookup(rel, importPath, version string) (fsPath string, err error) {
|
|
||||||
if importPath == "" {
|
|
||||||
return "", fmt.Errorf("import path cannot be emtpy")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation restriction: A compiler may restrict ImportPaths to non-empty
|
|
||||||
// strings using only characters belonging to Unicode's L, M, N, P, and S
|
|
||||||
// general categories (the Graphic characters without spaces) and may also
|
|
||||||
// exclude the characters !"#$%&'()*,:;<=>?[\]^`{|} and the Unicode replacement
|
|
||||||
// character U+FFFD.
|
|
||||||
if strings.ContainsAny(importPath, "!\"#$%&'()*,:;<=>?[\\]^`{|}\ufffd") {
|
|
||||||
return "", fmt.Errorf("invalid import path: %s", importPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range importPath {
|
|
||||||
if !unicode.Is(unicode.L, r) &&
|
|
||||||
!unicode.Is(unicode.M, r) &&
|
|
||||||
!unicode.Is(unicode.N, r) &&
|
|
||||||
!unicode.Is(unicode.P, r) &&
|
|
||||||
!unicode.Is(unicode.S, r) {
|
|
||||||
return "", fmt.Errorf("invalid import path: %s", importPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var search []string
|
|
||||||
ip0 := importPath
|
|
||||||
switch slash := strings.IndexByte(importPath, '/'); {
|
|
||||||
case strings.HasPrefix(importPath, "./"):
|
|
||||||
if rel != "" {
|
|
||||||
panic(todo(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("invalid import path: %s", importPath)
|
|
||||||
case strings.HasPrefix(importPath, "/"):
|
|
||||||
return importPath, nil
|
|
||||||
case slash > 0:
|
|
||||||
ip0 = importPath[:slash]
|
|
||||||
default:
|
|
||||||
ip0 = importPath
|
|
||||||
}
|
|
||||||
if ip0 != "" {
|
|
||||||
switch {
|
|
||||||
case strings.Contains(ip0, "."):
|
|
||||||
search = c.searchGoPaths
|
|
||||||
default:
|
|
||||||
search = c.searchGoroot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, v := range search {
|
|
||||||
fsPath = filepath.Join(v, importPath)
|
|
||||||
dir, err := c.open(fsPath)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fi, err := dir.Stat()
|
|
||||||
dir.Close()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() {
|
|
||||||
return fsPath, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("cannot find package %s, searched %v", importPath, search)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) getenv(nm, deflt string) (r string) {
|
|
||||||
if r = c.env[nm]; r != "" {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
if r = os.Getenv(nm); r != "" {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
return deflt
|
|
||||||
}
|
|
||||||
|
|
||||||
func DefaultFileFilter(cfg *Config, importPath string, matchedFSPaths []string, withTestFiles bool) (pkgFiles []string, err error) {
|
|
||||||
w := 0
|
|
||||||
for _, v := range matchedFSPaths {
|
|
||||||
base := filepath.Base(v)
|
|
||||||
base = base[:len(base)-len(filepath.Ext(base))]
|
|
||||||
const testSuffix = "_test"
|
|
||||||
if strings.HasSuffix(base, testSuffix) {
|
|
||||||
if !withTestFiles {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
base = base[:len(base)-len(testSuffix)]
|
|
||||||
}
|
|
||||||
if x := strings.LastIndexByte(base, '_'); x > 0 {
|
|
||||||
last := base[x+1:]
|
|
||||||
base = base[:x]
|
|
||||||
var prevLast string
|
|
||||||
if x := strings.LastIndexByte(base, '_'); x > 0 {
|
|
||||||
prevLast = base[x+1:]
|
|
||||||
}
|
|
||||||
if last != "" && prevLast != "" {
|
|
||||||
// *_GOOS_GOARCH
|
|
||||||
if knownOS[prevLast] && prevLast != cfg.goos {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if knownArch[last] && last != cfg.goarch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if last != "" {
|
|
||||||
// *_GOOS or *_GOARCH
|
|
||||||
if knownOS[last] && last != cfg.goos {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if knownArch[last] && last != cfg.goarch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
matchedFSPaths[w] = v
|
|
||||||
w++
|
|
||||||
}
|
|
||||||
return matchedFSPaths[:w], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigBuildTags configures build tags.
|
|
||||||
func ConfigBuildTags(tags []string) ConfigOption {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.configured {
|
|
||||||
return fmt.Errorf("ConfigBuildTags: Config instance already configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.buildTags = append(cfg.buildTags, tags...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigEnviron configures environment variables.
|
|
||||||
func ConfigEnviron(env []string) ConfigOption {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.configured {
|
|
||||||
return fmt.Errorf("ConfigEnviron: Config instance already configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range env {
|
|
||||||
switch x := strings.IndexByte(v, '='); {
|
|
||||||
case x < 0:
|
|
||||||
cfg.env[v] = ""
|
|
||||||
default:
|
|
||||||
cfg.env[v[:x]] = v[x+1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigFS configures a file system used for opening Go source files. If not
|
|
||||||
// explicitly configured, a default os.DirFS("/") is used on Unix-like
|
|
||||||
// operating systems. On Windows it will be rooted on the volume where
|
|
||||||
// runtime.GOROOT() is.
|
|
||||||
func ConfigFS(fs fs.FS) ConfigOption {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.configured {
|
|
||||||
return fmt.Errorf("ConfigFS: Config instance already configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.fs = fs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigLookup configures a lookup function.
|
|
||||||
func ConfigLookup(f func(dir, importPath, version string) (fsPath string, err error)) ConfigOption {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.configured {
|
|
||||||
return fmt.Errorf("ConfigLookup: Config instance already configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.lookup = f
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigCache configures a cache.
|
|
||||||
func ConfigCache(c *Cache) ConfigOption {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.configured {
|
|
||||||
return fmt.Errorf("ConfigCache: Config instance already configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.cache = c
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type importGuard struct {
|
|
||||||
m map[string]struct{}
|
|
||||||
stack []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newImportGuard() *importGuard { return &importGuard{m: map[string]struct{}{}} }
|
|
||||||
|
|
||||||
// Package represents a Go package. The instance must not be mutated.
|
|
||||||
type Package struct {
|
|
||||||
AST map[string]*AST // AST maps fsPaths of individual files to their respective ASTs
|
|
||||||
FSPath string
|
|
||||||
GoFiles []fs.FileInfo
|
|
||||||
ImportPath string
|
|
||||||
InvalidGoFiles map[string]error // errors for particular files, if any
|
|
||||||
Name Token
|
|
||||||
Scope *Scope // Package scope.
|
|
||||||
Version string
|
|
||||||
cfg *Config
|
|
||||||
guard *importGuard
|
|
||||||
mu sync.Mutex
|
|
||||||
typeCheck TypeCheck
|
|
||||||
|
|
||||||
isUnsafe bool // ImportPath == "usnafe"
|
|
||||||
// isChecked bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPackage returns a Package, possibly cached, for importPath@version or an
|
|
||||||
// error, if any. The fileFilter argument can be nil, in such case
|
|
||||||
// DefaultFileFilter is used, which ignores Files with suffix _test.go unless
|
|
||||||
// withTestFiles is true.
|
|
||||||
//
|
|
||||||
// NewPackage is safe for concurrent use by multiple goroutines.
|
|
||||||
func (c *Config) NewPackage(dir, importPath, version string, fileFilter FileFilter, withTestFiles bool, typeCheck TypeCheck) (pkg *Package, err error) {
|
|
||||||
return c.newPackage(dir, importPath, version, fileFilter, withTestFiles, typeCheck, newImportGuard())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) newPackage(dir, importPath, version string, fileFilter FileFilter, withTestFiles bool, typeCheck TypeCheck, guard *importGuard) (pkg *Package, err error) {
|
|
||||||
if _, ok := guard.m[importPath]; ok {
|
|
||||||
return nil, fmt.Errorf("import cycle %v", guard.stack)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.stack = append(guard.stack, importPath)
|
|
||||||
fsPath, err := c.lookup(dir, importPath, version)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("lookup %s: %v", importPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pat := filepath.Join(fsPath, "*.go")
|
|
||||||
matches, err := c.glob(pat)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("glob %s: %v", pat, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(matches) == 0 {
|
|
||||||
return nil, fmt.Errorf("no Go files in %s", fsPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fileFilter == nil {
|
|
||||||
fileFilter = DefaultFileFilter
|
|
||||||
}
|
|
||||||
if matches, err = fileFilter(c, importPath, matches, withTestFiles); err != nil {
|
|
||||||
return nil, fmt.Errorf("matching Go files in %s: %v", fsPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var k cacheKey
|
|
||||||
if c.cache != nil {
|
|
||||||
k = cacheKey{
|
|
||||||
buildTagsKey: c.buildTagsKey,
|
|
||||||
cfg: c,
|
|
||||||
fsPath: fsPath,
|
|
||||||
goarch: c.goarch,
|
|
||||||
goos: c.goos,
|
|
||||||
gopathKey: c.gopathKey,
|
|
||||||
goroot: c.goroot,
|
|
||||||
importPath: importPath,
|
|
||||||
typeCheck: typeCheck,
|
|
||||||
withTestFiles: withTestFiles,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.cache.Lock() // ---------------------------------------- lock
|
|
||||||
item, ok := c.cache.lru.Get(k)
|
|
||||||
if ok {
|
|
||||||
c.cache.Unlock() // ---------------------------- unlock
|
|
||||||
if pkg = item.wait(); pkg != nil && pkg.matches(&k, matches) {
|
|
||||||
return pkg, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item = newCacheItem()
|
|
||||||
c.cache.lru.Add(k, item)
|
|
||||||
c.cache.Unlock() // ------------------------------------ unlock
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if pkg != nil && err == nil {
|
|
||||||
item.set(pkg)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &Package{
|
|
||||||
AST: map[string]*AST{},
|
|
||||||
FSPath: fsPath,
|
|
||||||
ImportPath: importPath,
|
|
||||||
Scope: newScope(c.universe(), PackageScope),
|
|
||||||
Version: version,
|
|
||||||
cfg: c,
|
|
||||||
guard: guard,
|
|
||||||
isUnsafe: importPath == "unsafe",
|
|
||||||
typeCheck: typeCheck,
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { r.guard = nil }()
|
|
||||||
|
|
||||||
sort.Strings(matches)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
sort.Slice(r.GoFiles, func(i, j int) bool { return r.GoFiles[i].Name() < r.GoFiles[j].Name() })
|
|
||||||
if err != nil || len(r.InvalidGoFiles) != 0 || typeCheck == TypeCheckNone {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO err = r.check(newCtx(c))
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.parallel.throttle(func() {
|
|
||||||
for _, path := range matches {
|
|
||||||
if err = c.newPackageFile(r, path); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) newPackageFile(pkg *Package, path string) (err error) {
|
|
||||||
f, err := c.open(path)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("opening file %q: %v", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
f.Close()
|
|
||||||
if err != nil {
|
|
||||||
if pkg.InvalidGoFiles == nil {
|
|
||||||
pkg.InvalidGoFiles = map[string]error{}
|
|
||||||
}
|
|
||||||
pkg.InvalidGoFiles[path] = err
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var fi fs.FileInfo
|
|
||||||
if fi, err = f.Stat(); err != nil {
|
|
||||||
return fmt.Errorf("stat %s: %v", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fi.Mode().IsRegular() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var b []byte
|
|
||||||
if b, err = io.ReadAll(f); err != nil {
|
|
||||||
return fmt.Errorf("reading %s: %v", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := newParser(pkg.Scope, path, b, false)
|
|
||||||
if p.peek(0) == PACKAGE {
|
|
||||||
tok := Token{p.s.source, p.s.toks[p.ix].ch, int32(p.ix)}
|
|
||||||
if !c.checkConstraints(tok.Position(), tok.Sep()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg.GoFiles = append(pkg.GoFiles, fi)
|
|
||||||
var ast *AST
|
|
||||||
if ast, err = p.parse(); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg.AST[path] = ast
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Package) matches(k *cacheKey, matches []string) bool {
|
|
||||||
matched := map[string]struct{}{}
|
|
||||||
for _, match := range matches {
|
|
||||||
matched[match] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, cachedInfo := range p.GoFiles {
|
|
||||||
name := cachedInfo.Name()
|
|
||||||
path := filepath.Join(p.FSPath, name)
|
|
||||||
if _, ok := matched[path]; !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := k.cfg.stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() ||
|
|
||||||
info.Size() != cachedInfo.Size() ||
|
|
||||||
info.ModTime().After(cachedInfo.ModTime()) ||
|
|
||||||
info.Mode() != cachedInfo.Mode() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFile parses 'b', assuming it comes from 'path' and returns an AST or error, if any.
|
|
||||||
func ParseFile(path string, b []byte) (*AST, error) {
|
|
||||||
return newParser(newScope(nil, PackageScope), path, b, false).parse()
|
|
||||||
}
|
|
9415
vendor/modernc.org/gc/v3/parser.go
generated
vendored
9415
vendor/modernc.org/gc/v3/parser.go
generated
vendored
File diff suppressed because it is too large
Load diff
1446
vendor/modernc.org/gc/v3/scanner.go
generated
vendored
1446
vendor/modernc.org/gc/v3/scanner.go
generated
vendored
File diff suppressed because it is too large
Load diff
115
vendor/modernc.org/gc/v3/stringer.go
generated
vendored
115
vendor/modernc.org/gc/v3/stringer.go
generated
vendored
|
@ -1,115 +0,0 @@
|
||||||
// Code generated by "stringer -output stringer.go -linecomment -type=Kind,ScopeKind,ChanDir,TypeCheck"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package gc
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[InvalidKind-0]
|
|
||||||
_ = x[Array-1]
|
|
||||||
_ = x[Bool-2]
|
|
||||||
_ = x[Chan-3]
|
|
||||||
_ = x[Complex128-4]
|
|
||||||
_ = x[Complex64-5]
|
|
||||||
_ = x[Float32-6]
|
|
||||||
_ = x[Float64-7]
|
|
||||||
_ = x[Function-8]
|
|
||||||
_ = x[Int-9]
|
|
||||||
_ = x[Int16-10]
|
|
||||||
_ = x[Int32-11]
|
|
||||||
_ = x[Int64-12]
|
|
||||||
_ = x[Int8-13]
|
|
||||||
_ = x[Interface-14]
|
|
||||||
_ = x[Map-15]
|
|
||||||
_ = x[Pointer-16]
|
|
||||||
_ = x[Slice-17]
|
|
||||||
_ = x[String-18]
|
|
||||||
_ = x[Struct-19]
|
|
||||||
_ = x[Tuple-20]
|
|
||||||
_ = x[Uint-21]
|
|
||||||
_ = x[Uint16-22]
|
|
||||||
_ = x[Uint32-23]
|
|
||||||
_ = x[Uint64-24]
|
|
||||||
_ = x[Uint8-25]
|
|
||||||
_ = x[Uintptr-26]
|
|
||||||
_ = x[UnsafePointer-27]
|
|
||||||
_ = x[UntypedBool-28]
|
|
||||||
_ = x[UntypedComplex-29]
|
|
||||||
_ = x[UntypedFloat-30]
|
|
||||||
_ = x[UntypedInt-31]
|
|
||||||
_ = x[UntypedNil-32]
|
|
||||||
_ = x[UntypedRune-33]
|
|
||||||
_ = x[UntypedString-34]
|
|
||||||
}
|
|
||||||
|
|
||||||
const _Kind_name = "<invalid type>arrayboolchancomplex128complex64float32float64functionintint16int32int64int8interfacemappointerslicestringstructtupleuintuint16uint32uint64uint8uintptrunsafe.Pointeruntyped booluntyped complexuntyped floatuntyped intuntyped niluntyped runeuntyped string"
|
|
||||||
|
|
||||||
var _Kind_index = [...]uint16{0, 14, 19, 23, 27, 37, 46, 53, 60, 68, 71, 76, 81, 86, 90, 99, 102, 109, 114, 120, 126, 131, 135, 141, 147, 153, 158, 165, 179, 191, 206, 219, 230, 241, 253, 267}
|
|
||||||
|
|
||||||
func (i Kind) String() string {
|
|
||||||
if i >= Kind(len(_Kind_index)-1) {
|
|
||||||
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
|
||||||
}
|
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[scZero-0]
|
|
||||||
_ = x[UniverseScope-1]
|
|
||||||
_ = x[PackageScope-2]
|
|
||||||
_ = x[FileScope-3]
|
|
||||||
_ = x[OtherScope-4]
|
|
||||||
}
|
|
||||||
|
|
||||||
const _ScopeKind_name = "scZeroUniverseScopePackageScopeFileScopeOtherScope"
|
|
||||||
|
|
||||||
var _ScopeKind_index = [...]uint8{0, 6, 19, 31, 40, 50}
|
|
||||||
|
|
||||||
func (i ScopeKind) String() string {
|
|
||||||
if i < 0 || i >= ScopeKind(len(_ScopeKind_index)-1) {
|
|
||||||
return "ScopeKind(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
return _ScopeKind_name[_ScopeKind_index[i]:_ScopeKind_index[i+1]]
|
|
||||||
}
|
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[SendRecv-0]
|
|
||||||
_ = x[SendOnly-1]
|
|
||||||
_ = x[RecvOnly-2]
|
|
||||||
}
|
|
||||||
|
|
||||||
const _ChanDir_name = "SendRecvSendOnlyRecvOnly"
|
|
||||||
|
|
||||||
var _ChanDir_index = [...]uint8{0, 8, 16, 24}
|
|
||||||
|
|
||||||
func (i ChanDir) String() string {
|
|
||||||
if i < 0 || i >= ChanDir(len(_ChanDir_index)-1) {
|
|
||||||
return "ChanDir(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
return _ChanDir_name[_ChanDir_index[i]:_ChanDir_index[i+1]]
|
|
||||||
}
|
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[TypeCheckNone-0]
|
|
||||||
_ = x[TypeCheckAll-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
const _TypeCheck_name = "TypeCheckNoneTypeCheckAll"
|
|
||||||
|
|
||||||
var _TypeCheck_index = [...]uint8{0, 13, 25}
|
|
||||||
|
|
||||||
func (i TypeCheck) String() string {
|
|
||||||
if i < 0 || i >= TypeCheck(len(_TypeCheck_index)-1) {
|
|
||||||
return "TypeCheck(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
return _TypeCheck_name[_TypeCheck_index[i]:_TypeCheck_index[i+1]]
|
|
||||||
}
|
|
90
vendor/modernc.org/gc/v3/syslist.go
generated
vendored
90
vendor/modernc.org/gc/v3/syslist.go
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the GO-LICENSE file.
|
|
||||||
|
|
||||||
// Modifications
|
|
||||||
//
|
|
||||||
// Copyright 2022 The Gc 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 build // /usr/local/go/src/go/build/syslist.go
|
|
||||||
|
|
||||||
package gc // import "modernc.org/gc/v3"
|
|
||||||
|
|
||||||
// Go 1.19.3
|
|
||||||
|
|
||||||
// Note that this file is read by internal/goarch/gengoarch.go and by
|
|
||||||
// internal/goos/gengoos.go. If you change this file, look at those
|
|
||||||
// files as well.
|
|
||||||
|
|
||||||
// knownOS is the list of past, present, and future known GOOS values.
|
|
||||||
// Do not remove from this list, as it is used for filename matching.
|
|
||||||
// If you add an entry to this list, look at unixOS, below.
|
|
||||||
var knownOS = map[string]bool{
|
|
||||||
"aix": true,
|
|
||||||
"android": true,
|
|
||||||
"darwin": true,
|
|
||||||
"dragonfly": true,
|
|
||||||
"freebsd": true,
|
|
||||||
"hurd": true,
|
|
||||||
"illumos": true,
|
|
||||||
"ios": true,
|
|
||||||
"js": true,
|
|
||||||
"linux": true,
|
|
||||||
"nacl": true,
|
|
||||||
"netbsd": true,
|
|
||||||
"openbsd": true,
|
|
||||||
"plan9": true,
|
|
||||||
"solaris": true,
|
|
||||||
"windows": true,
|
|
||||||
"zos": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// unixOS is the set of GOOS values matched by the "unix" build tag.
|
|
||||||
// This is not used for filename matching.
|
|
||||||
// This list also appears in cmd/dist/build.go and
|
|
||||||
// cmd/go/internal/imports/build.go.
|
|
||||||
var unixOS = map[string]bool{
|
|
||||||
"aix": true,
|
|
||||||
"android": true,
|
|
||||||
"darwin": true,
|
|
||||||
"dragonfly": true,
|
|
||||||
"freebsd": true,
|
|
||||||
"hurd": true,
|
|
||||||
"illumos": true,
|
|
||||||
"ios": true,
|
|
||||||
"linux": true,
|
|
||||||
"netbsd": true,
|
|
||||||
"openbsd": true,
|
|
||||||
"solaris": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// knownArch is the list of past, present, and future known GOARCH values.
|
|
||||||
// Do not remove from this list, as it is used for filename matching.
|
|
||||||
var knownArch = map[string]bool{
|
|
||||||
"386": true,
|
|
||||||
"amd64": true,
|
|
||||||
"amd64p32": true,
|
|
||||||
"arm": true,
|
|
||||||
"armbe": true,
|
|
||||||
"arm64": true,
|
|
||||||
"arm64be": true,
|
|
||||||
"loong64": true,
|
|
||||||
"mips": true,
|
|
||||||
"mipsle": true,
|
|
||||||
"mips64": true,
|
|
||||||
"mips64le": true,
|
|
||||||
"mips64p32": true,
|
|
||||||
"mips64p32le": true,
|
|
||||||
"ppc": true,
|
|
||||||
"ppc64": true,
|
|
||||||
"ppc64le": true,
|
|
||||||
"riscv": true,
|
|
||||||
"riscv64": true,
|
|
||||||
"s390": true,
|
|
||||||
"s390x": true,
|
|
||||||
"sparc": true,
|
|
||||||
"sparc64": true,
|
|
||||||
"wasm": true,
|
|
||||||
}
|
|
813
vendor/modernc.org/gc/v3/type.go
generated
vendored
813
vendor/modernc.org/gc/v3/type.go
generated
vendored
|
@ -1,813 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 gc // modernc.org/gc/v3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Invalid = &InvalidType{}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ Type = (*ArrayTypeNode)(nil)
|
|
||||||
_ Type = (*ChannelTypeNode)(nil)
|
|
||||||
_ Type = (*FunctionTypeNode)(nil)
|
|
||||||
_ Type = (*InterfaceTypeNode)(nil)
|
|
||||||
_ Type = (*InvalidType)(nil)
|
|
||||||
_ Type = (*MapTypeNode)(nil)
|
|
||||||
_ Type = (*ParenthesizedTypeNode)(nil)
|
|
||||||
_ Type = (*PointerTypeNode)(nil)
|
|
||||||
_ Type = (*PredeclaredType)(nil)
|
|
||||||
_ Type = (*SliceTypeNode)(nil)
|
|
||||||
_ Type = (*StructTypeNode)(nil)
|
|
||||||
_ Type = (*TupleType)(nil)
|
|
||||||
_ Type = (*TypeDefNode)(nil)
|
|
||||||
_ Type = (*TypeNameNode)(nil)
|
|
||||||
_ Type = (*TypeNode)(nil)
|
|
||||||
|
|
||||||
invalidRecursiveType = &InvalidType{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Kind represents the specific kind of type that a Type represents. The zero
|
|
||||||
// Kind is not a valid kind.
|
|
||||||
type Kind byte
|
|
||||||
|
|
||||||
// Values of type Kind
|
|
||||||
const (
|
|
||||||
InvalidKind Kind = iota // <invalid type>
|
|
||||||
|
|
||||||
Array // array
|
|
||||||
Bool // bool
|
|
||||||
Chan // chan
|
|
||||||
Complex128 // complex128
|
|
||||||
Complex64 // complex64
|
|
||||||
Float32 // float32
|
|
||||||
Float64 // float64
|
|
||||||
Function // function
|
|
||||||
Int // int
|
|
||||||
Int16 // int16
|
|
||||||
Int32 // int32
|
|
||||||
Int64 // int64
|
|
||||||
Int8 // int8
|
|
||||||
Interface // interface
|
|
||||||
Map // map
|
|
||||||
Pointer // pointer
|
|
||||||
Slice // slice
|
|
||||||
String // string
|
|
||||||
Struct // struct
|
|
||||||
Tuple // tuple
|
|
||||||
Uint // uint
|
|
||||||
Uint16 // uint16
|
|
||||||
Uint32 // uint32
|
|
||||||
Uint64 // uint64
|
|
||||||
Uint8 // uint8
|
|
||||||
Uintptr // uintptr
|
|
||||||
UnsafePointer // unsafe.Pointer
|
|
||||||
UntypedBool // untyped bool
|
|
||||||
UntypedComplex // untyped complex
|
|
||||||
UntypedFloat // untyped float
|
|
||||||
UntypedInt // untyped int
|
|
||||||
UntypedNil // untyped nil
|
|
||||||
UntypedRune // untyped rune
|
|
||||||
UntypedString // untyped string
|
|
||||||
)
|
|
||||||
|
|
||||||
type typeSetter interface {
|
|
||||||
setType(t Type) Type
|
|
||||||
}
|
|
||||||
|
|
||||||
type typeCache struct {
|
|
||||||
t Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *typeCache) Type() Type {
|
|
||||||
if n.t != nil {
|
|
||||||
return n.t
|
|
||||||
}
|
|
||||||
|
|
||||||
n.t = Invalid
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *typeCache) setType(t Type) Type {
|
|
||||||
n.t = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *typeCache) enter(c *ctx, nd Node) bool {
|
|
||||||
switch {
|
|
||||||
case n.t == nil:
|
|
||||||
n.t = invalidRecursiveType
|
|
||||||
return true
|
|
||||||
case n.t == invalidRecursiveType:
|
|
||||||
n.t = Invalid
|
|
||||||
c.err(nd, "invalid recursive type")
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type typer interface {
|
|
||||||
Type() Type
|
|
||||||
}
|
|
||||||
|
|
||||||
type Type interface {
|
|
||||||
Node
|
|
||||||
|
|
||||||
// Align returns the alignment in bytes of a value of this type when allocated
|
|
||||||
// in memory.
|
|
||||||
Align() int
|
|
||||||
|
|
||||||
// FieldAlign returns the alignment in bytes of a value of this type when used
|
|
||||||
// as a field in a struct.
|
|
||||||
FieldAlign() int
|
|
||||||
|
|
||||||
// Kind returns the specific kind of this type.
|
|
||||||
Kind() Kind
|
|
||||||
|
|
||||||
// Size returns the number of bytes needed to store a value of the given type;
|
|
||||||
// it is analogous to unsafe.Sizeof.
|
|
||||||
Size() int64
|
|
||||||
|
|
||||||
// String returns a string representation of the type. The string
|
|
||||||
// representation is not guaranteed to be unique among types.
|
|
||||||
String() string
|
|
||||||
|
|
||||||
check(c *ctx) Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ArrayTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ArrayTypeNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ArrayTypeNode) Kind() Kind { return Array }
|
|
||||||
func (n *ArrayTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ArrayTypeNode) String() string {
|
|
||||||
return fmt.Sprintf("[%v]%v", n.ArrayLength.Value(), n.ElementType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ArrayTypeNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
n.ArrayLength = n.ArrayLength.checkExpr(c)
|
|
||||||
v := c.convertValue(n.ArrayLength, n.ArrayLength.Value(), c.cfg.int)
|
|
||||||
if !known(v) {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
n.ElementType.check(c)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChanDir represents a channel direction.
|
|
||||||
type ChanDir int
|
|
||||||
|
|
||||||
// Values of type ChanDir.
|
|
||||||
const (
|
|
||||||
SendRecv ChanDir = iota
|
|
||||||
SendOnly
|
|
||||||
RecvOnly
|
|
||||||
)
|
|
||||||
|
|
||||||
func (n *ChannelTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *ChannelTypeNode) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ChannelTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ChannelTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ChannelTypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *ChannelTypeNode) check(c *ctx) Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *FunctionTypeNode) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *FunctionTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *FunctionTypeNode) String() string {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
func (n *FunctionTypeNode) check(c *ctx) Type {
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
n.Signature.check(c)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *InterfaceTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *InterfaceTypeNode) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *InterfaceTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *InterfaceTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *InterfaceTypeNode) String() string {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
func (n *InterfaceTypeNode) check(c *ctx) Type {
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
n.InterfaceElemList.check(c, n)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *InterfaceElemListNode) check(c *ctx, t *InterfaceTypeNode) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for l := n; l != nil; l = l.List {
|
|
||||||
l.InterfaceElem.check(c, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *InterfaceElemNode) check(c *ctx, t *InterfaceTypeNode) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.MethodElem.check(c, t)
|
|
||||||
n.TypeElem.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodElemNode) check(c *ctx, t *InterfaceTypeNode) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nm := n.MethodName.Src()
|
|
||||||
if ex := t.methods[nm]; ex != nil {
|
|
||||||
panic(todo(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.methods == nil {
|
|
||||||
t.methods = map[string]*MethodElemNode{}
|
|
||||||
}
|
|
||||||
t.methods[nm] = n
|
|
||||||
n.typ = n.Signature.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeElemListNode) check(c *ctx) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
type InvalidType struct{}
|
|
||||||
|
|
||||||
func (n *InvalidType) Align() int { return 1 }
|
|
||||||
func (n *InvalidType) FieldAlign() int { return 1 }
|
|
||||||
func (n *InvalidType) Kind() Kind { return InvalidKind }
|
|
||||||
func (n *InvalidType) Position() (r token.Position) { return r }
|
|
||||||
func (n *InvalidType) Size() int64 { return 1 }
|
|
||||||
func (n *InvalidType) Source(full bool) string { return "<invalid type>" }
|
|
||||||
func (n *InvalidType) String() string { return "<invalid type>" }
|
|
||||||
func (n *InvalidType) check(c *ctx) Type { return n }
|
|
||||||
|
|
||||||
func (n *MapTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *MapTypeNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *MapTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *MapTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *MapTypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *MapTypeNode) check(c *ctx) Type { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) Align() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) Kind() Kind {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) Size() int64 {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) String() string {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedTypeNode) check(c *ctx) Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PointerTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *PointerTypeNode) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PointerTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *PointerTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *PointerTypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *PointerTypeNode) check(c *ctx) Type {
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
switch x := n.BaseType.(type) {
|
|
||||||
case *TypeNameNode:
|
|
||||||
x.checkDefined(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
type PredeclaredType struct {
|
|
||||||
Node
|
|
||||||
kind Kind
|
|
||||||
t ABIType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) newPredeclaredType(n Node, kind Kind) *PredeclaredType {
|
|
||||||
t, ok := c.cfg.abi.Types[kind]
|
|
||||||
if !ok && !isAnyUntypedKind(kind) {
|
|
||||||
panic(todo("%v: internal error %s: %s", n.Position(), n.Source(false), kind))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PredeclaredType{
|
|
||||||
Node: n,
|
|
||||||
kind: kind,
|
|
||||||
t: t,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PredeclaredType) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *PredeclaredType) FieldAlign() int {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PredeclaredType) Kind() Kind { return n.kind }
|
|
||||||
func (n *PredeclaredType) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *PredeclaredType) String() string {
|
|
||||||
switch n.Kind() {
|
|
||||||
case
|
|
||||||
String,
|
|
||||||
UntypedInt:
|
|
||||||
|
|
||||||
return n.Kind().String()
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %s %s", n.Position(), n.Kind(), n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PredeclaredType) check(c *ctx) Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *SliceTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *SliceTypeNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *SliceTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *SliceTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *SliceTypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *SliceTypeNode) check(c *ctx) Type {
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
switch x := n.ElementType.(type) {
|
|
||||||
case *TypeNameNode:
|
|
||||||
x.checkDefined(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
type Field struct {
|
|
||||||
Declaration *FieldDeclNode
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *StructTypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *StructTypeNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *StructTypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *StructTypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *StructTypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *StructTypeNode) check(c *ctx) Type {
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
if n.guard == guardChecking {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { n.guard = guardChecked }()
|
|
||||||
|
|
||||||
for l := n.FieldDeclList; l != nil; l = l.List {
|
|
||||||
n.fields = append(n.fields, l.check(c)...)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FieldDeclListNode) check(c *ctx) []Field {
|
|
||||||
return n.FieldDecl.check(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FieldDeclNode) check(c *ctx) (r []Field) {
|
|
||||||
switch {
|
|
||||||
case n.EmbeddedField != nil:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
default:
|
|
||||||
n.TypeNode.check(c)
|
|
||||||
for l := n.IdentifierList; l != nil; l = l.List {
|
|
||||||
r = append(r, Field{n, l.IDENT.Src()})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
type TupleType struct {
|
|
||||||
Node
|
|
||||||
Types []Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTupleType(n Node, types []Type) *TupleType { return &TupleType{n, types} }
|
|
||||||
|
|
||||||
func (n *TupleType) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TupleType) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TupleType) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *TupleType) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func (n *TupleType) Source(full bool) (r string) {
|
|
||||||
if n.Node != nil {
|
|
||||||
r = n.Node.Source(full)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TupleType) String() string {
|
|
||||||
var a []string
|
|
||||||
for _, v := range n.Types {
|
|
||||||
a = append(a, v.String())
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("(%s)", strings.Join(a, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TupleType) check(c *ctx) Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeDefNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeDefNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeDefNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeDefNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeDefNode) String() string { return fmt.Sprintf("%s.%s", n.pkg.ImportPath, n.IDENT.Src()) }
|
|
||||||
|
|
||||||
func (n *TypeDefNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.pkg != nil {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
n.pkg = c.pkg
|
|
||||||
if n.TypeParameters != nil {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x := n.TypeNode.check(c).(type) {
|
|
||||||
case *PredeclaredType:
|
|
||||||
n.TypeNode = x
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeNameNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNameNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNameNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNameNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNameNode) String() string { return n.Name.Source(false) }
|
|
||||||
|
|
||||||
func (n *TypeNameNode) checkDefined(c *ctx) bool {
|
|
||||||
switch x := n.Name.(type) {
|
|
||||||
case Token:
|
|
||||||
switch _, nmd := n.LexicalScope().lookup(x); y := nmd.n.(type) {
|
|
||||||
case *TypeDefNode, *AliasDeclNode:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
panic(todo("%v: type=%T %s", y.Position(), y, y.Source(false)))
|
|
||||||
}
|
|
||||||
case *QualifiedIdentNode:
|
|
||||||
if !token.IsExported(x.IDENT.Src()) {
|
|
||||||
panic(todo(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch _, nmd := n.LexicalScope().lookup(x.PackageName); y := nmd.n.(type) {
|
|
||||||
case *ImportSpecNode:
|
|
||||||
if y.pkg == nil {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch _, nmd := y.pkg.Scope.lookup(x.IDENT); z := nmd.n.(type) {
|
|
||||||
case *TypeDefNode, *AliasDeclNode:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
panic(todo("%v: type=%T %s", z.Position(), z, z.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: type=%T %s", y.Position(), y, y.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: type=%T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeNameNode) check(c *ctx) Type {
|
|
||||||
if n == nil {
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x := n.Name.(type) {
|
|
||||||
case Token:
|
|
||||||
nm := x.Src()
|
|
||||||
if c.isBuiltin() {
|
|
||||||
switch nm {
|
|
||||||
case "bool":
|
|
||||||
return c.newPredeclaredType(n, Bool)
|
|
||||||
case "uint8":
|
|
||||||
return c.newPredeclaredType(n, Uint8)
|
|
||||||
case "uint16":
|
|
||||||
return c.newPredeclaredType(n, Uint16)
|
|
||||||
case "uint32":
|
|
||||||
return c.newPredeclaredType(n, Uint32)
|
|
||||||
case "uint64":
|
|
||||||
return c.newPredeclaredType(n, Uint64)
|
|
||||||
case "int8":
|
|
||||||
return c.newPredeclaredType(n, Int8)
|
|
||||||
case "int16":
|
|
||||||
return c.newPredeclaredType(n, Int16)
|
|
||||||
case "int32":
|
|
||||||
return c.newPredeclaredType(n, Int32)
|
|
||||||
case "int64":
|
|
||||||
return c.newPredeclaredType(n, Int64)
|
|
||||||
case "float32":
|
|
||||||
return c.newPredeclaredType(n, Float32)
|
|
||||||
case "float64":
|
|
||||||
return c.newPredeclaredType(n, Float64)
|
|
||||||
case "complex64":
|
|
||||||
return c.newPredeclaredType(n, Complex64)
|
|
||||||
case "complex128":
|
|
||||||
return c.newPredeclaredType(n, Complex128)
|
|
||||||
case "string":
|
|
||||||
return c.newPredeclaredType(n, String)
|
|
||||||
case "int":
|
|
||||||
return c.newPredeclaredType(n, Int)
|
|
||||||
case "uint":
|
|
||||||
return c.newPredeclaredType(n, Uint)
|
|
||||||
case "uintptr":
|
|
||||||
return c.newPredeclaredType(n, Uintptr)
|
|
||||||
case "Type":
|
|
||||||
// ok
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg, _, nmd := c.lookup(n.LexicalScope(), x)
|
|
||||||
switch y := nmd.n.(type) {
|
|
||||||
case *TypeDefNode:
|
|
||||||
if pkg != c.pkg {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
return y.check(c)
|
|
||||||
case nil:
|
|
||||||
panic(todo("%v: %T %s", x.Position(), y, x.Source(false)))
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", y.Position(), y, y.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *TypeNode) Align() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNode) FieldAlign() int { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNode) Kind() Kind { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNode) Size() int64 { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNode) String() string { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
func (n *TypeNode) check(c *ctx) Type { panic(todo("%v: %T %s", n.Position(), n, n.Source(false))) }
|
|
||||||
|
|
||||||
func isAnyUntypedType(t Type) bool { return isAnyUntypedKind(t.Kind()) }
|
|
||||||
|
|
||||||
func isAnyUntypedKind(k Kind) bool {
|
|
||||||
switch k {
|
|
||||||
case UntypedBool, UntypedComplex, UntypedFloat, UntypedInt, UntypedNil, UntypedRune, UntypedString:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
guardUnchecked guard = iota
|
|
||||||
guardChecking
|
|
||||||
guardChecked
|
|
||||||
)
|
|
||||||
|
|
||||||
type guard byte
|
|
||||||
|
|
||||||
func (n *guard) enter(c *ctx, nd Node) bool {
|
|
||||||
switch *n {
|
|
||||||
case guardUnchecked:
|
|
||||||
*n = guardChecking
|
|
||||||
return true
|
|
||||||
case guardChecking:
|
|
||||||
c.err(nd, "invalid recursive type")
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isAnyArithmeticType(t Type) bool { return isArithmeticType(t) || isUntypedArithmeticType(t) }
|
|
||||||
|
|
||||||
func isUntypedArithmeticType(t Type) bool {
|
|
||||||
switch t.Kind() {
|
|
||||||
case UntypedInt, UntypedFloat, UntypedComplex:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isArithmeticType(t Type) bool {
|
|
||||||
return isIntegerType(t) || isFloatType(t) || isComplexType(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isComplexType(t Type) bool {
|
|
||||||
switch t.Kind() {
|
|
||||||
case Complex64, Complex128:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isFloatType(t Type) bool {
|
|
||||||
switch t.Kind() {
|
|
||||||
case Float32, Float64:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isIntegerType(t Type) bool {
|
|
||||||
switch t.Kind() {
|
|
||||||
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) isIdentical(n Node, t, u Type) bool {
|
|
||||||
tk := t.Kind()
|
|
||||||
uk := u.Kind()
|
|
||||||
if tk != uk {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == u {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if isAnyUntypedKind(tk) && isAnyUntypedKind(uk) && tk == uk {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch x := t.(type) {
|
|
||||||
// case *ArrayTypeNode:
|
|
||||||
// switch y := u.(type) {
|
|
||||||
// case *ArrayTypeNode:
|
|
||||||
// return x.Len == y.Len && c.isIdentical(n, x.Elem, y.Elem)
|
|
||||||
// }
|
|
||||||
// case *StructType:
|
|
||||||
// switch y := u.(type) {
|
|
||||||
// case *StructType:
|
|
||||||
// if len(x.Fields) != len(y.Fields) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for i, v := range x.Fields {
|
|
||||||
// w := y.Fields[i]
|
|
||||||
// if v.Name != w.Name || !c.isIdentical(n, v.Type(), w.Type()) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// case *FunctionType:
|
|
||||||
// switch y := u.(type) {
|
|
||||||
// case *FunctionType:
|
|
||||||
// in, out := x.Parameters.Types, x.Result.Types
|
|
||||||
// in2, out2 := y.Parameters.Types, y.Result.Types
|
|
||||||
// if len(in) != len(in2) || len(out) != len(out2) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for i, v := range in {
|
|
||||||
// if !c.isIdentical(n, v, in2[i]) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for i, v := range out {
|
|
||||||
// if !c.isIdentical(n, v, out2[i]) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// case *PointerType:
|
|
||||||
// switch y := u.(type) {
|
|
||||||
// case *PointerType:
|
|
||||||
// return c.isIdentical(n, x.Elem, y.Elem)
|
|
||||||
// }
|
|
||||||
default:
|
|
||||||
c.err(n, "TODO %v %v", x, u)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) mustIdentical(n Node, t, u Type) bool {
|
|
||||||
if !c.isIdentical(n, t, u) {
|
|
||||||
c.err(n, "incompatible types: %v and %v", t, u)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) checkType(n Node) Type {
|
|
||||||
switch x := n.(type) {
|
|
||||||
case *ArrayTypeNode:
|
|
||||||
return x.check(c)
|
|
||||||
default:
|
|
||||||
c.err(n, "TODO %T", x)
|
|
||||||
return Invalid
|
|
||||||
}
|
|
||||||
}
|
|
716
vendor/modernc.org/gc/v3/value.go
generated
vendored
716
vendor/modernc.org/gc/v3/value.go
generated
vendored
|
@ -1,716 +0,0 @@
|
||||||
// Copyright 2022 The Gc 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 gc // modernc.org/gc/v3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/constant"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ Expression = (*BasicLitNode)(nil)
|
|
||||||
_ Expression = (*BinaryExpressionNode)(nil)
|
|
||||||
_ Expression = (*CompositeLitNode)(nil)
|
|
||||||
_ Expression = (*ConversionNode)(nil)
|
|
||||||
_ Expression = (*FunctionLitNode)(nil)
|
|
||||||
_ Expression = (*KeyedElementNode)(nil)
|
|
||||||
_ Expression = (*LiteralValueNode)(nil)
|
|
||||||
_ Expression = (*MethodExprNode)(nil)
|
|
||||||
_ Expression = (*OperandNameNode)(nil)
|
|
||||||
_ Expression = (*OperandNode)(nil)
|
|
||||||
_ Expression = (*OperandQualifiedNameNode)(nil)
|
|
||||||
_ Expression = (*ParenthesizedExpressionNode)(nil)
|
|
||||||
_ Expression = (*PrimaryExprNode)(nil)
|
|
||||||
_ Expression = (*UnaryExprNode)(nil)
|
|
||||||
_ Expression = (*ValueExpression)(nil)
|
|
||||||
|
|
||||||
falseVal = constant.MakeBool(false)
|
|
||||||
trueVal = constant.MakeBool(true)
|
|
||||||
unknown = constant.MakeUnknown()
|
|
||||||
)
|
|
||||||
|
|
||||||
func known(v constant.Value) bool { return v != nil && v.Kind() != constant.Unknown }
|
|
||||||
|
|
||||||
type valueCache struct {
|
|
||||||
v constant.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *valueCache) Value() constant.Value {
|
|
||||||
if n.v != nil {
|
|
||||||
return n.v
|
|
||||||
}
|
|
||||||
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *valueCache) setValue(v constant.Value) constant.Value {
|
|
||||||
n.v = v
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
type valuer interface {
|
|
||||||
Value() constant.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
type Expression interface {
|
|
||||||
Node
|
|
||||||
checkExpr(c *ctx) Expression
|
|
||||||
clone() Expression
|
|
||||||
typer
|
|
||||||
valuer
|
|
||||||
}
|
|
||||||
|
|
||||||
type ValueExpression struct {
|
|
||||||
Node
|
|
||||||
typeCache
|
|
||||||
valueCache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ValueExpression) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ValueExpression) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BasicLitNode) Type() Type {
|
|
||||||
switch n.Ch() {
|
|
||||||
case CHAR:
|
|
||||||
return n.ctx.int32
|
|
||||||
case INT:
|
|
||||||
return n.ctx.untypedInt
|
|
||||||
case FLOAT:
|
|
||||||
return n.ctx.untypedFloat
|
|
||||||
case STRING:
|
|
||||||
return n.ctx.untypedString
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s %v", n.Position(), n, n.Source(false), n.Ch()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BasicLitNode) Value() constant.Value {
|
|
||||||
return constant.MakeFromLiteral(n.Src(), n.Ch(), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BasicLitNode) checkExpr(c *ctx) Expression {
|
|
||||||
n.ctx = c
|
|
||||||
if !known(n.Value()) {
|
|
||||||
c.err(n, "invalid literal: %s", n.Source(false))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BasicLitNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNameNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNameNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNameNode) checkExpr(c *ctx) Expression {
|
|
||||||
in, named := n.LexicalScope().lookup(n.Name)
|
|
||||||
switch x := named.n.(type) {
|
|
||||||
case *ConstSpecNode:
|
|
||||||
switch in.kind {
|
|
||||||
case UniverseScope:
|
|
||||||
switch n.Name.Src() {
|
|
||||||
case "iota":
|
|
||||||
if c.iota < 0 {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &ValueExpression{Node: x}
|
|
||||||
r.t = c.untypedInt
|
|
||||||
r.v = constant.MakeInt64(c.iota)
|
|
||||||
return r
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return x.Expression
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNameNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedExpressionNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedExpressionNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedExpressionNode) checkExpr(c *ctx) Expression {
|
|
||||||
return n.Expression.checkExpr(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ParenthesizedExpressionNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *KeyedElementNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *KeyedElementNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *KeyedElementNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *KeyedElementNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *CompositeLitNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *CompositeLitNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *CompositeLitNode) checkExpr(c *ctx) Expression {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !n.enter(c, n) {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
t := n.setType(c.checkType(n.LiteralType))
|
|
||||||
n.LiteralValue.check(c, t)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *CompositeLitNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) check(c *ctx, t Type) {
|
|
||||||
if n == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case Array:
|
|
||||||
n.checkArray(c, t.(*ArrayTypeNode))
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s %v", n.Position(), n, n.Source(false), t.Kind()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LiteralValueNode) checkArray(c *ctx, t *ArrayTypeNode) {
|
|
||||||
panic(todo("%v: %T %s %s", n.Position(), n, t, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionLitNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionLitNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionLitNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *FunctionLitNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandQualifiedNameNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandQualifiedNameNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandQualifiedNameNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *OperandQualifiedNameNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ConversionNode) Type() Type {
|
|
||||||
return n.TypeNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ConversionNode) checkExpr(c *ctx) Expression {
|
|
||||||
t := n.TypeNode.check(c)
|
|
||||||
n.Expression = n.Expression.checkExpr(c)
|
|
||||||
v := n.Expression.Value()
|
|
||||||
n.v = c.convertValue(n.Expression, v, t)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *ConversionNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodExprNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodExprNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodExprNode) checkExpr(c *ctx) Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *MethodExprNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PrimaryExprNode) Type() Type {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PrimaryExprNode) Value() constant.Value {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PrimaryExprNode) checkExpr(c *ctx) Expression {
|
|
||||||
switch x := n.PrimaryExpr.(type) {
|
|
||||||
case *OperandNameNode:
|
|
||||||
_, named := x.LexicalScope().lookup(x.Name)
|
|
||||||
switch y := named.n.(type) {
|
|
||||||
case *TypeDefNode:
|
|
||||||
switch z := n.Postfix.(type) {
|
|
||||||
case *ArgumentsNode:
|
|
||||||
cnv := &ConversionNode{
|
|
||||||
TypeNode: &TypeNameNode{
|
|
||||||
Name: x.Name,
|
|
||||||
lexicalScoper: x.lexicalScoper,
|
|
||||||
},
|
|
||||||
LPAREN: z.LPAREN,
|
|
||||||
Expression: z.Expression,
|
|
||||||
RPAREN: z.RPAREN,
|
|
||||||
}
|
|
||||||
return cnv.checkExpr(c)
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), z, n.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), y, n.Source(false)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
n.PrimaryExpr = n.PrimaryExpr.checkExpr(c)
|
|
||||||
switch x := n.Postfix.(type) {
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *PrimaryExprNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BinaryExpressionNode) checkExpr(c *ctx) (r Expression) {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.typeCache.Type() != Invalid {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
n.LHS = n.LHS.checkExpr(c)
|
|
||||||
n.RHS = n.RHS.checkExpr(c)
|
|
||||||
lv := n.LHS.Value()
|
|
||||||
lt := n.LHS.Type()
|
|
||||||
rv := n.RHS.Value()
|
|
||||||
rt := n.RHS.Type()
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if known(lv) && known(rv) && r != nil && !known(r.Value()) {
|
|
||||||
c.err(n.Op, "operation value not determined: %v %s %v", lv, n.Op.Src(), rv)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
switch n.Op.Ch() {
|
|
||||||
case SHL, SHR:
|
|
||||||
var u uint64
|
|
||||||
var uOk bool
|
|
||||||
n.t = lt
|
|
||||||
// The right operand in a shift expression must have integer type or be an
|
|
||||||
// untyped constant representable by a value of type uint.
|
|
||||||
switch {
|
|
||||||
case isIntegerType(rt):
|
|
||||||
// ok
|
|
||||||
case known(rv):
|
|
||||||
if isAnyArithmeticType(rt) {
|
|
||||||
rv = c.convertValue(n.RHS, rv, c.cfg.uint)
|
|
||||||
if known(rv) {
|
|
||||||
u, uOk = constant.Uint64Val(rv)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
c.err(n.Op, "TODO %v", n.Op.Src())
|
|
||||||
return n
|
|
||||||
default:
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the left operand of a non-constant shift expression is an untyped
|
|
||||||
// constant, it is first implicitly converted to the type it would assume if
|
|
||||||
// the shift expression were replaced by its left operand alone.
|
|
||||||
switch {
|
|
||||||
case known(lv) && !known(rv):
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
// c.err(n.Op, "TODO %v", n.Op.Ch.str())
|
|
||||||
// return n
|
|
||||||
case known(lv) && known(rv):
|
|
||||||
if !uOk {
|
|
||||||
panic(todo(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
n.t = lt
|
|
||||||
n.v = constant.Shift(lv, n.Op.Ch(), uint(u))
|
|
||||||
default:
|
|
||||||
trc("", known(lv), known(rv), u, uOk)
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
// n.t = lt
|
|
||||||
// n.v = constant.BinaryOp(lv, n.Op.Ch(), rv)
|
|
||||||
}
|
|
||||||
case ADD, SUB, MUL, QUO, REM:
|
|
||||||
if !isAnyArithmeticType(lt) || !isAnyArithmeticType(rt) {
|
|
||||||
c.err(n.Op, "TODO %v %v", lt, rt)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// For other binary operators, the operand types must be identical unless the
|
|
||||||
// operation involves shifts or untyped constants.
|
|
||||||
//
|
|
||||||
// Except for shift operations, if one operand is an untyped constant and the
|
|
||||||
// other operand is not, the constant is implicitly converted to the type of
|
|
||||||
// the other operand.
|
|
||||||
switch {
|
|
||||||
case isAnyUntypedType(lt) && isAnyUntypedType(rt):
|
|
||||||
n.v = constant.BinaryOp(lv, n.Op.Ch(), rv)
|
|
||||||
switch n.v.Kind() {
|
|
||||||
case constant.Int:
|
|
||||||
n.t = c.untypedInt
|
|
||||||
case constant.Float:
|
|
||||||
n.t = c.untypedFloat
|
|
||||||
default:
|
|
||||||
c.err(n.Op, "TODO %v %v %q %v %v -> %v %v", lv, lt, n.Op.Src(), rv, rt, n.v, n.v.Kind())
|
|
||||||
}
|
|
||||||
case isAnyUntypedType(lt) && !isAnyUntypedType(rt):
|
|
||||||
c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
|
|
||||||
case !isAnyUntypedType(lt) && isAnyUntypedType(rt):
|
|
||||||
c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
|
|
||||||
default: // case !isAnyUntypedType(lt) && !isAnyUntypedType(rt):
|
|
||||||
c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BinaryExpressionNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *UnaryExprNode) checkExpr(c *ctx) Expression {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.typeCache.Type() != Invalid {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
n.UnaryExpr = n.UnaryExpr.checkExpr(c)
|
|
||||||
v := n.UnaryExpr.Value()
|
|
||||||
t := n.UnaryExpr.Type()
|
|
||||||
switch n.Op.Ch() {
|
|
||||||
default:
|
|
||||||
trc("", v, t)
|
|
||||||
panic(todo("%v: %T %s", n.Op.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *UnaryExprNode) clone() Expression {
|
|
||||||
panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctx) convertValue(n Node, v constant.Value, to Type) (r constant.Value) {
|
|
||||||
if !known(v) {
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
switch to.Kind() {
|
|
||||||
case
|
|
||||||
Complex128,
|
|
||||||
Complex64,
|
|
||||||
Function,
|
|
||||||
Interface,
|
|
||||||
Map,
|
|
||||||
Pointer,
|
|
||||||
Slice,
|
|
||||||
String,
|
|
||||||
Struct,
|
|
||||||
Tuple,
|
|
||||||
UnsafePointer,
|
|
||||||
UntypedBool,
|
|
||||||
UntypedComplex,
|
|
||||||
UntypedFloat,
|
|
||||||
UntypedInt,
|
|
||||||
UntypedNil,
|
|
||||||
UntypedRune,
|
|
||||||
UntypedString:
|
|
||||||
|
|
||||||
c.err(n, "TODO %v -> %v", v, to)
|
|
||||||
case Int:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
i64, ok := constant.Int64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c.cfg.goarch {
|
|
||||||
case "386", "arm":
|
|
||||||
if i64 < math.MinInt32 || i64 > math.MaxInt32 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w
|
|
||||||
case Int8:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
i64, ok := constant.Int64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if i64 < math.MinInt8 || i64 > math.MaxInt8 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Int16:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
i64, ok := constant.Int64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if i64 < math.MinInt16 || i64 > math.MaxInt16 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Int32:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
i64, ok := constant.Int64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if i64 < math.MinInt32 || i64 > math.MaxInt32 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Int64:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := constant.Int64Val(w); !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Uint, Uintptr:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
u64, ok := constant.Uint64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c.cfg.goarch {
|
|
||||||
case "386", "arm":
|
|
||||||
if u64 > math.MaxUint32 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w
|
|
||||||
case Uint8:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
u64, ok := constant.Uint64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if u64 > math.MaxUint8 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Uint16:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
u64, ok := constant.Uint64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if u64 > math.MaxUint16 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Uint32:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
u64, ok := constant.Uint64Val(w)
|
|
||||||
if !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if u64 > math.MaxUint32 {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Uint64:
|
|
||||||
w := constant.ToInt(v)
|
|
||||||
if !known(w) {
|
|
||||||
c.err(n, "cannot convert %s to %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := constant.Uint64Val(w); !ok {
|
|
||||||
c.err(n, "value %s overflows %s", v, to)
|
|
||||||
return unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
return w
|
|
||||||
case Float32, Float64:
|
|
||||||
return constant.ToFloat(v)
|
|
||||||
case Bool:
|
|
||||||
if v.Kind() == constant.Bool {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return unknown
|
|
||||||
}
|
|
9
vendor/modernc.org/sqlite/Makefile
generated
vendored
9
vendor/modernc.org/sqlite/Makefile
generated
vendored
|
@ -37,8 +37,8 @@ build_all_targets:
|
||||||
GOOS=linux GOARCH=riscv64 go build -v ./...
|
GOOS=linux GOARCH=riscv64 go build -v ./...
|
||||||
GOOS=linux GOARCH=s390x go test -c -o /dev/null
|
GOOS=linux GOARCH=s390x go test -c -o /dev/null
|
||||||
GOOS=linux GOARCH=s390x go build -v ./...
|
GOOS=linux GOARCH=s390x go build -v ./...
|
||||||
GOOS=netbsd GOARCH=amd64 go test -c -o /dev/null
|
# GOOS=netbsd GOARCH=amd64 go test -c -o /dev/null
|
||||||
GOOS=netbsd GOARCH=amd64 go build -v ./...
|
# GOOS=netbsd GOARCH=amd64 go build -v ./...
|
||||||
GOOS=openbsd GOARCH=amd64 go test -c -o /dev/null
|
GOOS=openbsd GOARCH=amd64 go test -c -o /dev/null
|
||||||
GOOS=openbsd GOARCH=amd64 go build -v ./...
|
GOOS=openbsd GOARCH=amd64 go build -v ./...
|
||||||
GOOS=openbsd GOARCH=arm64 go test -c -o /dev/null
|
GOOS=openbsd GOARCH=arm64 go test -c -o /dev/null
|
||||||
|
@ -69,7 +69,10 @@ test:
|
||||||
go test -v -timeout 24h 2>&1 | tee log-test
|
go test -v -timeout 24h 2>&1 | tee log-test
|
||||||
|
|
||||||
vendor:
|
vendor:
|
||||||
go run vendor_libsqlite3.go && make build_all_targets
|
cd vendor_libsqlite3 && go build -o ../vendor main.go
|
||||||
|
./vendor
|
||||||
|
rm -f vendor
|
||||||
|
make build_all_targets
|
||||||
make build_all_targets
|
make build_all_targets
|
||||||
|
|
||||||
work:
|
work:
|
||||||
|
|
6
vendor/modernc.org/sqlite/lib/hooks.go
generated
vendored
6
vendor/modernc.org/sqlite/lib/hooks.go
generated
vendored
|
@ -2,6 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !(linux && arm64)
|
||||||
|
|
||||||
package sqlite3
|
package sqlite3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -12,3 +14,7 @@
|
||||||
func X__ccgo_sqlite3_log(t *libc.TLS, iErrCode int32, zFormat uintptr, va uintptr) { /* sqlite3.c:29405:17: */
|
func X__ccgo_sqlite3_log(t *libc.TLS, iErrCode int32, zFormat uintptr, va uintptr) { /* sqlite3.c:29405:17: */
|
||||||
libc.X__ccgo_sqlite3_log(t, iErrCode, zFormat, va)
|
libc.X__ccgo_sqlite3_log(t, iErrCode, zFormat, va)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PatchIssue199() {
|
||||||
|
// nop
|
||||||
|
}
|
||||||
|
|
30
vendor/modernc.org/sqlite/lib/hooks_linux_arm64.go
generated
vendored
Normal file
30
vendor/modernc.org/sqlite/lib/hooks_linux_arm64.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2019 The Sqlite 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 sqlite3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"modernc.org/libc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Format and write a message to the log if logging is enabled.
|
||||||
|
func X__ccgo_sqlite3_log(t *libc.TLS, iErrCode int32, zFormat uintptr, va uintptr) { /* sqlite3.c:29405:17: */
|
||||||
|
libc.X__ccgo_sqlite3_log(t, iErrCode, zFormat, va)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gitlab.com/cznic/sqlite/-/issues/199
|
||||||
|
//
|
||||||
|
// We are currently stuck on libc@v1.55.3. Until that is resolved - fix the
|
||||||
|
// problem at runtime.
|
||||||
|
func PatchIssue199() {
|
||||||
|
p := unsafe.Pointer(&_aSyscall)
|
||||||
|
*(*uintptr)(unsafe.Add(p, 608)) = __ccgo_fp(_unixGetpagesizeIssue199)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _unixGetpagesizeIssue199(tls *libc.TLS) (r int32) {
|
||||||
|
return int32(syscall.Getpagesize())
|
||||||
|
}
|
5
vendor/modernc.org/sqlite/sqlite.go
generated
vendored
5
vendor/modernc.org/sqlite/sqlite.go
generated
vendored
|
@ -55,6 +55,11 @@
|
||||||
sqliteLockedSharedcache = sqlite3.SQLITE_LOCKED | (1 << 8)
|
sqliteLockedSharedcache = sqlite3.SQLITE_LOCKED | (1 << 8)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// https://gitlab.com/cznic/sqlite/-/issues/199
|
||||||
|
func init() {
|
||||||
|
sqlite3.PatchIssue199()
|
||||||
|
}
|
||||||
|
|
||||||
// Error represents sqlite library error code.
|
// Error represents sqlite library error code.
|
||||||
type Error struct {
|
type Error struct {
|
||||||
msg string
|
msg string
|
||||||
|
|
126
vendor/modernc.org/sqlite/vendor_libsqlite3.go
generated
vendored
126
vendor/modernc.org/sqlite/vendor_libsqlite3.go
generated
vendored
|
@ -1,126 +0,0 @@
|
||||||
// Copyright 2024 The Sqlite Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build none
|
|
||||||
// +build none
|
|
||||||
|
|
||||||
// Tool for 1.28+ -> 1.29+. Pulls adjusted libsqlite3 code to this repo.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"modernc.org/gc/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fail(rc int, msg string, args ...any) {
|
|
||||||
fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprintf(msg, args...)))
|
|
||||||
os.Exit(rc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
for _, v := range []struct{ goos, goarch string }{
|
|
||||||
{"darwin", "amd64"},
|
|
||||||
{"darwin", "arm64"},
|
|
||||||
{"freebsd", "amd64"},
|
|
||||||
{"freebsd", "arm64"},
|
|
||||||
{"linux", "386"},
|
|
||||||
{"linux", "amd64"},
|
|
||||||
{"linux", "arm"},
|
|
||||||
{"linux", "arm64"},
|
|
||||||
{"linux", "loong64"},
|
|
||||||
{"linux", "ppc64le"},
|
|
||||||
{"linux", "riscv64"},
|
|
||||||
{"linux", "s390x"},
|
|
||||||
{"windows", "386"},
|
|
||||||
{"windows", "amd64"},
|
|
||||||
} {
|
|
||||||
base := fmt.Sprintf("ccgo_%s_%s.go", v.goos, v.goarch)
|
|
||||||
if v.goos == "windows" && v.goarch == "amd64" {
|
|
||||||
base = "ccgo_windows.go"
|
|
||||||
}
|
|
||||||
ifn := filepath.Join("..", "libsqlite3", base)
|
|
||||||
fmt.Printf("%s/%s\t%s\n", v.goos, v.goarch, ifn)
|
|
||||||
in, err := os.ReadFile(ifn)
|
|
||||||
if err != nil {
|
|
||||||
fail(1, "%s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ast, err := gc.ParseFile(ifn, in)
|
|
||||||
if err != nil {
|
|
||||||
fail(1, "%s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
s := ast.SourceFile.PackageClause.Source(true)
|
|
||||||
s = strings.Replace(s, "package libsqlite3", "package sqlite3", 1)
|
|
||||||
fmt.Fprintln(b, s)
|
|
||||||
fmt.Fprint(b, ast.SourceFile.ImportDeclList.Source(true))
|
|
||||||
taken := map[string]struct{}{}
|
|
||||||
for n := ast.SourceFile.TopLevelDeclList; n != nil; n = n.List {
|
|
||||||
switch x := n.TopLevelDecl.(type) {
|
|
||||||
case *gc.TypeDeclNode:
|
|
||||||
adn := x.TypeSpecList.TypeSpec.(*gc.AliasDeclNode)
|
|
||||||
nm := adn.IDENT.Src()
|
|
||||||
taken[nm] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loop:
|
|
||||||
for n := ast.SourceFile.TopLevelDeclList; n != nil; n = n.List {
|
|
||||||
switch x := n.TopLevelDecl.(type) {
|
|
||||||
case *gc.ConstDeclNode:
|
|
||||||
switch y := x.ConstSpec.(type) {
|
|
||||||
case *gc.ConstSpecNode:
|
|
||||||
if y.IDENT.Src() != "SQLITE_TRANSIENT" {
|
|
||||||
fmt.Fprintln(b, x.Source(true))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("%v: %T %q", x.Position(), y, x.Source(false)))
|
|
||||||
}
|
|
||||||
|
|
||||||
case *gc.FunctionDeclNode:
|
|
||||||
fmt.Fprintln(b, x.Source(true))
|
|
||||||
case *gc.TypeDeclNode:
|
|
||||||
fmt.Fprintln(b, x.Source(true))
|
|
||||||
adn := x.TypeSpecList.TypeSpec.(*gc.AliasDeclNode)
|
|
||||||
nm := adn.IDENT.Src()
|
|
||||||
nm2 := nm[1:]
|
|
||||||
if _, ok := taken[nm2]; ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if token.IsExported(nm) {
|
|
||||||
fmt.Fprintf(b, "\ntype %s = %s\n", nm2, nm)
|
|
||||||
}
|
|
||||||
case *gc.VarDeclNode:
|
|
||||||
fmt.Fprintln(b, x.Source(true))
|
|
||||||
default:
|
|
||||||
fmt.Printf("%v: TODO %T\n", n.Position(), x)
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteString(`
|
|
||||||
type Sqlite3_int64 = sqlite3_int64
|
|
||||||
type Sqlite3_mutex_methods = sqlite3_mutex_methods
|
|
||||||
type Sqlite3_value = sqlite3_value
|
|
||||||
|
|
||||||
type Sqlite3_index_info = sqlite3_index_info
|
|
||||||
type Sqlite3_module = sqlite3_module
|
|
||||||
type Sqlite3_vtab = sqlite3_vtab
|
|
||||||
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
|
|
||||||
|
|
||||||
`)
|
|
||||||
base = strings.Replace(base, "ccgo_", "sqlite_", 1)
|
|
||||||
if err := os.WriteFile(filepath.Join("lib", base), b.Bytes(), 0660); err != nil {
|
|
||||||
fail(1, "%s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
12
vendor/modernc.org/strutil/AUTHORS
generated
vendored
12
vendor/modernc.org/strutil/AUTHORS
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
# This file lists authors for copyright purposes. This file is distinct from
|
|
||||||
# the CONTRIBUTORS files. See the latter for an explanation.
|
|
||||||
#
|
|
||||||
# Names should be added to this file as:
|
|
||||||
# Name or Organization <email address>
|
|
||||||
#
|
|
||||||
# The email address is not required for organizations.
|
|
||||||
#
|
|
||||||
# Please keep the list sorted.
|
|
||||||
|
|
||||||
CZ.NIC z.s.p.o. <kontakt@nic.cz>
|
|
||||||
Jan Mercl <0xjnml@gmail.com>
|
|
9
vendor/modernc.org/strutil/CONTRIBUTORS
generated
vendored
9
vendor/modernc.org/strutil/CONTRIBUTORS
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
# This file lists people who contributed code to this repository. The AUTHORS
|
|
||||||
# file lists the copyright holders; this file lists people.
|
|
||||||
#
|
|
||||||
# Names should be added to this file like so:
|
|
||||||
# Name <email address>
|
|
||||||
#
|
|
||||||
# Please keep the list sorted.
|
|
||||||
|
|
||||||
Jan Mercl <0xjnml@gmail.com>
|
|
27
vendor/modernc.org/strutil/LICENSE
generated
vendored
27
vendor/modernc.org/strutil/LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 2014 The strutil Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the names of the authors nor the names of the
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
59
vendor/modernc.org/strutil/Makefile
generated
vendored
59
vendor/modernc.org/strutil/Makefile
generated
vendored
|
@ -1,59 +0,0 @@
|
||||||
# Copyright (c) 2014 The sortutil Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
.PHONY: all clean cover cpu editor internalError later mem nuke todo edit
|
|
||||||
|
|
||||||
grep=--include=*.go --include=*.l --include=*.y --include=*.yy
|
|
||||||
ngrep='TODOOK\|parser\.go\|scanner\.go\|.*_string\.go'
|
|
||||||
|
|
||||||
all: editor
|
|
||||||
go vet 2>&1 | grep -v $(ngrep) || true
|
|
||||||
golint 2>&1 | grep -v $(ngrep) || true
|
|
||||||
make todo
|
|
||||||
unused . || true
|
|
||||||
misspell *.go
|
|
||||||
gosimple || true
|
|
||||||
maligned || true
|
|
||||||
unconvert -apply
|
|
||||||
|
|
||||||
clean:
|
|
||||||
go clean
|
|
||||||
rm -f *~ *.test *.out
|
|
||||||
|
|
||||||
cover:
|
|
||||||
t=$(shell tempfile) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t
|
|
||||||
|
|
||||||
cpu: clean
|
|
||||||
go test -run @ -bench . -cpuprofile cpu.out
|
|
||||||
go tool pprof -lines *.test cpu.out
|
|
||||||
|
|
||||||
edit:
|
|
||||||
@ 1>/dev/null 2>/dev/null gvim -p Makefile *.go
|
|
||||||
|
|
||||||
editor:
|
|
||||||
unconvert -apply || true
|
|
||||||
gofmt -l -s -w *.go
|
|
||||||
go test -i
|
|
||||||
go test 2>&1 | tee log
|
|
||||||
go install
|
|
||||||
|
|
||||||
internalError:
|
|
||||||
egrep -ho '"internal error.*"' *.go | sort | cat -n
|
|
||||||
|
|
||||||
later:
|
|
||||||
@grep -n $(grep) LATER * || true
|
|
||||||
@grep -n $(grep) MAYBE * || true
|
|
||||||
|
|
||||||
mem: clean
|
|
||||||
go test -run @ -bench . -memprofile mem.out -memprofilerate 1 -timeout 24h
|
|
||||||
go tool pprof -lines -web -alloc_space *.test mem.out
|
|
||||||
|
|
||||||
nuke: clean
|
|
||||||
go clean -i
|
|
||||||
|
|
||||||
todo:
|
|
||||||
@grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) TODO * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) BUG * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true
|
|
8
vendor/modernc.org/strutil/README
generated
vendored
8
vendor/modernc.org/strutil/README
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
modernc.orgall-able mirror of modified code already published at:
|
|
||||||
http://git.nic.cz/redmine/projects/gostrutil/repository
|
|
||||||
|
|
||||||
Online godoc documentation for this package (should be) available at:
|
|
||||||
http://gopkgdoc.appspot.com/pkg/modernc.org/strutil
|
|
||||||
|
|
||||||
Installation:
|
|
||||||
$ go get modernc.org/strutil
|
|
733
vendor/modernc.org/strutil/strutil.go
generated
vendored
733
vendor/modernc.org/strutil/strutil.go
generated
vendored
|
@ -1,733 +0,0 @@
|
||||||
// Copyright (c) 2014 The sortutil 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 strutil collects utils supplemental to the standard strings package.
|
|
||||||
package strutil // import "modernc.org/strutil"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/base32"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Base32ExtDecode decodes base32 extended (RFC 4648) text to binary data.
|
|
||||||
func Base32ExtDecode(text []byte) (data []byte, err error) {
|
|
||||||
n := base32.HexEncoding.DecodedLen(len(text))
|
|
||||||
data = make([]byte, n)
|
|
||||||
decoder := base32.NewDecoder(base32.HexEncoding, bytes.NewBuffer(text))
|
|
||||||
if n, err = decoder.Read(data); err != nil {
|
|
||||||
n = 0
|
|
||||||
}
|
|
||||||
data = data[:n]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base32ExtEncode encodes binary data to base32 extended (RFC 4648) encoded text.
|
|
||||||
func Base32ExtEncode(data []byte) (text []byte) {
|
|
||||||
n := base32.HexEncoding.EncodedLen(len(data))
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, n))
|
|
||||||
encoder := base32.NewEncoder(base32.HexEncoding, buf)
|
|
||||||
encoder.Write(data)
|
|
||||||
encoder.Close()
|
|
||||||
if buf.Len() != n {
|
|
||||||
panic("internal error")
|
|
||||||
}
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base64Decode decodes base64 text to binary data.
|
|
||||||
func Base64Decode(text []byte) (data []byte, err error) {
|
|
||||||
n := base64.StdEncoding.DecodedLen(len(text))
|
|
||||||
data = make([]byte, n)
|
|
||||||
decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(text))
|
|
||||||
if n, err = decoder.Read(data); err != nil {
|
|
||||||
n = 0
|
|
||||||
}
|
|
||||||
data = data[:n]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base64Encode encodes binary data to base64 encoded text.
|
|
||||||
func Base64Encode(data []byte) (text []byte) {
|
|
||||||
n := base64.StdEncoding.EncodedLen(len(data))
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, n))
|
|
||||||
encoder := base64.NewEncoder(base64.StdEncoding, buf)
|
|
||||||
encoder.Write(data)
|
|
||||||
encoder.Close()
|
|
||||||
if buf.Len() != n {
|
|
||||||
panic("internal error")
|
|
||||||
}
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formatter is an io.Writer extended by a fmt.Printf like function Format
|
|
||||||
type Formatter interface {
|
|
||||||
io.Writer
|
|
||||||
Format(format string, args ...interface{}) (n int, errno error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type indentFormatter struct {
|
|
||||||
io.Writer
|
|
||||||
indent []byte
|
|
||||||
indentLevel int
|
|
||||||
state int
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
st0 = iota
|
|
||||||
stBOL
|
|
||||||
stPERC
|
|
||||||
stBOLPERC
|
|
||||||
)
|
|
||||||
|
|
||||||
// IndentFormatter returns a new Formatter which interprets %i and %u in the
|
|
||||||
// Format() format string as indent and undent commands. The commands can
|
|
||||||
// nest. The Formatter writes to io.Writer 'w' and inserts one 'indent'
|
|
||||||
// string per current indent level value.
|
|
||||||
// Behaviour of commands reaching negative indent levels is undefined.
|
|
||||||
// IndentFormatter(os.Stdout, "\t").Format("abc%d%%e%i\nx\ny\n%uz\n", 3)
|
|
||||||
// output:
|
|
||||||
// abc3%e
|
|
||||||
// x
|
|
||||||
// y
|
|
||||||
// z
|
|
||||||
// The Go quoted string literal form of the above is:
|
|
||||||
// "abc%%e\n\tx\n\tx\nz\n"
|
|
||||||
// The commands can be scattered between separate invocations of Format(),
|
|
||||||
// i.e. the formatter keeps track of the indent level and knows if it is
|
|
||||||
// positioned on start of a line and should emit indentation(s).
|
|
||||||
// The same output as above can be produced by e.g.:
|
|
||||||
// f := IndentFormatter(os.Stdout, " ")
|
|
||||||
// f.Format("abc%d%%e%i\nx\n", 3)
|
|
||||||
// f.Format("y\n%uz\n")
|
|
||||||
func IndentFormatter(w io.Writer, indent string) Formatter {
|
|
||||||
return &indentFormatter{w, []byte(indent), 0, stBOL}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *indentFormatter) format(flat bool, format string, args ...interface{}) (n int, errno error) {
|
|
||||||
buf := []byte{}
|
|
||||||
for i := 0; i < len(format); i++ {
|
|
||||||
c := format[i]
|
|
||||||
switch f.state {
|
|
||||||
case st0:
|
|
||||||
switch c {
|
|
||||||
case '\n':
|
|
||||||
cc := c
|
|
||||||
if flat && f.indentLevel != 0 {
|
|
||||||
cc = ' '
|
|
||||||
}
|
|
||||||
buf = append(buf, cc)
|
|
||||||
f.state = stBOL
|
|
||||||
case '%':
|
|
||||||
f.state = stPERC
|
|
||||||
default:
|
|
||||||
buf = append(buf, c)
|
|
||||||
}
|
|
||||||
case stBOL:
|
|
||||||
switch c {
|
|
||||||
case '\n':
|
|
||||||
cc := c
|
|
||||||
if flat && f.indentLevel != 0 {
|
|
||||||
cc = ' '
|
|
||||||
}
|
|
||||||
buf = append(buf, cc)
|
|
||||||
case '%':
|
|
||||||
f.state = stBOLPERC
|
|
||||||
default:
|
|
||||||
if !flat {
|
|
||||||
for i := 0; i < f.indentLevel; i++ {
|
|
||||||
buf = append(buf, f.indent...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf = append(buf, c)
|
|
||||||
f.state = st0
|
|
||||||
}
|
|
||||||
case stBOLPERC:
|
|
||||||
switch c {
|
|
||||||
case 'i':
|
|
||||||
f.indentLevel++
|
|
||||||
f.state = stBOL
|
|
||||||
case 'u':
|
|
||||||
f.indentLevel--
|
|
||||||
f.state = stBOL
|
|
||||||
default:
|
|
||||||
if !flat {
|
|
||||||
for i := 0; i < f.indentLevel; i++ {
|
|
||||||
buf = append(buf, f.indent...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf = append(buf, '%', c)
|
|
||||||
f.state = st0
|
|
||||||
}
|
|
||||||
case stPERC:
|
|
||||||
switch c {
|
|
||||||
case 'i':
|
|
||||||
f.indentLevel++
|
|
||||||
f.state = st0
|
|
||||||
case 'u':
|
|
||||||
f.indentLevel--
|
|
||||||
f.state = st0
|
|
||||||
default:
|
|
||||||
buf = append(buf, '%', c)
|
|
||||||
f.state = st0
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unexpected state")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch f.state {
|
|
||||||
case stPERC, stBOLPERC:
|
|
||||||
buf = append(buf, '%')
|
|
||||||
}
|
|
||||||
return f.Write([]byte(fmt.Sprintf(string(buf), args...)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *indentFormatter) Format(format string, args ...interface{}) (n int, errno error) {
|
|
||||||
return f.format(false, format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type flatFormatter indentFormatter
|
|
||||||
|
|
||||||
// FlatFormatter returns a newly created Formatter with the same functionality as the one returned
|
|
||||||
// by IndentFormatter except it allows a newline in the 'format' string argument of Format
|
|
||||||
// to pass through iff indent level is currently zero.
|
|
||||||
//
|
|
||||||
// If indent level is non-zero then such new lines are changed to a space character.
|
|
||||||
// There is no indent string, the %i and %u format verbs are used solely to determine the indent level.
|
|
||||||
//
|
|
||||||
// The FlatFormatter is intended for flattening of normally nested structure textual representation to
|
|
||||||
// a one top level structure per line form.
|
|
||||||
// FlatFormatter(os.Stdout, " ").Format("abc%d%%e%i\nx\ny\n%uz\n", 3)
|
|
||||||
// output in the form of a Go quoted string literal:
|
|
||||||
// "abc3%%e x y z\n"
|
|
||||||
func FlatFormatter(w io.Writer) Formatter {
|
|
||||||
return (*flatFormatter)(IndentFormatter(w, "").(*indentFormatter))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *flatFormatter) Format(format string, args ...interface{}) (n int, errno error) {
|
|
||||||
return (*indentFormatter)(f).format(true, format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pool handles aligning of strings having equal values to the same string instance.
|
|
||||||
// Intended use is to conserve some memory e.g. where a large number of identically valued strings
|
|
||||||
// with non identical backing arrays may exists in several semantically distinct instances of some structs.
|
|
||||||
// Pool is *not* concurrent access safe. It doesn't handle common prefix/suffix aligning,
|
|
||||||
// e.g. having s1 == "abc" and s2 == "bc", s2 is not automatically aligned as s1[1:].
|
|
||||||
type Pool struct {
|
|
||||||
pool map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPool returns a newly created Pool.
|
|
||||||
func NewPool() *Pool {
|
|
||||||
return &Pool{map[string]string{}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align returns a string with the same value as its argument. It guarantees that
|
|
||||||
// all aligned strings share a single instance in memory.
|
|
||||||
func (p *Pool) Align(s string) string {
|
|
||||||
if a, ok := p.pool[s]; ok {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
s = StrPack(s)
|
|
||||||
p.pool[s] = s
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the number of items in the pool.
|
|
||||||
func (p *Pool) Count() int {
|
|
||||||
return len(p.pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GoPool is a concurrent access safe version of Pool.
|
|
||||||
type GoPool struct {
|
|
||||||
pool map[string]string
|
|
||||||
rwm *sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGoPool returns a newly created GoPool.
|
|
||||||
func NewGoPool() (p *GoPool) {
|
|
||||||
return &GoPool{map[string]string{}, &sync.RWMutex{}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align returns a string with the same value as its argument. It guarantees that
|
|
||||||
// all aligned strings share a single instance in memory.
|
|
||||||
func (p *GoPool) Align(s string) (y string) {
|
|
||||||
if s != "" {
|
|
||||||
p.rwm.RLock() // R++
|
|
||||||
if a, ok := p.pool[s]; ok { // found
|
|
||||||
p.rwm.RUnlock() // R--
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
p.rwm.RUnlock() // R--
|
|
||||||
// not found but with a race condition, retry within a write lock
|
|
||||||
p.rwm.Lock() // W++
|
|
||||||
defer p.rwm.Unlock() // W--
|
|
||||||
if a, ok := p.pool[s]; ok { // done in a race
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// we won
|
|
||||||
s = StrPack(s)
|
|
||||||
p.pool[s] = s
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the number of items in the pool.
|
|
||||||
func (p *GoPool) Count() int {
|
|
||||||
return len(p.pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dict is a string <-> id bijection. Dict is *not* concurrent access safe for assigning new ids
|
|
||||||
// to strings not yet contained in the bijection.
|
|
||||||
// Id for an empty string is guaranteed to be 0,
|
|
||||||
// thus Id for any non empty string is guaranteed to be non zero.
|
|
||||||
type Dict struct {
|
|
||||||
si map[string]int
|
|
||||||
is []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDict returns a newly created Dict.
|
|
||||||
func NewDict() (d *Dict) {
|
|
||||||
d = &Dict{map[string]int{}, []string{}}
|
|
||||||
d.Id("")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the number of items in the dict.
|
|
||||||
func (d *Dict) Count() int {
|
|
||||||
return len(d.is)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Id maps string s to its numeric identificator.
|
|
||||||
func (d *Dict) Id(s string) (y int) {
|
|
||||||
if y, ok := d.si[s]; ok {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
s = StrPack(s)
|
|
||||||
y = len(d.is)
|
|
||||||
d.si[s] = y
|
|
||||||
d.is = append(d.is, s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// S maps an id to its string value and ok == true. Id values not contained in the bijection
|
|
||||||
// return "", false.
|
|
||||||
func (d *Dict) S(id int) (s string, ok bool) {
|
|
||||||
if id >= len(d.is) {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return d.is[id], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GoDict is a concurrent access safe version of Dict.
|
|
||||||
type GoDict struct {
|
|
||||||
si map[string]int
|
|
||||||
is []string
|
|
||||||
rwm *sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGoDict returns a newly created GoDict.
|
|
||||||
func NewGoDict() (d *GoDict) {
|
|
||||||
d = &GoDict{map[string]int{}, []string{}, &sync.RWMutex{}}
|
|
||||||
d.Id("")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the number of items in the dict.
|
|
||||||
func (d *GoDict) Count() int {
|
|
||||||
return len(d.is)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Id maps string s to its numeric identificator. The implementation honors getting
|
|
||||||
// an existing id at the cost of assigning a new one.
|
|
||||||
func (d *GoDict) Id(s string) (y int) {
|
|
||||||
d.rwm.RLock() // R++
|
|
||||||
if y, ok := d.si[s]; ok { // found
|
|
||||||
d.rwm.RUnlock() // R--
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
d.rwm.RUnlock() // R--
|
|
||||||
|
|
||||||
// not found but with a race condition
|
|
||||||
d.rwm.Lock() // W++ recheck with write lock
|
|
||||||
defer d.rwm.Unlock() // W--
|
|
||||||
if y, ok := d.si[s]; ok { // some other goroutine won already
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
// a race free not found state => insert the string
|
|
||||||
s = StrPack(s)
|
|
||||||
y = len(d.is)
|
|
||||||
d.si[s] = y
|
|
||||||
d.is = append(d.is, s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// S maps an id to its string value and ok == true. Id values not contained in the bijection
|
|
||||||
// return "", false.
|
|
||||||
func (d *GoDict) S(id int) (s string, ok bool) {
|
|
||||||
d.rwm.RLock() // R++
|
|
||||||
defer d.rwm.RUnlock() // R--
|
|
||||||
if id >= len(d.is) {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return d.is[id], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrPack returns a new instance of s which is tightly packed in memory.
|
|
||||||
// It is intended for avoiding the situation where having a live reference
|
|
||||||
// to a string slice over an unreferenced biger underlying string keeps the biger one
|
|
||||||
// in memory anyway - it can't be GCed.
|
|
||||||
func StrPack(s string) string {
|
|
||||||
return string([]byte(s)) // T(U(T)) intentional.
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinFields returns strings in flds joined by sep. Flds may contain arbitrary
|
|
||||||
// bytes, including the sep as they are safely escaped. JoinFields panics if
|
|
||||||
// sep is the backslash character or if len(sep) != 1.
|
|
||||||
func JoinFields(flds []string, sep string) string {
|
|
||||||
if len(sep) != 1 || sep == "\\" {
|
|
||||||
panic("invalid separator")
|
|
||||||
}
|
|
||||||
|
|
||||||
a := make([]string, len(flds))
|
|
||||||
for i, v := range flds {
|
|
||||||
v = strings.Replace(v, "\\", "\\0", -1)
|
|
||||||
a[i] = strings.Replace(v, sep, "\\1", -1)
|
|
||||||
}
|
|
||||||
return strings.Join(a, sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SplitFields splits s, which must be produced by JoinFields using the same
|
|
||||||
// sep, into flds. SplitFields panics if sep is the backslash character or if
|
|
||||||
// len(sep) != 1.
|
|
||||||
func SplitFields(s, sep string) (flds []string) {
|
|
||||||
if len(sep) != 1 || sep == "\\" {
|
|
||||||
panic("invalid separator")
|
|
||||||
}
|
|
||||||
|
|
||||||
a := strings.Split(s, sep)
|
|
||||||
r := make([]string, len(a))
|
|
||||||
for i, v := range a {
|
|
||||||
v = strings.Replace(v, "\\1", sep, -1)
|
|
||||||
r[i] = strings.Replace(v, "\\0", "\\", -1)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrintHooks allow to customize the result of PrettyPrint for types
|
|
||||||
// listed in the map value.
|
|
||||||
type PrettyPrintHooks map[reflect.Type]func(f Formatter, v interface{}, prefix, suffix string)
|
|
||||||
|
|
||||||
// PrettyString returns the output of PrettyPrint as a string.
|
|
||||||
func PrettyString(v interface{}, prefix, suffix string, hooks PrettyPrintHooks) string {
|
|
||||||
var b bytes.Buffer
|
|
||||||
PrettyPrint(&b, v, prefix, suffix, hooks)
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrint pretty prints v to w. Zero values and unexported struct fields
|
|
||||||
// are omitted.
|
|
||||||
//
|
|
||||||
// Force printing of zero values of struct fields by including in the field tag
|
|
||||||
// PrettyPrint:"zero".
|
|
||||||
//
|
|
||||||
// Enable using a String method, if any, of a struct field type by including in
|
|
||||||
// the field tag PrettyPrint:"stringer".
|
|
||||||
//
|
|
||||||
// The tags can be combined as in PrettyPrint:"zero,stringer". The order is not
|
|
||||||
// important, so PrettyPrint:stringer,zero has the same effect.
|
|
||||||
//
|
|
||||||
// A hook attached to the field type has priority over the struct field tag
|
|
||||||
// described above.
|
|
||||||
func PrettyPrint(w io.Writer, v interface{}, prefix, suffix string, hooks PrettyPrintHooks) {
|
|
||||||
if v == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
f := IndentFormatter(w, "· ")
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
f.Format("\npanic: %v", e)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
prettyPrint(nil, f, prefix, suffix, v, hooks, false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func prettyPrint(protect map[interface{}]struct{}, sf Formatter, prefix, suffix string, v interface{}, hooks PrettyPrintHooks, zero, stringer bool) {
|
|
||||||
if v == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rt := reflect.TypeOf(v)
|
|
||||||
if handler := hooks[rt]; handler != nil {
|
|
||||||
handler(sf, v, prefix, suffix)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
if stringer {
|
|
||||||
if _, ok := v.(fmt.Stringer); ok {
|
|
||||||
sf.Format("%s%s", prefix, v)
|
|
||||||
sf.Format(suffix)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch rt.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
if rv.Len() == 0 && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sf.Format("%s[]%T{ // len %d%i\n", prefix, rv.Index(0).Interface(), rv.Len())
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
|
||||||
prettyPrint(protect, sf, fmt.Sprintf("%d: ", i), ",\n", rv.Index(i).Interface(), hooks, false, false)
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%u}" + suffix)
|
|
||||||
case reflect.Array:
|
|
||||||
if reflect.Zero(rt).Interface() == rv.Interface() && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sf.Format("%s[%d]%T{%i\n", prefix, rv.Len(), rv.Index(0).Interface())
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
|
||||||
prettyPrint(protect, sf, fmt.Sprintf("%d: ", i), ",\n", rv.Index(i).Interface(), hooks, false, false)
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%u}" + suffix)
|
|
||||||
case reflect.Struct:
|
|
||||||
if rt.NumField() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if reflect.DeepEqual(reflect.Zero(rt).Interface(), rv.Interface()) && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sf.Format("%s%T{%i\n", prefix, v)
|
|
||||||
for i := 0; i < rt.NumField(); i++ {
|
|
||||||
f := rv.Field(i)
|
|
||||||
if !f.CanInterface() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var stringer, zero bool
|
|
||||||
ft := rt.Field(i)
|
|
||||||
if tag, ok := ft.Tag.Lookup("PrettyPrint"); ok {
|
|
||||||
a := strings.Split(tag, ",")
|
|
||||||
for _, v := range a {
|
|
||||||
switch strings.TrimSpace(v) {
|
|
||||||
case "stringer":
|
|
||||||
stringer = true
|
|
||||||
case "zero":
|
|
||||||
zero = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prettyPrint(protect, sf, fmt.Sprintf("%s: ", rt.Field(i).Name), ",\n", f.Interface(), hooks, zero, stringer)
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%u}" + suffix)
|
|
||||||
case reflect.Ptr:
|
|
||||||
if rv.IsNil() && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rvi := rv.Interface()
|
|
||||||
if _, ok := protect[rvi]; ok {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s&%T{ /* recursive/repetitive pointee not shown */ }"+suffix, prefix, rv.Elem().Interface())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if protect == nil {
|
|
||||||
protect = map[interface{}]struct{}{}
|
|
||||||
}
|
|
||||||
protect[rvi] = struct{}{}
|
|
||||||
prettyPrint(protect, sf, prefix+"&", suffix, rv.Elem().Interface(), hooks, false, false)
|
|
||||||
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8:
|
|
||||||
if v := rv.Int(); v != 0 || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, v)
|
|
||||||
}
|
|
||||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8:
|
|
||||||
if v := rv.Uint(); v != 0 || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, v)
|
|
||||||
}
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
if v := rv.Float(); v != 0 || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, v)
|
|
||||||
}
|
|
||||||
case reflect.Complex64, reflect.Complex128:
|
|
||||||
if v := rv.Complex(); v != 0 || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, v)
|
|
||||||
}
|
|
||||||
case reflect.Uintptr:
|
|
||||||
if v := rv.Uint(); v != 0 || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, v)
|
|
||||||
}
|
|
||||||
case reflect.UnsafePointer:
|
|
||||||
s := fmt.Sprintf("%p", rv.Interface())
|
|
||||||
if s == "0x0" && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%s"+suffix, prefix, s)
|
|
||||||
case reflect.Bool:
|
|
||||||
if v := rv.Bool(); v || zero {
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%v"+suffix, prefix, rv.Bool())
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
s := rv.Interface().(string)
|
|
||||||
if s == "" && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%q"+suffix, prefix, s)
|
|
||||||
case reflect.Chan:
|
|
||||||
if reflect.Zero(rt).Interface() == rv.Interface() && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c := rv.Cap()
|
|
||||||
s := ""
|
|
||||||
if c != 0 {
|
|
||||||
s = fmt.Sprintf("// capacity: %d", c)
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%s%s %s%s"+suffix, prefix, rt.ChanDir(), rt.Elem().Name(), s)
|
|
||||||
case reflect.Func:
|
|
||||||
if rv.IsNil() && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var in, out []string
|
|
||||||
for i := 0; i < rt.NumIn(); i++ {
|
|
||||||
x := reflect.Zero(rt.In(i))
|
|
||||||
in = append(in, fmt.Sprintf("%T", x.Interface()))
|
|
||||||
}
|
|
||||||
if rt.IsVariadic() {
|
|
||||||
i := len(in) - 1
|
|
||||||
in[i] = "..." + in[i][2:]
|
|
||||||
}
|
|
||||||
for i := 0; i < rt.NumOut(); i++ {
|
|
||||||
out = append(out, rt.Out(i).Name())
|
|
||||||
}
|
|
||||||
s := "(" + strings.Join(in, ", ") + ")"
|
|
||||||
t := strings.Join(out, ", ")
|
|
||||||
if len(out) > 1 {
|
|
||||||
t = "(" + t + ")"
|
|
||||||
}
|
|
||||||
if t != "" {
|
|
||||||
t = " " + t
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%sfunc%s%s { ... }"+suffix, prefix, s, t)
|
|
||||||
case reflect.Map:
|
|
||||||
keys := rv.MapKeys()
|
|
||||||
if len(keys) == 0 && !zero {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
nf := IndentFormatter(&buf, "· ")
|
|
||||||
var skeys []string
|
|
||||||
for i, k := range keys {
|
|
||||||
prettyPrint(protect, nf, "", "", k.Interface(), hooks, false, false)
|
|
||||||
skeys = append(skeys, fmt.Sprintf("%s%10d", buf.Bytes(), i))
|
|
||||||
buf.Reset()
|
|
||||||
}
|
|
||||||
sort.Strings(skeys)
|
|
||||||
sf.Format("%s%T{%i\n", prefix, v)
|
|
||||||
for _, k := range skeys {
|
|
||||||
si := strings.TrimSpace(k[len(k)-10:])
|
|
||||||
k = k[:len(k)-10]
|
|
||||||
n, _ := strconv.ParseUint(si, 10, 64)
|
|
||||||
mv := rv.MapIndex(keys[n])
|
|
||||||
prettyPrint(protect, sf, fmt.Sprintf("%s: ", k), ",\n", mv.Interface(), hooks, false, false)
|
|
||||||
}
|
|
||||||
suffix = strings.Replace(suffix, "%", "%%", -1)
|
|
||||||
sf.Format("%u}" + suffix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gopath returns the value of the $GOPATH environment variable or its default
|
|
||||||
// value if not set.
|
|
||||||
func Gopath() string {
|
|
||||||
if r := os.Getenv("GOPATH"); r != "" {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// go1.8: https://github.com/golang/go/blob/74628a8b9f102bddd5078ee426efe0fd57033115/doc/code.html#L122
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "plan9":
|
|
||||||
return os.Getenv("home")
|
|
||||||
case "windows":
|
|
||||||
return filepath.Join(os.Getenv("USERPROFILE"), "go")
|
|
||||||
default:
|
|
||||||
return filepath.Join(os.Getenv("HOME"), "go")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Homepath returns the user's home directory path.
|
|
||||||
func Homepath() string {
|
|
||||||
// go1.8: https://github.com/golang/go/blob/74628a8b9f102bddd5078ee426efe0fd57033115/doc/code.html#L122
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "plan9":
|
|
||||||
return os.Getenv("home")
|
|
||||||
case "windows":
|
|
||||||
return os.Getenv("USERPROFILE")
|
|
||||||
default:
|
|
||||||
return os.Getenv("HOME")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportPath returns the import path of the caller or an error, if any.
|
|
||||||
func ImportPath() (string, error) {
|
|
||||||
_, file, _, ok := runtime.Caller(1)
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("runtime.Caller failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
gopath := Gopath()
|
|
||||||
for _, v := range filepath.SplitList(gopath) {
|
|
||||||
gp := filepath.Join(v, "src")
|
|
||||||
path, err := filepath.Rel(gp, file)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return filepath.Dir(path), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("cannot determine import path using GOPATH=%s", gopath)
|
|
||||||
}
|
|
27
vendor/modernc.org/token/LICENSE
generated
vendored
27
vendor/modernc.org/token/LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
56
vendor/modernc.org/token/Makefile
generated
vendored
56
vendor/modernc.org/token/Makefile
generated
vendored
|
@ -1,56 +0,0 @@
|
||||||
.PHONY: all clean cover cpu editor internalError later mem nuke todo edit
|
|
||||||
|
|
||||||
grep=--include=*.go --include=*.l --include=*.y --include=*.yy
|
|
||||||
ngrep='TODOOK\|parser\.go\|scanner\.go\|.*_string\.go'
|
|
||||||
|
|
||||||
all: editor
|
|
||||||
go vet 2>&1 | grep -v $(ngrep) || true
|
|
||||||
golint 2>&1 | grep -v $(ngrep) || true
|
|
||||||
make todo
|
|
||||||
unused . || true
|
|
||||||
misspell *.go
|
|
||||||
gosimple || true
|
|
||||||
maligned || true
|
|
||||||
unconvert -apply
|
|
||||||
|
|
||||||
clean:
|
|
||||||
go clean
|
|
||||||
rm -f *~ *.test *.out
|
|
||||||
|
|
||||||
cover:
|
|
||||||
t=$(shell mktemp) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t
|
|
||||||
|
|
||||||
cpu: clean
|
|
||||||
go test -run @ -bench . -cpuprofile cpu.out
|
|
||||||
go tool pprof -lines *.test cpu.out
|
|
||||||
|
|
||||||
|
|
||||||
edit:
|
|
||||||
@touch log
|
|
||||||
@if [ -f "Session.vim" ]; then gvim -S & else gvim -p Makefile *.go & fi
|
|
||||||
|
|
||||||
editor:
|
|
||||||
gofmt -l -s -w *.go
|
|
||||||
go test -i
|
|
||||||
go test 2>&1 | tee log
|
|
||||||
go install
|
|
||||||
|
|
||||||
internalError:
|
|
||||||
egrep -ho '"internal error.*"' *.go | sort | cat -n
|
|
||||||
|
|
||||||
later:
|
|
||||||
@grep -n $(grep) LATER * || true
|
|
||||||
@grep -n $(grep) MAYBE * || true
|
|
||||||
|
|
||||||
mem: clean
|
|
||||||
go test -run @ -bench . -memprofile mem.out -memprofilerate 1 -timeout 24h
|
|
||||||
go tool pprof -lines -web -alloc_space *.test mem.out
|
|
||||||
|
|
||||||
nuke: clean
|
|
||||||
go clean -i
|
|
||||||
|
|
||||||
todo:
|
|
||||||
@grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) TODO * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) BUG * | grep -v $(ngrep) || true
|
|
||||||
@grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true
|
|
9
vendor/modernc.org/token/README.md
generated
vendored
9
vendor/modernc.org/token/README.md
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
# token
|
|
||||||
|
|
||||||
Package token is a variant of the stdlib package token with types FileSet and Token removed
|
|
||||||
|
|
||||||
Installation
|
|
||||||
|
|
||||||
$ go get [-u] modernc.org/token
|
|
||||||
|
|
||||||
Documentation: [godoc.org/modernc.org/token](http://godoc.org/modernc.org/token)
|
|
359
vendor/modernc.org/token/position.go
generated
vendored
359
vendor/modernc.org/token/position.go
generated
vendored
|
@ -1,359 +0,0 @@
|
||||||
// Copyright 2010 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 token is variant of the stdlib package token with types FileSet and
|
|
||||||
// Token removed.
|
|
||||||
package token // import "modernc.org/token"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Positions
|
|
||||||
|
|
||||||
// Position describes an arbitrary source position
|
|
||||||
// including the file, line, and column location.
|
|
||||||
// A Position is valid if the line number is > 0.
|
|
||||||
type Position struct {
|
|
||||||
Filename string // filename, if any
|
|
||||||
Offset int // offset, starting at 0
|
|
||||||
Line int // line number, starting at 1
|
|
||||||
Column int // column number, starting at 1 (byte count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid reports whether the position is valid.
|
|
||||||
func (pos *Position) IsValid() bool { return pos.Line > 0 }
|
|
||||||
|
|
||||||
// String returns a string in one of several forms:
|
|
||||||
//
|
|
||||||
// file:line:column valid position with file name
|
|
||||||
// file:line valid position with file name but no column (column == 0)
|
|
||||||
// line:column valid position without file name
|
|
||||||
// line valid position without file name and no column (column == 0)
|
|
||||||
// file invalid position with file name
|
|
||||||
// - invalid position without file name
|
|
||||||
func (pos Position) String() string {
|
|
||||||
s := pos.Filename
|
|
||||||
if pos.IsValid() {
|
|
||||||
if s != "" {
|
|
||||||
s += ":"
|
|
||||||
}
|
|
||||||
s += fmt.Sprintf("%d", pos.Line)
|
|
||||||
if pos.Column != 0 {
|
|
||||||
s += fmt.Sprintf(":%d", pos.Column)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if s == "" {
|
|
||||||
s = "-"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pos is a compact encoding of a source position within a file set.
|
|
||||||
// It can be converted into a Position for a more convenient, but much
|
|
||||||
// larger, representation.
|
|
||||||
//
|
|
||||||
// The Pos value for a given file is a number in the range [base, base+size],
|
|
||||||
// where base and size are specified when a file is added to the file set.
|
|
||||||
// The difference between a Pos value and the corresponding file base
|
|
||||||
// corresponds to the byte offset of that position (represented by the Pos value)
|
|
||||||
// from the beginning of the file. Thus, the file base offset is the Pos value
|
|
||||||
// representing the first byte in the file.
|
|
||||||
//
|
|
||||||
// To create the Pos value for a specific source offset (measured in bytes),
|
|
||||||
// first add the respective file to the current file set using FileSet.AddFile
|
|
||||||
// and then call File.Pos(offset) for that file. Given a Pos value p
|
|
||||||
// for a specific file set fset, the corresponding Position value is
|
|
||||||
// obtained by calling fset.Position(p).
|
|
||||||
//
|
|
||||||
// Pos values can be compared directly with the usual comparison operators:
|
|
||||||
// If two Pos values p and q are in the same file, comparing p and q is
|
|
||||||
// equivalent to comparing the respective source file offsets. If p and q
|
|
||||||
// are in different files, p < q is true if the file implied by p was added
|
|
||||||
// to the respective file set before the file implied by q.
|
|
||||||
type Pos int
|
|
||||||
|
|
||||||
// The zero value for Pos is NoPos; there is no file and line information
|
|
||||||
// associated with it, and NoPos.IsValid() is false. NoPos is always
|
|
||||||
// smaller than any other Pos value. The corresponding Position value
|
|
||||||
// for NoPos is the zero value for Position.
|
|
||||||
const NoPos Pos = 0
|
|
||||||
|
|
||||||
// IsValid reports whether the position is valid.
|
|
||||||
func (p Pos) IsValid() bool {
|
|
||||||
return p != NoPos
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// File
|
|
||||||
|
|
||||||
// A File is a handle for a file belonging to a FileSet.
|
|
||||||
// A File has a name, size, and line offset table.
|
|
||||||
type File struct {
|
|
||||||
name string // file name as provided to AddFile
|
|
||||||
base int // Pos value range for this file is [base...base+size]
|
|
||||||
size int // file size as provided to AddFile
|
|
||||||
|
|
||||||
lines []int // lines contains the offset of the first character for each line (the first entry is always 0)
|
|
||||||
infos []lineInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFile returns a new file with a given filename and file size.
|
|
||||||
//
|
|
||||||
func NewFile(filename string, size int) *File {
|
|
||||||
return &File{name: filename, base: 1, size: size, lines: []int{0}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the file name of file f as registered with AddFile.
|
|
||||||
func (f *File) Name() string {
|
|
||||||
return f.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base returns the base offset of file f as registered with AddFile.
|
|
||||||
func (f *File) Base() int {
|
|
||||||
return f.base
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of file f as registered with AddFile.
|
|
||||||
func (f *File) Size() int {
|
|
||||||
return f.size
|
|
||||||
}
|
|
||||||
|
|
||||||
// LineCount returns the number of lines in file f.
|
|
||||||
func (f *File) LineCount() int {
|
|
||||||
n := len(f.lines)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddLine adds the line offset for a new line.
|
|
||||||
// The line offset must be larger than the offset for the previous line
|
|
||||||
// and smaller than the file size; otherwise the line offset is ignored.
|
|
||||||
func (f *File) AddLine(offset int) {
|
|
||||||
if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size {
|
|
||||||
f.lines = append(f.lines, offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MergeLine merges a line with the following line. It is akin to replacing
|
|
||||||
// the newline character at the end of the line with a space (to not change the
|
|
||||||
// remaining offsets). To obtain the line number, consult e.g. Position.Line.
|
|
||||||
// MergeLine will panic if given an invalid line number.
|
|
||||||
func (f *File) MergeLine(line int) {
|
|
||||||
if line < 1 {
|
|
||||||
panic(fmt.Sprintf("invalid line number %d (should be >= 1)", line))
|
|
||||||
}
|
|
||||||
if line >= len(f.lines) {
|
|
||||||
panic(fmt.Sprintf("invalid line number %d (should be < %d)", line, len(f.lines)))
|
|
||||||
}
|
|
||||||
// To merge the line numbered <line> with the line numbered <line+1>,
|
|
||||||
// we need to remove the entry in lines corresponding to the line
|
|
||||||
// numbered <line+1>. The entry in lines corresponding to the line
|
|
||||||
// numbered <line+1> is located at index <line>, since indices in lines
|
|
||||||
// are 0-based and line numbers are 1-based.
|
|
||||||
copy(f.lines[line:], f.lines[line+1:])
|
|
||||||
f.lines = f.lines[:len(f.lines)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLines sets the line offsets for a file and reports whether it succeeded.
|
|
||||||
// The line offsets are the offsets of the first character of each line;
|
|
||||||
// for instance for the content "ab\nc\n" the line offsets are {0, 3}.
|
|
||||||
// An empty file has an empty line offset table.
|
|
||||||
// Each line offset must be larger than the offset for the previous line
|
|
||||||
// and smaller than the file size; otherwise SetLines fails and returns
|
|
||||||
// false.
|
|
||||||
// Callers must not mutate the provided slice after SetLines returns.
|
|
||||||
func (f *File) SetLines(lines []int) bool {
|
|
||||||
// verify validity of lines table
|
|
||||||
size := f.size
|
|
||||||
for i, offset := range lines {
|
|
||||||
if i > 0 && offset <= lines[i-1] || size <= offset {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set lines table
|
|
||||||
f.lines = lines
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLinesForContent sets the line offsets for the given file content.
|
|
||||||
// It ignores position-altering //line comments.
|
|
||||||
func (f *File) SetLinesForContent(content []byte) {
|
|
||||||
var lines []int
|
|
||||||
line := 0
|
|
||||||
for offset, b := range content {
|
|
||||||
if line >= 0 {
|
|
||||||
lines = append(lines, line)
|
|
||||||
}
|
|
||||||
line = -1
|
|
||||||
if b == '\n' {
|
|
||||||
line = offset + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set lines table
|
|
||||||
f.lines = lines
|
|
||||||
}
|
|
||||||
|
|
||||||
// LineStart returns the Pos value of the start of the specified line.
|
|
||||||
// It ignores any alternative positions set using AddLineColumnInfo.
|
|
||||||
// LineStart panics if the 1-based line number is invalid.
|
|
||||||
func (f *File) LineStart(line int) Pos {
|
|
||||||
if line < 1 {
|
|
||||||
panic(fmt.Sprintf("invalid line number %d (should be >= 1)", line))
|
|
||||||
}
|
|
||||||
if line > len(f.lines) {
|
|
||||||
panic(fmt.Sprintf("invalid line number %d (should be < %d)", line, len(f.lines)))
|
|
||||||
}
|
|
||||||
return Pos(f.base + f.lines[line-1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// A lineInfo object describes alternative file, line, and column
|
|
||||||
// number information (such as provided via a //line directive)
|
|
||||||
// for a given file offset.
|
|
||||||
type lineInfo struct {
|
|
||||||
// fields are exported to make them accessible to gob
|
|
||||||
Offset int
|
|
||||||
Filename string
|
|
||||||
Line, Column int
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddLineInfo is like AddLineColumnInfo with a column = 1 argument.
|
|
||||||
// It is here for backward-compatibility for code prior to Go 1.11.
|
|
||||||
func (f *File) AddLineInfo(offset int, filename string, line int) {
|
|
||||||
f.AddLineColumnInfo(offset, filename, line, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddLineColumnInfo adds alternative file, line, and column number
|
|
||||||
// information for a given file offset. The offset must be larger
|
|
||||||
// than the offset for the previously added alternative line info
|
|
||||||
// and smaller than the file size; otherwise the information is
|
|
||||||
// ignored.
|
|
||||||
//
|
|
||||||
// AddLineColumnInfo is typically used to register alternative position
|
|
||||||
// information for line directives such as //line filename:line:column.
|
|
||||||
func (f *File) AddLineColumnInfo(offset int, filename string, line, column int) {
|
|
||||||
if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
|
|
||||||
f.infos = append(f.infos, lineInfo{offset, filename, line, column})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pos returns the Pos value for the given file offset;
|
|
||||||
// the offset must be <= f.Size().
|
|
||||||
// f.Pos(f.Offset(p)) == p.
|
|
||||||
func (f *File) Pos(offset int) Pos {
|
|
||||||
if offset > f.size {
|
|
||||||
panic(fmt.Sprintf("invalid file offset %d (should be <= %d)", offset, f.size))
|
|
||||||
}
|
|
||||||
return Pos(f.base + offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset returns the offset for the given file position p;
|
|
||||||
// p must be a valid Pos value in that file.
|
|
||||||
// f.Offset(f.Pos(offset)) == offset.
|
|
||||||
func (f *File) Offset(p Pos) int {
|
|
||||||
if int(p) < f.base || int(p) > f.base+f.size {
|
|
||||||
panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size))
|
|
||||||
}
|
|
||||||
return int(p) - f.base
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line returns the line number for the given file position p;
|
|
||||||
// p must be a Pos value in that file or NoPos.
|
|
||||||
func (f *File) Line(p Pos) int {
|
|
||||||
return f.Position(p).Line
|
|
||||||
}
|
|
||||||
|
|
||||||
func searchLineInfos(a []lineInfo, x int) int {
|
|
||||||
return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack returns the filename and line and column number for a file offset.
|
|
||||||
// If adjusted is set, unpack will return the filename and line information
|
|
||||||
// possibly adjusted by //line comments; otherwise those comments are ignored.
|
|
||||||
func (f *File) unpack(offset int, adjusted bool) (filename string, line, column int) {
|
|
||||||
filename = f.name
|
|
||||||
if i := searchInts(f.lines, offset); i >= 0 {
|
|
||||||
line, column = i+1, offset-f.lines[i]+1
|
|
||||||
}
|
|
||||||
if adjusted && len(f.infos) > 0 {
|
|
||||||
// few files have extra line infos
|
|
||||||
if i := searchLineInfos(f.infos, offset); i >= 0 {
|
|
||||||
alt := &f.infos[i]
|
|
||||||
filename = alt.Filename
|
|
||||||
if i := searchInts(f.lines, alt.Offset); i >= 0 {
|
|
||||||
// i+1 is the line at which the alternative position was recorded
|
|
||||||
d := line - (i + 1) // line distance from alternative position base
|
|
||||||
line = alt.Line + d
|
|
||||||
if alt.Column == 0 {
|
|
||||||
// alternative column is unknown => relative column is unknown
|
|
||||||
// (the current specification for line directives requires
|
|
||||||
// this to apply until the next PosBase/line directive,
|
|
||||||
// not just until the new newline)
|
|
||||||
column = 0
|
|
||||||
} else if d == 0 {
|
|
||||||
// the alternative position base is on the current line
|
|
||||||
// => column is relative to alternative column
|
|
||||||
column = alt.Column + (offset - alt.Offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *File) position(p Pos, adjusted bool) (pos Position) {
|
|
||||||
offset := int(p) - f.base
|
|
||||||
pos.Offset = offset
|
|
||||||
pos.Filename, pos.Line, pos.Column = f.unpack(offset, adjusted)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// PositionFor returns the Position value for the given file position p.
|
|
||||||
// If adjusted is set, the position may be adjusted by position-altering
|
|
||||||
// //line comments; otherwise those comments are ignored.
|
|
||||||
// p must be a Pos value in f or NoPos.
|
|
||||||
func (f *File) PositionFor(p Pos, adjusted bool) (pos Position) {
|
|
||||||
if p != NoPos {
|
|
||||||
if int(p) < f.base || int(p) > f.base+f.size {
|
|
||||||
panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size))
|
|
||||||
}
|
|
||||||
pos = f.position(p, adjusted)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position returns the Position value for the given file position p.
|
|
||||||
// Calling f.Position(p) is equivalent to calling f.PositionFor(p, true).
|
|
||||||
func (f *File) Position(p Pos) (pos Position) {
|
|
||||||
return f.PositionFor(p, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Helper functions
|
|
||||||
|
|
||||||
func searchInts(a []int, x int) int {
|
|
||||||
// This function body is a manually inlined version of:
|
|
||||||
//
|
|
||||||
// return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
|
|
||||||
//
|
|
||||||
// With better compiler optimizations, this may not be needed in the
|
|
||||||
// future, but at the moment this change improves the go/printer
|
|
||||||
// benchmark performance by ~30%. This has a direct impact on the
|
|
||||||
// speed of gofmt and thus seems worthwhile (2011-04-29).
|
|
||||||
// TODO(gri): Remove this when compilers have caught up.
|
|
||||||
i, j := 0, len(a)
|
|
||||||
for i < j {
|
|
||||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
|
||||||
// i ≤ h < j
|
|
||||||
if a[h] <= x {
|
|
||||||
i = h + 1
|
|
||||||
} else {
|
|
||||||
j = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i - 1
|
|
||||||
}
|
|
18
vendor/modules.txt
vendored
18
vendor/modules.txt
vendored
|
@ -364,11 +364,6 @@ github.com/gorilla/websocket
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
||||||
# github.com/hashicorp/golang-lru/v2 v2.0.7
|
|
||||||
## explicit; go 1.18
|
|
||||||
github.com/hashicorp/golang-lru/v2
|
|
||||||
github.com/hashicorp/golang-lru/v2/internal
|
|
||||||
github.com/hashicorp/golang-lru/v2/simplelru
|
|
||||||
# github.com/hashicorp/hcl v1.0.0
|
# github.com/hashicorp/hcl v1.0.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/hashicorp/hcl
|
github.com/hashicorp/hcl
|
||||||
|
@ -1289,9 +1284,6 @@ gopkg.in/yaml.v2
|
||||||
# gopkg.in/yaml.v3 v3.0.1
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
# modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6
|
|
||||||
## explicit; go 1.20
|
|
||||||
modernc.org/gc/v3
|
|
||||||
# modernc.org/libc v1.55.3
|
# modernc.org/libc v1.55.3
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
modernc.org/libc
|
modernc.org/libc
|
||||||
|
@ -1326,21 +1318,15 @@ modernc.org/mathutil
|
||||||
# modernc.org/memory v1.8.0
|
# modernc.org/memory v1.8.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
modernc.org/memory
|
modernc.org/memory
|
||||||
# modernc.org/sqlite v0.0.0-00010101000000-000000000000 => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.2-concurrency-workaround
|
# modernc.org/sqlite v0.0.0-00010101000000-000000000000 => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.5-concurrency-workaround
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
modernc.org/sqlite
|
modernc.org/sqlite
|
||||||
modernc.org/sqlite/lib
|
modernc.org/sqlite/lib
|
||||||
# modernc.org/strutil v1.2.0
|
|
||||||
## explicit; go 1.18
|
|
||||||
modernc.org/strutil
|
|
||||||
# modernc.org/token v1.1.0
|
|
||||||
## explicit
|
|
||||||
modernc.org/token
|
|
||||||
# mvdan.cc/xurls/v2 v2.6.0
|
# mvdan.cc/xurls/v2 v2.6.0
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
mvdan.cc/xurls/v2
|
mvdan.cc/xurls/v2
|
||||||
# github.com/go-swagger/go-swagger => github.com/superseriousbusiness/go-swagger v0.31.0-gts-go1.23-fix
|
# github.com/go-swagger/go-swagger => github.com/superseriousbusiness/go-swagger v0.31.0-gts-go1.23-fix
|
||||||
# modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.2-concurrency-workaround
|
# modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.34.5-concurrency-workaround
|
||||||
# go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.29.0
|
# go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.29.0
|
||||||
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
|
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
|
||||||
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
|
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
|
||||||
|
|
Loading…
Reference in a new issue