Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d64563edee | ||
|
|
07039262a0 | ||
|
|
4ed9ccb5c4 | ||
|
|
25edcfee7a | ||
|
|
d183f4205e | ||
|
|
821e9ee006 | ||
|
|
00e3f924c1 | ||
|
|
2248851d77 | ||
|
|
f74d1ea6d8 | ||
|
|
606b4c3a37 | ||
|
|
4e77fc9436 | ||
|
|
ad9db379e7 | ||
|
|
7be17d393f | ||
|
|
5665c9a410 | ||
|
|
1cf9d345aa | ||
|
|
f07f25f1ba | ||
|
|
c93b836c77 | ||
|
|
371103f0d1 | ||
|
|
8bd7afbe62 | ||
|
|
8ea3a493f4 | ||
|
|
f2abd346c0 | ||
|
|
c784713aca | ||
|
|
14acf618af | ||
|
|
fbee2baf9d | ||
|
|
2819b4167b | ||
|
|
2af660cb1f | ||
|
|
8323068414 | ||
|
|
5b62f9fdb6 | ||
|
|
4f66e3fe6c | ||
|
|
1335b4c64f | ||
|
|
da03c922ca | ||
|
|
9620116c30 | ||
|
|
dd7197f2a2 | ||
|
|
9214806342 | ||
|
|
348e713a8e | ||
|
|
cb81fe41ab | ||
|
|
a876bb3673 | ||
|
|
afa46daccd | ||
|
|
3c00da291e | ||
|
|
c847481184 | ||
|
|
f46ef67180 | ||
|
|
229ddfdae1 | ||
|
|
aa7f0849e3 | ||
|
|
7617b8a090 | ||
|
|
4e06abe002 | ||
|
|
b1a758dd5a | ||
|
|
5bf4daef2d | ||
|
|
e56db3b82e | ||
|
|
d3bbe01d5c | ||
|
|
286d6c6359 | ||
|
|
84424b52bc | ||
|
|
98c2dcd3e5 | ||
|
|
808f0bde9d | ||
|
|
c5c6012947 | ||
|
|
836060c8ad | ||
|
|
7a54353c7b | ||
|
|
b591ba0e78 | ||
|
|
5af51aefe6 | ||
|
|
e7c0f68bab | ||
|
|
bd9a6a4f8a | ||
|
|
3eb2c79fd8 | ||
|
|
4653d87298 | ||
|
|
45d569c215 | ||
|
|
c33caeb573 | ||
|
|
91a55cc4c5 | ||
|
|
05f08d776a | ||
|
|
d2569a85a6 | ||
|
|
772cd68fea | ||
|
|
4af992bccb | ||
|
|
da922ce90b | ||
|
|
7b77b0fa22 | ||
|
|
b7f9a39eff | ||
|
|
d2b25a7426 | ||
|
|
b5bf4ef31a | ||
|
|
a69b9bc2dc |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -8,7 +8,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
GO_VERSION: 1.17
|
GO_VERSION: 1.17
|
||||||
GOLANGCI_LINT_VERSION: v1.41.1
|
GOLANGCI_LINT_VERSION: v1.42.1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
|||||||
@@ -63,10 +63,10 @@
|
|||||||
exclude = []
|
exclude = []
|
||||||
|
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "interp/.+_test\\.go"
|
path = ".+_test\\.go"
|
||||||
linters = ["goconst"]
|
linters = ["goconst"]
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "interp/.+_test\\.go"
|
path = ".+_test\\.go"
|
||||||
text = "var-declaration:"
|
text = "var-declaration:"
|
||||||
|
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
@@ -75,6 +75,9 @@
|
|||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "interp/interp.go"
|
path = "interp/interp.go"
|
||||||
text = "`out` can be `io.Writer`"
|
text = "`out` can be `io.Writer`"
|
||||||
|
[[issues.exclude-rules]]
|
||||||
|
path = "interp/interp.go"
|
||||||
|
text = "`Panic` should conform to the `XxxError` format"
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "interp/interp_eval_test.go"
|
path = "interp/interp_eval_test.go"
|
||||||
linters = ["thelper"]
|
linters = ["thelper"]
|
||||||
|
|||||||
10
_test/a29.go
10
_test/a29.go
@@ -6,16 +6,18 @@ const (
|
|||||||
zero = iota
|
zero = iota
|
||||||
one
|
one
|
||||||
two
|
two
|
||||||
|
three
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
a := [...]string{
|
a := [...]string{
|
||||||
zero: "zero",
|
zero: "zero",
|
||||||
one: "one",
|
one: "one",
|
||||||
two: "two",
|
three: "three",
|
||||||
|
three + 2: "five",
|
||||||
}
|
}
|
||||||
fmt.Printf("%v %T\n", a, a)
|
fmt.Printf("%v %T\n", a, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [zero one two] [3]string
|
// [zero one three five] [6]string
|
||||||
|
|||||||
18
_test/alias2.go
Normal file
18
_test/alias2.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func (t MyT) Test() string {
|
||||||
|
return "hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyT int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := MyT(1)
|
||||||
|
|
||||||
|
fmt.Println(t.Test())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
22
_test/alias3.go
Normal file
22
_test/alias3.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/traefik/yaegi/_test/alias3"
|
||||||
|
|
||||||
|
var globalT *T
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
globalT = &T{A: "test"}
|
||||||
|
}
|
||||||
|
|
||||||
|
type T alias3.T
|
||||||
|
|
||||||
|
func (t *T) PrintT() {
|
||||||
|
(*alias3.T)(t).Print()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
globalT.PrintT()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test
|
||||||
9
_test/alias3/alias3.go
Normal file
9
_test/alias3/alias3.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package alias3
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
A string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Print() {
|
||||||
|
println(t.A)
|
||||||
|
}
|
||||||
27
_test/alias4.go
Normal file
27
_test/alias4.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type A http.Header
|
||||||
|
|
||||||
|
func (a A) Test1() {
|
||||||
|
fmt.Println("test1")
|
||||||
|
}
|
||||||
|
|
||||||
|
type B A
|
||||||
|
|
||||||
|
func (b B) Test2() {
|
||||||
|
fmt.Println("test2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := B{}
|
||||||
|
|
||||||
|
b.Test2()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test2
|
||||||
37
_test/assert2.go
Normal file
37
_test/assert2.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Defined an interface of stringBuilder that compatible with
|
||||||
|
// strings.Builder(go 1.10) and bytes.Buffer(< go 1.10)
|
||||||
|
type stringBuilder interface {
|
||||||
|
WriteRune(r rune) (n int, err error)
|
||||||
|
WriteString(s string) (int, error)
|
||||||
|
Reset()
|
||||||
|
Grow(n int)
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
var builderPool = sync.Pool{New: func() interface{} {
|
||||||
|
return newStringBuilder()
|
||||||
|
}}
|
||||||
|
|
||||||
|
func newStringBuilder() stringBuilder {
|
||||||
|
return &strings.Builder{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
i := builderPool.Get()
|
||||||
|
sb := i.(stringBuilder)
|
||||||
|
_, _ = sb.WriteString("hello")
|
||||||
|
|
||||||
|
println(sb.String())
|
||||||
|
|
||||||
|
builderPool.Put(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
@@ -8,4 +8,4 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error:
|
// Error:
|
||||||
// _test/assign15.go:5:26: cannot use type chan<- struct{} as type <-chan struct{} in assignment
|
// _test/assign15.go:5:26: cannot use type chan<- struct {} as type <-chan struct {} in assignment
|
||||||
|
|||||||
24
_test/break0.go
Normal file
24
_test/break0.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
OuterLoop:
|
||||||
|
println("Boo")
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
break OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 15:5: invalid break label OuterLoop
|
||||||
24
_test/break1.go
Normal file
24
_test/break1.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
OuterLoop:
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
break OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// I: 0
|
||||||
|
// true
|
||||||
25
_test/break2.go
Normal file
25
_test/break2.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
OuterLoop:
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
break OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
continue OuterLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// I: 0
|
||||||
|
// true
|
||||||
27
_test/break3.go
Normal file
27
_test/break3.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
goto OuterLoop
|
||||||
|
println("Boo")
|
||||||
|
OuterLoop:
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
break OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
goto OuterLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// I: 0
|
||||||
|
// true
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// A test program
|
|
||||||
|
|
||||||
// +build darwin,linux !arm
|
|
||||||
// +build go1.12 !go1.13
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
println("hello world")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// hello world
|
|
||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -13,7 +13,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -21,7 +21,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -13,7 +13,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -40,7 +40,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -40,7 +40,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -41,7 +41,7 @@ func client(uri string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
32
_test/composite18.go
Normal file
32
_test/composite18.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type fn func(string, string) bool
|
||||||
|
|
||||||
|
var funcs = []fn{
|
||||||
|
cmpLessFn,
|
||||||
|
cmpGreaterFn,
|
||||||
|
nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpLessFn(a string, b string) bool {
|
||||||
|
return a < b
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpGreaterFn(a string, b string) bool {
|
||||||
|
return a > b
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, f := range funcs {
|
||||||
|
if f == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println(f("a", "b"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
33
_test/composite19.go
Normal file
33
_test/composite19.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type fn func(string, string) bool
|
||||||
|
|
||||||
|
var funcs = map[string]fn{
|
||||||
|
"less": cmpLessFn,
|
||||||
|
"greater": cmpGreaterFn,
|
||||||
|
"none": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpLessFn(a string, b string) bool {
|
||||||
|
return a < b
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpGreaterFn(a string, b string) bool {
|
||||||
|
return a > b
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, n := range []string{"less", "greater", "none"} {
|
||||||
|
f := funcs[n]
|
||||||
|
if f == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println(f("a", "b"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
@@ -9,7 +9,7 @@ func main() {
|
|||||||
const huge = 1 << 100
|
const huge = 1 << 100
|
||||||
const large = huge >> 38
|
const large = huge >> 38
|
||||||
|
|
||||||
fmt.Println(large)
|
fmt.Println(int64(large))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
const maxLen = int64(int(^uint(0) >> 1))
|
const maxLen = int64(int64(^uint64(0) >> 1))
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println(maxLen)
|
fmt.Println(maxLen)
|
||||||
|
|||||||
28
_test/const26.go
Normal file
28
_test/const26.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fmt.Println(constString)
|
||||||
|
fmt.Println(const2)
|
||||||
|
fmt.Println(varString)
|
||||||
|
}
|
||||||
|
|
||||||
|
const constString string = "hello"
|
||||||
|
|
||||||
|
const (
|
||||||
|
const1 = iota + 10
|
||||||
|
const2
|
||||||
|
const3
|
||||||
|
)
|
||||||
|
|
||||||
|
var varString string = "test"
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
|
// 11
|
||||||
|
// test
|
||||||
26
_test/cont2.go
Normal file
26
_test/cont2.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
OuterLoop:
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
continue OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// I: 0
|
||||||
|
// true
|
||||||
|
// I: 1
|
||||||
|
// true
|
||||||
24
_test/cont3.go
Normal file
24
_test/cont3.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 2
|
||||||
|
m := 2
|
||||||
|
foo := true
|
||||||
|
OuterLoop:
|
||||||
|
println("boo")
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
println("I: ", i)
|
||||||
|
for j := 0; j < m; j++ {
|
||||||
|
switch foo {
|
||||||
|
case true:
|
||||||
|
println(foo)
|
||||||
|
continue OuterLoop
|
||||||
|
case false:
|
||||||
|
println(foo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 15:5: invalid continue label OuterLoop
|
||||||
@@ -2,12 +2,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
file, err := ioutil.TempFile("", "yeagibench")
|
file, err := os.CreateTemp("", "yeagibench")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -23,7 +22,7 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(file.Name())
|
b, err := os.ReadFile(file.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
|
r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(r)
|
b, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -10,4 +10,4 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error:
|
// Error:
|
||||||
// 9:6: cannot use type string as type int in assignment
|
// 9:6: cannot use type untyped string as type int in assignment
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +12,7 @@ type sink interface {
|
|||||||
|
|
||||||
func newSink() sink {
|
func newSink() sink {
|
||||||
// return os.Stdout // Stdout is special in yaegi tests
|
// return os.Stdout // Stdout is special in yaegi tests
|
||||||
file, err := ioutil.TempFile("", "yaegi-test.*")
|
file, err := os.CreateTemp("", "yaegi-test.*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
67
_test/issue-1260.go
Normal file
67
_test/issue-1260.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WriteSyncer interface {
|
||||||
|
io.Writer
|
||||||
|
Sync() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Sink interface {
|
||||||
|
WriteSyncer
|
||||||
|
io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFileSink(path string) (Sink, error) {
|
||||||
|
return os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Sink1 struct{ name string }
|
||||||
|
|
||||||
|
func (s Sink1) Write(b []byte) (int, error) { println("in Write"); return 0, nil }
|
||||||
|
func (s Sink1) Sync() error { println("in Sync"); return nil }
|
||||||
|
func (s Sink1) Close() error { println("in Close", s.name); return nil }
|
||||||
|
func newS1(name string) Sink { return Sink1{name} }
|
||||||
|
func newS1p(name string) Sink { return &Sink1{name} }
|
||||||
|
|
||||||
|
type Sink2 struct{ name string }
|
||||||
|
|
||||||
|
func (s *Sink2) Write(b []byte) (int, error) { println("in Write"); return 0, nil }
|
||||||
|
func (s *Sink2) Sync() error { println("in Sync"); return nil }
|
||||||
|
func (s *Sink2) Close() error { println("in Close", s.name); return nil }
|
||||||
|
func newS2(name string) Sink { return Sink1{name} }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tmpfile, err := os.CreateTemp("", "xxx")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
closers := []io.Closer{}
|
||||||
|
sink, err := newFileSink(tmpfile.Name())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
closers = append(closers, sink)
|
||||||
|
|
||||||
|
s1p := newS1p("ptr")
|
||||||
|
s1 := newS1("struct")
|
||||||
|
s2 := newS2("ptr2")
|
||||||
|
closers = append(closers, s1p, s1, s2)
|
||||||
|
for _, closer := range closers {
|
||||||
|
fmt.Println(closer.Close())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// in Close ptr
|
||||||
|
// <nil>
|
||||||
|
// in Close struct
|
||||||
|
// <nil>
|
||||||
|
// in Close ptr2
|
||||||
|
// <nil>
|
||||||
24
_test/issue-1276.go
Normal file
24
_test/issue-1276.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
type customFlag struct{}
|
||||||
|
|
||||||
|
func (cf customFlag) String() string {
|
||||||
|
return "custom flag"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cf customFlag) Set(string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Var(customFlag{}, "cf", "custom flag")
|
||||||
|
flag.Parse()
|
||||||
|
println("Hello, playground")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello, playground
|
||||||
30
_test/issue-1280.go
Normal file
30
_test/issue-1280.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DBReader interface {
|
||||||
|
io.ReadCloser
|
||||||
|
io.ReaderAt
|
||||||
|
}
|
||||||
|
|
||||||
|
type DB struct {
|
||||||
|
f DBReader
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f, err := os.Open("/dev/null")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
d := &DB{f}
|
||||||
|
data := make([]byte, 1)
|
||||||
|
_, _ = d.f.ReadAt(data, 0)
|
||||||
|
println("bye")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// bye
|
||||||
25
_test/issue-1285.go
Normal file
25
_test/issue-1285.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type (
|
||||||
|
T1 struct{ Path [12]int8 }
|
||||||
|
T2 struct{ Path *[12]int8 }
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
t11 = &T1{}
|
||||||
|
t21 = &T2{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := [12]byte{}
|
||||||
|
t12 := &T1{}
|
||||||
|
t22 := &T2{}
|
||||||
|
b11 := (*[len(t11.Path)]byte)(&b)
|
||||||
|
b12 := (*[len(t12.Path)]byte)(&b)
|
||||||
|
b21 := (*[len(t21.Path)]byte)(&b)
|
||||||
|
b22 := (*[len(t22.Path)]byte)(&b)
|
||||||
|
println(len(b11), len(b12), len(b21), len(b22))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12 12 12 12
|
||||||
10
_test/issue-1288.go
Normal file
10
_test/issue-1288.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("Hi")
|
||||||
|
goto done
|
||||||
|
done:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hi
|
||||||
20
_test/issue-1300.go
Normal file
20
_test/issue-1300.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const buflen = 512
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func f(t *T) { *t = T{buf: make([]byte, 0, buflen)} }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := T{}
|
||||||
|
println(cap(s.buf))
|
||||||
|
f(&s)
|
||||||
|
println(cap(s.buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0
|
||||||
|
// 512
|
||||||
16
_test/issue-1304.go
Normal file
16
_test/issue-1304.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
Name string
|
||||||
|
Alias *Node
|
||||||
|
Child []*Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := &Node{Name: "parent"}
|
||||||
|
n.Child = append(n.Child, &Node{Name: "child"})
|
||||||
|
println(n.Name, n.Child[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// parent child
|
||||||
15
_test/issue-1306.go
Normal file
15
_test/issue-1306.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func check() (result bool, err error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result, error := check()
|
||||||
|
fmt.Println(result, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true <nil>
|
||||||
27
_test/issue-1308.go
Normal file
27
_test/issue-1308.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
v interface{}
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := []test{
|
||||||
|
{
|
||||||
|
v: []interface{}{
|
||||||
|
T{"hello"},
|
||||||
|
},
|
||||||
|
s: "world",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fmt.Println(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [{[{hello}] world}]
|
||||||
19
_test/issue-1311.go
Normal file
19
_test/issue-1311.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
v interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func f() (ret int64, err error) {
|
||||||
|
ret += 2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := &T{}
|
||||||
|
t.v, _ = f()
|
||||||
|
println(t.v.(int64))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2
|
||||||
32
_test/issue-1315.go
Normal file
32
_test/issue-1315.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Intf interface {
|
||||||
|
M()
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) M() { println("in M") }
|
||||||
|
|
||||||
|
func f(i interface{}) {
|
||||||
|
switch j := i.(type) {
|
||||||
|
case Intf:
|
||||||
|
j.M()
|
||||||
|
default:
|
||||||
|
println("default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var i Intf
|
||||||
|
var k interface{} = 1
|
||||||
|
i = &T{"hello"}
|
||||||
|
f(i)
|
||||||
|
f(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// in M
|
||||||
|
// default
|
||||||
29
_test/issue-1320.go
Normal file
29
_test/issue-1320.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Pooler interface {
|
||||||
|
Get() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type baseClient struct {
|
||||||
|
connPool Pooler
|
||||||
|
}
|
||||||
|
|
||||||
|
type connPool struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *connPool) Get() string { return c.name }
|
||||||
|
|
||||||
|
func newBaseClient(i int, p Pooler) *baseClient {
|
||||||
|
return &baseClient{connPool: p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConnPool() *connPool { return &connPool{name: "connPool"} }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := newBaseClient(0, newConnPool())
|
||||||
|
println(b.connPool.(*connPool).name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// connPool
|
||||||
42
_test/issue-1326.go
Normal file
42
_test/issue-1326.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Option interface {
|
||||||
|
apply(*T)
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
|
||||||
|
type opt struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *opt) apply(t *T) {
|
||||||
|
println(o.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildOptions() []Option {
|
||||||
|
return []Option{
|
||||||
|
&opt{"opt1"},
|
||||||
|
&opt{"opt2"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewT(name string, options ...Option) *T {
|
||||||
|
t := &T{name}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt.apply(t)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := NewT("hello", BuildOptions()...)
|
||||||
|
println(t.s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// opt1
|
||||||
|
// opt2
|
||||||
|
// hello
|
||||||
16
_test/issue-1328.go
Normal file
16
_test/issue-1328.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
script := "hello"
|
||||||
|
sumRaw := sha1.Sum([]byte(script))
|
||||||
|
sum := hex.EncodeToString(sumRaw[:])
|
||||||
|
println(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
|
||||||
42
_test/issue-1330.go
Normal file
42
_test/issue-1330.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type wrappedConn struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_, err := net.Listen("tcp", "127.0.0.1:49153")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
LocalAddr: &net.TCPAddr{
|
||||||
|
IP: net.ParseIP("127.0.0.1"),
|
||||||
|
Port: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := dialer.Dial("tcp", "127.0.0.1:49153")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
t := &wrappedConn{conn}
|
||||||
|
var w io.Writer = t
|
||||||
|
if n, err := w.Write([]byte("hello")); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
fmt.Println(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 5
|
||||||
17
_test/issue-1332.go
Normal file
17
_test/issue-1332.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func run(fn func(name string)) { fn("test") }
|
||||||
|
|
||||||
|
type T2 struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T2) f(s string) { println(s, t.name) }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t2 := &T2{"foo"}
|
||||||
|
run(t2.f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test foo
|
||||||
37
_test/issue-1333.go
Normal file
37
_test/issue-1333.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mock(name string) http.HandlerFunc {
|
||||||
|
return func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
fmt.Fprint(rw, "Hello ", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func client(uri string) {
|
||||||
|
resp, err := http.Get(uri)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
mux.Handle("/", mock("foo"))
|
||||||
|
client(server.URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello foo
|
||||||
26
_test/issue-1337.go
Normal file
26
_test/issue-1337.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f(i interface{}) {
|
||||||
|
switch at := i.(type) {
|
||||||
|
case int, int8:
|
||||||
|
println("integer", at)
|
||||||
|
case io.Reader:
|
||||||
|
println("reader")
|
||||||
|
}
|
||||||
|
println("bye")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var fd *os.File
|
||||||
|
var r io.Reader = fd
|
||||||
|
f(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// reader
|
||||||
|
// bye
|
||||||
12
_test/issue-1342.go
Normal file
12
_test/issue-1342.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var a interface{}
|
||||||
|
a = "a"
|
||||||
|
fmt.Println(a, a == "a")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a true
|
||||||
13
_test/issue-1344.go
Normal file
13
_test/issue-1344.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var m = map[string]interface{}{"a": "a"}
|
||||||
|
a, _ := m["a"]
|
||||||
|
b, ok := a.(string)
|
||||||
|
fmt.Println("a:", a, ", b:", b, ", ok:", ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a: a , b: a , ok: true
|
||||||
21
_test/issue-1354.go
Normal file
21
_test/issue-1354.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(test()) // Go prints true, Yaegi false
|
||||||
|
}
|
||||||
|
|
||||||
|
func test() bool {
|
||||||
|
if true {
|
||||||
|
goto label
|
||||||
|
}
|
||||||
|
goto label
|
||||||
|
label:
|
||||||
|
println("Go continues here")
|
||||||
|
return true
|
||||||
|
println("Yaegi goes straight to this return (this line is never printed)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Go continues here
|
||||||
|
// true
|
||||||
22
_test/issue-1355.go
Normal file
22
_test/issue-1355.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/traefik/yaegi/_test/p2"
|
||||||
|
|
||||||
|
func f(i interface{}) {
|
||||||
|
_, ok := i.(p2.I)
|
||||||
|
println("ok:", ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var v *p2.T
|
||||||
|
var i interface{}
|
||||||
|
|
||||||
|
i = v
|
||||||
|
_, ok := i.(p2.I)
|
||||||
|
println("ok:", ok)
|
||||||
|
f(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok: true
|
||||||
|
// ok: true
|
||||||
14
_test/issue-1360.go
Normal file
14
_test/issue-1360.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
. "net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v := IP{}
|
||||||
|
fmt.Println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
27
_test/issue-1361.go
Normal file
27
_test/issue-1361.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type obj struct {
|
||||||
|
num float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fun func(o *obj) (r *obj, err error)
|
||||||
|
|
||||||
|
func numFun(fn func(f float64) float64) Fun {
|
||||||
|
return func(o *obj) (*obj, error) {
|
||||||
|
return &obj{fn(o.num)}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := numFun(math.Cos)
|
||||||
|
r, err := f(&obj{})
|
||||||
|
fmt.Println(r, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// &{1} <nil>
|
||||||
16
_test/issue-1364.go
Normal file
16
_test/issue-1364.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var value interface{}
|
||||||
|
var err error
|
||||||
|
value, err = strconv.ParseFloat("123", 64)
|
||||||
|
fmt.Println(value, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 123 <nil>
|
||||||
18
_test/issue-1365.go
Normal file
18
_test/issue-1365.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func genInt() (int, error) { return 3, nil }
|
||||||
|
|
||||||
|
func getInt() (value int) {
|
||||||
|
value, err := genInt()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(getInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
16
_test/issue-1368.go
Normal file
16
_test/issue-1368.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const dollar byte = 36
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var c byte = 36
|
||||||
|
switch true {
|
||||||
|
case c == dollar:
|
||||||
|
println("ok")
|
||||||
|
default:
|
||||||
|
println("not ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok
|
||||||
18
_test/issue-1371.go
Normal file
18
_test/issue-1371.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
parent *node
|
||||||
|
child []*node
|
||||||
|
key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
root := &node{key: "root"}
|
||||||
|
root.child = nil
|
||||||
|
fmt.Println("root:", root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// root: &{<nil> [] root}
|
||||||
17
_test/issue-1373.go
Normal file
17
_test/issue-1373.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewBadExpr() ast.Expr {
|
||||||
|
return &ast.BadExpr{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("%T\n", NewBadExpr().(*ast.BadExpr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// *ast.BadExpr
|
||||||
38
_test/issue-1375.go
Normal file
38
_test/issue-1375.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Option func(*Struct)
|
||||||
|
|
||||||
|
func WithOption(opt string) Option {
|
||||||
|
return func(s *Struct) {
|
||||||
|
s.opt = opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Struct struct {
|
||||||
|
opt string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(opts ...Option) *Struct {
|
||||||
|
s := new(Struct)
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(s)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) ShowOption() {
|
||||||
|
fmt.Println(s.opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
opts := []Option{
|
||||||
|
WithOption("test"),
|
||||||
|
}
|
||||||
|
s := New(opts...)
|
||||||
|
s.ShowOption()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test
|
||||||
21
_test/issue-1378.go
Normal file
21
_test/issue-1378.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fn := func() error {
|
||||||
|
_, err := t.GobEncode()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(fn())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
58
_test/issue-1381.go
Normal file
58
_test/issue-1381.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var bufPtrOne *bytes.Buffer
|
||||||
|
var bufPtrTwo *bytes.Buffer
|
||||||
|
var bufPtrThree *bytes.Buffer
|
||||||
|
var bufPtrFour *bytes.Buffer
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
bufOne := bytes.Buffer{}
|
||||||
|
bufTwo := &bytes.Buffer{}
|
||||||
|
var bufThree bytes.Buffer
|
||||||
|
bufFour := new(bytes.Buffer)
|
||||||
|
|
||||||
|
if bufPtrOne == nil {
|
||||||
|
bufPtrOne = &bufOne
|
||||||
|
} else if bufPtrOne == &bufOne {
|
||||||
|
fmt.Println("bufOne was not properly redeclared")
|
||||||
|
} else {
|
||||||
|
fmt.Println("bufOne is properly redeclared")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bufPtrTwo == nil {
|
||||||
|
bufPtrTwo = bufTwo
|
||||||
|
} else if bufPtrTwo == bufTwo {
|
||||||
|
fmt.Println("bufTwo was not properly redeclared")
|
||||||
|
} else {
|
||||||
|
fmt.Println("bufTwo is properly redeclared")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bufPtrThree == nil {
|
||||||
|
bufPtrThree = &bufThree
|
||||||
|
} else if bufPtrThree == &bufThree {
|
||||||
|
fmt.Println("bufThree was not properly redeclared")
|
||||||
|
} else {
|
||||||
|
fmt.Println("bufThree is properly redeclared")
|
||||||
|
}
|
||||||
|
|
||||||
|
if bufPtrFour == nil {
|
||||||
|
bufPtrFour = bufFour
|
||||||
|
} else if bufPtrFour == bufFour {
|
||||||
|
fmt.Println("bufFour was not properly redeclared")
|
||||||
|
} else {
|
||||||
|
fmt.Println("bufFour is properly redeclared")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// bufOne is properly redeclared
|
||||||
|
// bufTwo is properly redeclared
|
||||||
|
// bufThree is properly redeclared
|
||||||
|
// bufFour is properly redeclared
|
||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -36,7 +35,7 @@ type pipe struct {
|
|||||||
|
|
||||||
func newReadAutoCloser(r io.Reader) readAutoCloser {
|
func newReadAutoCloser(r io.Reader) readAutoCloser {
|
||||||
if _, ok := r.(io.Closer); !ok {
|
if _, ok := r.(io.Closer); !ok {
|
||||||
return readAutoCloser{ioutil.NopCloser(r)}
|
return readAutoCloser{io.NopCloser(r)}
|
||||||
}
|
}
|
||||||
return readAutoCloser{r.(io.ReadCloser)}
|
return readAutoCloser{r.(io.ReadCloser)}
|
||||||
}
|
}
|
||||||
@@ -44,7 +43,7 @@ func newReadAutoCloser(r io.Reader) readAutoCloser {
|
|||||||
func main() {
|
func main() {
|
||||||
p := &pipe{}
|
p := &pipe{}
|
||||||
p.Reader = newReadAutoCloser(strings.NewReader("test"))
|
p.Reader = newReadAutoCloser(strings.NewReader("test"))
|
||||||
b, err := ioutil.ReadAll(p.Reader)
|
b, err := io.ReadAll(p.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
14
_test/method38.go
Normal file
14
_test/method38.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/traefik/yaegi/_test/method38"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(method38.Get())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// &{[] {<nil>}}
|
||||||
19
_test/method38/a.go
Normal file
19
_test/method38/a.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package method38
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
func NewPool() Pool { return Pool{} }
|
||||||
|
|
||||||
|
type Buffer struct {
|
||||||
|
bs []byte
|
||||||
|
pool Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pool struct {
|
||||||
|
p *sync.Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_pool = NewPool()
|
||||||
|
Get = _pool.Get
|
||||||
|
)
|
||||||
3
_test/method38/b.go
Normal file
3
_test/method38/b.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package method38
|
||||||
|
|
||||||
|
func (p Pool) Get() *Buffer { return &Buffer{} }
|
||||||
32
_test/method39.go
Normal file
32
_test/method39.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/traefik/yaegi/_test/method38"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewPool() Pool { return Pool{} }
|
||||||
|
|
||||||
|
type Buffer struct {
|
||||||
|
bs []byte
|
||||||
|
pool Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pool struct {
|
||||||
|
p *sync.Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_pool = NewPool()
|
||||||
|
Get = _pool.Get
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(Get())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 17:11: undefined selector Get
|
||||||
@@ -7,4 +7,4 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error:
|
// Error:
|
||||||
// 5:2: invalid operation: mismatched types int and float64
|
// 5:2: invalid operation: mismatched types int and untyped float
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
_, err := ioutil.ReadFile("__NotExisting__")
|
_, err := os.ReadFile("__NotExisting__")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
}
|
}
|
||||||
9
_test/p2/p2.go
Normal file
9
_test/p2/p2.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package p2
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
isI()
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct{}
|
||||||
|
|
||||||
|
func (t *T) isI() {}
|
||||||
0
_test/p3/empty
Normal file
0
_test/p3/empty
Normal file
22
_test/rune2.go
Normal file
22
_test/rune2.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const majorVersion = '2'
|
||||||
|
|
||||||
|
type hashed struct {
|
||||||
|
major byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(majorVersion)
|
||||||
|
|
||||||
|
p := new(hashed)
|
||||||
|
p.major = majorVersion
|
||||||
|
|
||||||
|
fmt.Println(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 50
|
||||||
|
// &{50}
|
||||||
@@ -9,10 +9,20 @@ func test(time string, t time.Time) string {
|
|||||||
return time
|
return time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var zero = time.Time{}
|
||||||
|
|
||||||
|
func test2(time string) time.Time {
|
||||||
|
return zero
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
str := test("test", time.Now())
|
str := test("test", time.Now())
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str2 := test2("test2")
|
||||||
|
fmt.Println(str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// test
|
// test
|
||||||
|
// 0001-01-01 00:00:00 +0000 UTC
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type A struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type D struct {
|
type D struct {
|
||||||
|
F *A
|
||||||
E *A
|
E *A
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
_test/struct61.go
Normal file
22
_test/struct61.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type A struct {
|
||||||
|
B string
|
||||||
|
D
|
||||||
|
}
|
||||||
|
|
||||||
|
type D struct {
|
||||||
|
*A
|
||||||
|
E *A
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := &A{B: "b"}
|
||||||
|
a.D = D{E: a}
|
||||||
|
fmt.Println(a.D.E.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// b
|
||||||
11
_test/struct62.go
Normal file
11
_test/struct62.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type A struct{ *A }
|
||||||
|
v := &A{}
|
||||||
|
v.A = v
|
||||||
|
println("v.A.A = v", v.A.A == v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// v.A.A = v true
|
||||||
17
_test/type27.go
Normal file
17
_test/type27.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Foo = int
|
||||||
|
|
||||||
|
func (f Foo) Bar() int {
|
||||||
|
return f * f
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := Foo(1)
|
||||||
|
fmt.Println(x.Bar())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 7:1: cannot define new methods on non-local type int
|
||||||
17
_test/type28.go
Normal file
17
_test/type28.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Foo = int
|
||||||
|
|
||||||
|
func (f *Foo) Bar() int {
|
||||||
|
return *f * *f
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := Foo(1)
|
||||||
|
fmt.Println(x.Bar())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 7:1: cannot define new methods on non-local type int
|
||||||
12
_test/type29.go
Normal file
12
_test/type29.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var Foo int
|
||||||
|
|
||||||
|
func (f Foo) Bar() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 5:1: cannot define new methods on non-local type int
|
||||||
12
_test/type30.go
Normal file
12
_test/type30.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var Foo *int
|
||||||
|
|
||||||
|
func (f Foo) Bar() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 5:1: cannot define new methods on non-local type int
|
||||||
17
_test/type31.go
Normal file
17
_test/type31.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func (f Foo) Bar() int {
|
||||||
|
return f * f
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo = int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := Foo(1)
|
||||||
|
fmt.Println(x.Bar())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 5:1: cannot define new methods on non-local type int
|
||||||
17
_test/type32.go
Normal file
17
_test/type32.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func (f *Foo) Bar() int {
|
||||||
|
return *f * *f
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo = int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := Foo(1)
|
||||||
|
fmt.Println(x.Bar())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 5:1: cannot define new methods on non-local type int
|
||||||
11
_test/type33.go
Normal file
11
_test/type33.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func (f *Foo) Bar() int {
|
||||||
|
return *f * *f
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 3:1: undefined: Foo
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SSize = 16
|
const (
|
||||||
|
SSize = 16
|
||||||
|
WSize = bits.UintSize / 8
|
||||||
|
)
|
||||||
|
|
||||||
type S struct {
|
type S struct {
|
||||||
X int
|
X int
|
||||||
@@ -13,14 +16,19 @@ type S struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
bigEndian := (*(*[2]uint8)(unsafe.Pointer(&[]uint16{1}[0])))[0] == 0
|
||||||
var sBuf [SSize]byte
|
var sBuf [SSize]byte
|
||||||
s := (*S)(unsafe.Pointer(&sBuf[0]))
|
s := (*S)(unsafe.Pointer(&sBuf[0]))
|
||||||
|
|
||||||
s.X = 2
|
s.X = 2
|
||||||
s.Y = 4
|
s.Y = 4
|
||||||
|
|
||||||
fmt.Println(sBuf)
|
if bigEndian {
|
||||||
|
println(sBuf[0+WSize-1], sBuf[WSize+WSize-1])
|
||||||
|
} else {
|
||||||
|
println(sBuf[0], sBuf[WSize])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [2 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0]
|
// 2 4
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SSize = 24
|
const WSize = bits.UintSize / 8
|
||||||
|
|
||||||
type S struct {
|
type S struct {
|
||||||
X int
|
X int
|
||||||
@@ -20,7 +21,8 @@ func main() {
|
|||||||
{X: 3},
|
{X: 3},
|
||||||
}
|
}
|
||||||
addr := unsafe.Pointer(&arr[0])
|
addr := unsafe.Pointer(&arr[0])
|
||||||
s := *(*S)(unsafe.Pointer(uintptr(addr) + SSize*2))
|
// s := *(*S)(unsafe.Pointer(uintptr(addr) + SSize*2))
|
||||||
|
s := *(*S)(unsafe.Pointer(uintptr(addr) + WSize*6))
|
||||||
|
|
||||||
fmt.Println(s.X)
|
fmt.Println(s.X)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const WSize = bits.UintSize / 8
|
||||||
|
|
||||||
type S struct {
|
type S struct {
|
||||||
X int
|
X int
|
||||||
Y int
|
Y int
|
||||||
@@ -13,12 +15,12 @@ type S struct {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
x := S{}
|
x := S{}
|
||||||
size := unsafe.Sizeof(x)
|
size := unsafe.Sizeof(x) / WSize
|
||||||
align := unsafe.Alignof(x.Y)
|
align := unsafe.Alignof(x.Y) / WSize
|
||||||
offset := unsafe.Offsetof(x.Z)
|
offset := unsafe.Offsetof(x.Z) / WSize
|
||||||
|
|
||||||
fmt.Println(size, align, offset)
|
println(size, align, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 24 8 16
|
// 3 1 2
|
||||||
|
|||||||
23
_test/unsafe6.go
Normal file
23
_test/unsafe6.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type S struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
Z int
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := S{Z: 5}
|
||||||
|
ptr := unsafe.Pointer(&x)
|
||||||
|
offset := int(unsafe.Offsetof(x.Z))
|
||||||
|
p := unsafe.Add(ptr, offset)
|
||||||
|
|
||||||
|
i := *(*int)(p)
|
||||||
|
|
||||||
|
fmt.Println(i)
|
||||||
|
}
|
||||||
20
_test/unsafe7.go
Normal file
20
_test/unsafe7.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type S struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
Z int
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := [2]S{{Z: 5}, {Z: 10}}
|
||||||
|
|
||||||
|
s := unsafe.Slice(&x[0], 2)
|
||||||
|
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
19
_test/var16.go
Normal file
19
_test/var16.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func getArray() ([]int, error) { println("getArray"); return []int{1, 2}, nil }
|
||||||
|
|
||||||
|
func getNum() (int, error) { println("getNum"); return 3, nil }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if a, err := getNum(); err != nil {
|
||||||
|
println("#1", a)
|
||||||
|
} else if a, err := getArray(); err != nil {
|
||||||
|
println("#2", a)
|
||||||
|
}
|
||||||
|
println("#3")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// getNum
|
||||||
|
// getArray
|
||||||
|
// #3
|
||||||
@@ -18,12 +18,14 @@ func extractCmd(arg []string) error {
|
|||||||
var name string
|
var name string
|
||||||
var exclude string
|
var exclude string
|
||||||
var include string
|
var include string
|
||||||
|
var tag string
|
||||||
|
|
||||||
eflag := flag.NewFlagSet("run", flag.ContinueOnError)
|
eflag := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||||
eflag.StringVar(&licensePath, "license", "", "path to a LICENSE file")
|
eflag.StringVar(&licensePath, "license", "", "path to a LICENSE file")
|
||||||
eflag.StringVar(&name, "name", "", "the namespace for the extracted symbols")
|
eflag.StringVar(&name, "name", "", "the namespace for the extracted symbols")
|
||||||
eflag.StringVar(&exclude, "exclude", "", "comma separated list of regexp matching symbols to exclude")
|
eflag.StringVar(&exclude, "exclude", "", "comma separated list of regexp matching symbols to exclude")
|
||||||
eflag.StringVar(&include, "include", "", "comma separated list of regexp matching symbols to include")
|
eflag.StringVar(&include, "include", "", "comma separated list of regexp matching symbols to include")
|
||||||
|
eflag.StringVar(&tag, "tag", "", "comma separated list of build tags to be added to the created package")
|
||||||
eflag.Usage = func() {
|
eflag.Usage = func() {
|
||||||
fmt.Println("Usage: yaegi extract [options] packages...")
|
fmt.Println("Usage: yaegi extract [options] packages...")
|
||||||
fmt.Println("Options:")
|
fmt.Println("Options:")
|
||||||
@@ -56,6 +58,9 @@ func extractCmd(arg []string) error {
|
|||||||
Dest: name,
|
Dest: name,
|
||||||
License: license,
|
License: license,
|
||||||
}
|
}
|
||||||
|
if tag != "" {
|
||||||
|
ext.Tag = strings.Split(tag, ",")
|
||||||
|
}
|
||||||
|
|
||||||
if exclude != "" {
|
if exclude != "" {
|
||||||
ext.Exclude = strings.Split(exclude, ",")
|
ext.Exclude = strings.Split(exclude, ",")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -47,7 +46,12 @@ func run(arg []string) error {
|
|||||||
}
|
}
|
||||||
args := rflag.Args()
|
args := rflag.Args()
|
||||||
|
|
||||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, BuildTags: strings.Split(tags, ",")})
|
i := interp.New(interp.Options{
|
||||||
|
GoPath: build.Default.GOPATH,
|
||||||
|
BuildTags: strings.Split(tags, ","),
|
||||||
|
Env: os.Environ(),
|
||||||
|
Unrestricted: useUnrestricted,
|
||||||
|
})
|
||||||
if err := i.Use(stdlib.Symbols); err != nil {
|
if err := i.Use(stdlib.Symbols); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -130,7 +134,7 @@ func isFile(path string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runFile(i *interp.Interpreter, path string, noAutoImport bool) error {
|
func runFile(i *interp.Interpreter, path string, noAutoImport bool) error {
|
||||||
b, err := ioutil.ReadFile(path)
|
b, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,12 @@ func test(arg []string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, BuildTags: strings.Split(tags, ",")})
|
i := interp.New(interp.Options{
|
||||||
|
GoPath: build.Default.GOPATH,
|
||||||
|
BuildTags: strings.Split(tags, ","),
|
||||||
|
Env: os.Environ(),
|
||||||
|
Unrestricted: useUnrestricted,
|
||||||
|
})
|
||||||
if err := i.Use(stdlib.Symbols); err != nil {
|
if err := i.Use(stdlib.Symbols); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -37,7 +37,7 @@ func applyCIMultiplier(timeout time.Duration) time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestYaegiCmdCancel(t *testing.T) {
|
func TestYaegiCmdCancel(t *testing.T) {
|
||||||
tmp, err := ioutil.TempDir("", "yaegi-")
|
tmp, err := os.MkdirTemp("", "yaegi-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tmp directory: %v", err)
|
t.Fatalf("failed to create tmp directory: %v", err)
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,15 @@ func TestYaegiCmdCancel(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
yaegi := filepath.Join(tmp, "yaegi")
|
yaegi := filepath.Join(tmp, "yaegi")
|
||||||
build := exec.Command("go", "build", "-race", "-o", yaegi, ".")
|
|
||||||
|
args := []string{"build"}
|
||||||
|
if raceDetectorSupported(runtime.GOOS, runtime.GOARCH) {
|
||||||
|
args = append(args, "-race")
|
||||||
|
}
|
||||||
|
args = append(args, "-o", yaegi, ".")
|
||||||
|
|
||||||
|
build := exec.Command("go", args...)
|
||||||
|
|
||||||
out, err := build.CombinedOutput()
|
out, err := build.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to build yaegi command: %v: %s", err, out)
|
t.Fatalf("failed to build yaegi command: %v: %s", err, out)
|
||||||
@@ -115,3 +123,16 @@ func TestYaegiCmdCancel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func raceDetectorSupported(goos, goarch string) bool {
|
||||||
|
switch goos {
|
||||||
|
case "linux":
|
||||||
|
return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64"
|
||||||
|
case "darwin":
|
||||||
|
return goarch == "amd64" || goarch == "arm64"
|
||||||
|
case "freebsd", "netbsd", "openbsd", "windows":
|
||||||
|
return goarch == "amd64"
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
67
example/fs/fs_test.go
Normal file
67
example/fs/fs_test.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package fs1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
// only available from 1.16.
|
||||||
|
"testing/fstest"
|
||||||
|
|
||||||
|
"github.com/traefik/yaegi/interp"
|
||||||
|
"github.com/traefik/yaegi/stdlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testFilesystem = fstest.MapFS{
|
||||||
|
"main.go": &fstest.MapFile{
|
||||||
|
Data: []byte(`package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"foo/bar"
|
||||||
|
"./localfoo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bar.PrintSomething()
|
||||||
|
localfoo.PrintSomethingElse()
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
"_pkg/src/foo/bar/bar.go": &fstest.MapFile{
|
||||||
|
Data: []byte(`package bar
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintSomething() {
|
||||||
|
fmt.Println("I am a virtual filesystem printing something from _pkg/src/foo/bar/bar.go!")
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
"localfoo/foo.go": &fstest.MapFile{
|
||||||
|
Data: []byte(`package localfoo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintSomethingElse() {
|
||||||
|
fmt.Println("I am virtual filesystem printing else from localfoo/foo.go!")
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilesystemMapFS(t *testing.T) {
|
||||||
|
i := interp.New(interp.Options{
|
||||||
|
GoPath: "./_pkg",
|
||||||
|
SourcecodeFilesystem: testFilesystem,
|
||||||
|
})
|
||||||
|
if err := i.Use(stdlib.Symbols); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := i.EvalPath(`main.go`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,7 +80,14 @@ func init() {
|
|||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
||||||
{{range $m := $value.Method -}}
|
{{range $m := $value.Method -}}
|
||||||
func (W {{$value.Name}}) {{$m.Name}}{{$m.Param}} {{$m.Result}} { {{$m.Ret}} W.W{{$m.Name}}{{$m.Arg}} }
|
func (W {{$value.Name}}) {{$m.Name}}{{$m.Param}} {{$m.Result}} {
|
||||||
|
{{- if eq $m.Name "String"}}
|
||||||
|
if W.WString == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
{{end -}}
|
||||||
|
{{$m.Ret}} W.W{{$m.Name}}{{$m.Arg}}
|
||||||
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
`
|
`
|
||||||
@@ -270,6 +277,15 @@ func (e *Extractor) genContent(importPath string, p *types.Package) ([]byte, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, t := range e.Tag {
|
||||||
|
if len(t) != 0 {
|
||||||
|
buildTags += "," + t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(buildTags) != 0 && buildTags[0] == ',' {
|
||||||
|
buildTags = buildTags[1:]
|
||||||
|
}
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"Dest": e.Dest,
|
"Dest": e.Dest,
|
||||||
@@ -336,6 +352,7 @@ type Extractor struct {
|
|||||||
License string // License text to be included in the created package, optional.
|
License string // License text to be included in the created package, optional.
|
||||||
Exclude []string // Comma separated list of regexp matching symbols to exclude.
|
Exclude []string // Comma separated list of regexp matching symbols to exclude.
|
||||||
Include []string // Comma separated list of regexp matching symbols to include.
|
Include []string // Comma separated list of regexp matching symbols to include.
|
||||||
|
Tag []string // Comma separated of build tags to be added to the created package.
|
||||||
}
|
}
|
||||||
|
|
||||||
// importPath checks whether pkgIdent is an existing directory relative to
|
// importPath checks whether pkgIdent is an existing directory relative to
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,3 +1,3 @@
|
|||||||
module github.com/traefik/yaegi
|
module github.com/traefik/yaegi
|
||||||
|
|
||||||
go 1.12
|
go 1.16
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"go/format"
|
"go/format"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
@@ -535,6 +535,7 @@ func {{$name}}(n *node) {
|
|||||||
typ := n.typ.concrete().TypeOf()
|
typ := n.typ.concrete().TypeOf()
|
||||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||||
c0, c1 := n.child[0], n.child[1]
|
c0, c1 := n.child[0], n.child[1]
|
||||||
|
t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf()
|
||||||
|
|
||||||
{{- if or (eq $op.Name "==") (eq $op.Name "!=") }}
|
{{- if or (eq $op.Name "==") (eq $op.Name "!=") }}
|
||||||
|
|
||||||
@@ -557,7 +558,7 @@ func {{$name}}(n *node) {
|
|||||||
fnext := getExec(n.fnext)
|
fnext := getExec(n.fnext)
|
||||||
n.exec = func(f *frame) bltn {
|
n.exec = func(f *frame) bltn {
|
||||||
i1 := v1(f).Interface()
|
i1 := v1(f).Interface()
|
||||||
if i0 != i1 {
|
if i0 {{$op.Name}} i1 {
|
||||||
dest(f).SetBool(true)
|
dest(f).SetBool(true)
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
@@ -579,7 +580,7 @@ func {{$name}}(n *node) {
|
|||||||
fnext := getExec(n.fnext)
|
fnext := getExec(n.fnext)
|
||||||
n.exec = func(f *frame) bltn {
|
n.exec = func(f *frame) bltn {
|
||||||
i0 := v0(f).Interface()
|
i0 := v0(f).Interface()
|
||||||
if i0 != i1 {
|
if i0 {{$op.Name}} i1 {
|
||||||
dest(f).SetBool(true)
|
dest(f).SetBool(true)
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
@@ -602,7 +603,7 @@ func {{$name}}(n *node) {
|
|||||||
n.exec = func(f *frame) bltn {
|
n.exec = func(f *frame) bltn {
|
||||||
i0 := v0(f).Interface()
|
i0 := v0(f).Interface()
|
||||||
i1 := v1(f).Interface()
|
i1 := v1(f).Interface()
|
||||||
if i0 != i1 {
|
if i0 {{$op.Name}} i1 {
|
||||||
dest(f).SetBool(true)
|
dest(f).SetBool(true)
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
@@ -621,9 +622,39 @@ func {{$name}}(n *node) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not attempt to optimize '==' or '!=' if an operand is an interface.
|
||||||
|
// This will preserve proper dynamic type checking at runtime. For static types,
|
||||||
|
// type checks are already performed, so bypass them if possible.
|
||||||
|
if t0.Kind() == reflect.Interface || t1.Kind() == reflect.Interface {
|
||||||
|
v0 := genValue(c0)
|
||||||
|
v1 := genValue(c1)
|
||||||
|
if n.fnext != nil {
|
||||||
|
fnext := getExec(n.fnext)
|
||||||
|
n.exec = func(f *frame) bltn {
|
||||||
|
i0 := v0(f).Interface()
|
||||||
|
i1 := v1(f).Interface()
|
||||||
|
if i0 {{$op.Name}} i1 {
|
||||||
|
dest(f).SetBool(true)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
dest(f).SetBool(false)
|
||||||
|
return fnext
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest := genValue(n)
|
||||||
|
n.exec = func(f *frame) bltn {
|
||||||
|
i0 := v0(f).Interface()
|
||||||
|
i1 := v1(f).Interface()
|
||||||
|
dest(f).SetBool(i0 {{$op.Name}} i1)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
switch t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf(); {
|
switch {
|
||||||
case isString(t0) || isString(t1):
|
case isString(t0) || isString(t1):
|
||||||
switch {
|
switch {
|
||||||
case isInterface:
|
case isInterface:
|
||||||
@@ -1183,7 +1214,7 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ioutil.WriteFile("op.go", source, 0666); err != nil {
|
if err = os.WriteFile("op.go", source, 0o666); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
61
internal/unsafe2/unsafe.go
Normal file
61
internal/unsafe2/unsafe.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package unsafe2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type dummy struct{}
|
||||||
|
|
||||||
|
// DummyType represents a stand-in for a recursive type.
|
||||||
|
var DummyType = reflect.TypeOf(dummy{})
|
||||||
|
|
||||||
|
// the following type sizes must match their original definition in Go src/reflect/type.go.
|
||||||
|
|
||||||
|
type rtype struct {
|
||||||
|
_ uintptr
|
||||||
|
_ uintptr
|
||||||
|
_ uint32
|
||||||
|
_ uint32
|
||||||
|
_ uintptr
|
||||||
|
_ uintptr
|
||||||
|
_ uint32
|
||||||
|
_ uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type emptyInterface struct {
|
||||||
|
typ *rtype
|
||||||
|
_ unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
type structField struct {
|
||||||
|
_ uintptr
|
||||||
|
typ *rtype
|
||||||
|
_ uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type structType struct {
|
||||||
|
rtype
|
||||||
|
_ uintptr
|
||||||
|
fields []structField
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFieldType sets the type of the struct field at the given index, to the given type.
|
||||||
|
//
|
||||||
|
// The struct type must have been created at runtime. This is very unsafe.
|
||||||
|
func SetFieldType(s reflect.Type, idx int, t reflect.Type) {
|
||||||
|
if s.Kind() != reflect.Struct || idx >= s.NumField() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rtyp := unpackType(s)
|
||||||
|
styp := (*structType)(unsafe.Pointer(rtyp))
|
||||||
|
f := styp.fields[idx]
|
||||||
|
f.typ = unpackType(t)
|
||||||
|
styp.fields[idx] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackType(t reflect.Type) *rtype {
|
||||||
|
v := reflect.New(t).Elem().Interface()
|
||||||
|
return (*emptyInterface)(unsafe.Pointer(&v)).typ
|
||||||
|
}
|
||||||
33
internal/unsafe2/unsafe_test.go
Normal file
33
internal/unsafe2/unsafe_test.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package unsafe2_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/traefik/yaegi/internal/unsafe2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSwapFieldType(t *testing.T) {
|
||||||
|
f := []reflect.StructField{
|
||||||
|
{
|
||||||
|
Name: "A",
|
||||||
|
Type: reflect.TypeOf(int(0)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "B",
|
||||||
|
Type: reflect.PtrTo(unsafe2.DummyType),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "C",
|
||||||
|
Type: reflect.TypeOf(int64(0)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
typ := reflect.StructOf(f)
|
||||||
|
ntyp := reflect.PtrTo(typ)
|
||||||
|
|
||||||
|
unsafe2.SetFieldType(typ, 1, ntyp)
|
||||||
|
|
||||||
|
if typ.Field(1).Type != ntyp {
|
||||||
|
t.Fatalf("unexpected field type: want %s; got %s", ntyp, typ.Field(1).Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user