Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f07f25f1ba | ||
|
|
c93b836c77 | ||
|
|
371103f0d1 | ||
|
|
8bd7afbe62 | ||
|
|
8ea3a493f4 | ||
|
|
f2abd346c0 | ||
|
|
c784713aca | ||
|
|
14acf618af | ||
|
|
fbee2baf9d | ||
|
|
2819b4167b | ||
|
|
2af660cb1f | ||
|
|
8323068414 | ||
|
|
5b62f9fdb6 | ||
|
|
4f66e3fe6c | ||
|
|
1335b4c64f | ||
|
|
da03c922ca | ||
|
|
9620116c30 | ||
|
|
dd7197f2a2 |
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ func (s *Sink2) Close() error { println("in Close", s.name); retu
|
|||||||
func newS2(name string) Sink { return Sink1{name} }
|
func newS2(name string) Sink { return Sink1{name} }
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
tmpfile, err := ioutil.TempFile("", "xxx")
|
tmpfile, err := os.CreateTemp("", "xxx")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
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
|
||||||
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}
|
||||||
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
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
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
|
||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -135,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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -38,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
)
|
)
|
||||||
@@ -1183,7 +1183,7 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ioutil.WriteFile("op.go", source, 0o666); err != nil {
|
if err = os.WriteFile("op.go", source, 0o666); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if n.scope == nil {
|
||||||
|
n.scope = sc
|
||||||
|
}
|
||||||
switch n.kind {
|
switch n.kind {
|
||||||
case binaryExpr, unaryExpr, parenExpr:
|
case binaryExpr, unaryExpr, parenExpr:
|
||||||
if isBoolAction(n) {
|
if isBoolAction(n) {
|
||||||
@@ -662,7 +665,12 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
|||||||
if r := lc.child[0].typ.numOut(); r != l {
|
if r := lc.child[0].typ.numOut(); r != l {
|
||||||
err = n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, lc.child[0].name(), r)
|
err = n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, lc.child[0].name(), r)
|
||||||
}
|
}
|
||||||
n.gen = nop
|
if isBinCall(lc, sc) {
|
||||||
|
n.gen = nop
|
||||||
|
} else {
|
||||||
|
// TODO (marc): skip if no conversion or wrapping is needed.
|
||||||
|
n.gen = assignFromCall
|
||||||
|
}
|
||||||
case indexExpr:
|
case indexExpr:
|
||||||
lc.gen = getIndexMap2
|
lc.gen = getIndexMap2
|
||||||
n.gen = nop
|
n.gen = nop
|
||||||
@@ -970,7 +978,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
|||||||
n.typ = c0.typ
|
n.typ = c0.typ
|
||||||
n.findex = sc.add(n.typ)
|
n.findex = sc.add(n.typ)
|
||||||
}
|
}
|
||||||
case isBinCall(n):
|
case isBinCall(n, sc):
|
||||||
err = check.arguments(n, n.child[1:], n.child[0], n.action == aCallSlice)
|
err = check.arguments(n, n.child[1:], n.child[0], n.action == aCallSlice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
@@ -1824,6 +1832,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
|||||||
setFNext(c, clauses[i+1])
|
setFNext(c, clauses[i+1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sbn.start = clauses[0].start
|
||||||
n.start = n.child[0].start
|
n.start = n.child[0].start
|
||||||
n.child[0].tnext = sbn.start
|
n.child[0].tnext = sbn.start
|
||||||
|
|
||||||
@@ -2019,7 +2028,12 @@ func compDefineX(sc *scope, n *node) error {
|
|||||||
if len(types) != l {
|
if len(types) != l {
|
||||||
return n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, src.child[0].name(), len(types))
|
return n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, src.child[0].name(), len(types))
|
||||||
}
|
}
|
||||||
n.gen = nop
|
if isBinCall(src, sc) {
|
||||||
|
n.gen = nop
|
||||||
|
} else {
|
||||||
|
// TODO (marc): skip if no conversion or wrapping is needed.
|
||||||
|
n.gen = assignFromCall
|
||||||
|
}
|
||||||
|
|
||||||
case indexExpr:
|
case indexExpr:
|
||||||
types = append(types, src.typ, sc.getType("bool"))
|
types = append(types, src.typ, sc.getType("bool"))
|
||||||
@@ -2047,12 +2061,18 @@ func compDefineX(sc *scope, n *node) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, t := range types {
|
for i, t := range types {
|
||||||
index := sc.add(t)
|
var index int
|
||||||
sc.sym[n.child[i].ident] = &symbol{index: index, kind: varSym, typ: t}
|
id := n.child[i].ident
|
||||||
|
if sym, _, ok := sc.lookup(id); ok && sym.kind == varSym && sym.typ.equals(t) {
|
||||||
|
// Reuse symbol in case of a variable redeclaration with the same type.
|
||||||
|
index = sym.index
|
||||||
|
} else {
|
||||||
|
index = sc.add(t)
|
||||||
|
sc.sym[id] = &symbol{index: index, kind: varSym, typ: t}
|
||||||
|
}
|
||||||
n.child[i].typ = t
|
n.child[i].typ = t
|
||||||
n.child[i].findex = index
|
n.child[i].findex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2468,8 +2488,19 @@ func isCall(n *node) bool {
|
|||||||
return n.action == aCall || n.action == aCallSlice
|
return n.action == aCall || n.action == aCallSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBinCall(n *node) bool {
|
func isBinCall(n *node, sc *scope) bool {
|
||||||
return isCall(n) && n.child[0].typ.cat == valueT && n.child[0].typ.rtype.Kind() == reflect.Func
|
if !isCall(n) || len(n.child) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c0 := n.child[0]
|
||||||
|
if c0.typ == nil {
|
||||||
|
// If called early in parsing, child type may not be known yet.
|
||||||
|
c0.typ, _ = nodeType(n.interp, sc, c0)
|
||||||
|
if c0.typ == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c0.typ.cat == valueT && c0.typ.rtype.Kind() == reflect.Func
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOffsetof(n *node) bool {
|
func isOffsetof(n *node) bool {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package interp
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -69,7 +68,7 @@ func (nopCloser) Close() error { return nil }
|
|||||||
// dotWriter returns an output stream to a dot(1) co-process where to write data in .dot format.
|
// dotWriter returns an output stream to a dot(1) co-process where to write data in .dot format.
|
||||||
func dotWriter(dotCmd string) io.WriteCloser {
|
func dotWriter(dotCmd string) io.WriteCloser {
|
||||||
if dotCmd == "" {
|
if dotCmd == "" {
|
||||||
return nopCloser{ioutil.Discard}
|
return nopCloser{io.Discard}
|
||||||
}
|
}
|
||||||
fields := strings.Fields(dotCmd)
|
fields := strings.Fields(dotCmd)
|
||||||
cmd := exec.Command(fields[0], fields[1:]...)
|
cmd := exec.Command(fields[0], fields[1:]...)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package interp_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -26,7 +26,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
baseDir := filepath.Join("..", "_test")
|
baseDir := filepath.Join("..", "_test")
|
||||||
files, err := ioutil.ReadDir(baseDir)
|
files, err := os.ReadDir(baseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
|||||||
file.Name() == "io0.go" || // use random number
|
file.Name() == "io0.go" || // use random number
|
||||||
file.Name() == "issue-1093.go" || // expect error
|
file.Name() == "issue-1093.go" || // expect error
|
||||||
file.Name() == "issue-1276.go" || // expect error
|
file.Name() == "issue-1276.go" || // expect error
|
||||||
|
file.Name() == "issue-1330.go" || // expect error
|
||||||
file.Name() == "op1.go" || // expect error
|
file.Name() == "op1.go" || // expect error
|
||||||
file.Name() == "op7.go" || // expect error
|
file.Name() == "op7.go" || // expect error
|
||||||
file.Name() == "op9.go" || // expect error
|
file.Name() == "op9.go" || // expect error
|
||||||
@@ -145,7 +146,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
|||||||
if err = w.Close(); err != nil {
|
if err = w.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
outInterp, err := ioutil.ReadAll(r)
|
outInterp, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -885,7 +884,7 @@ func TestMultiEval(t *testing.T) {
|
|||||||
if err = w.Close(); err != nil {
|
if err = w.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
outInterp, err := ioutil.ReadAll(r)
|
outInterp, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -916,7 +915,7 @@ func TestMultiEvalNoName(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for k, v := range names {
|
for k, v := range names {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(f.Name(), v))
|
data, err := os.ReadFile(filepath.Join(f.Name(), v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"go/build"
|
"go/build"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -26,7 +25,7 @@ func TestFile(t *testing.T) {
|
|||||||
_ = os.Setenv("YAEGI_SPECIAL_STDIO", "1")
|
_ = os.Setenv("YAEGI_SPECIAL_STDIO", "1")
|
||||||
|
|
||||||
baseDir := filepath.Join("..", "_test")
|
baseDir := filepath.Join("..", "_test")
|
||||||
files, err := ioutil.ReadDir(baseDir)
|
files, err := os.ReadDir(baseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package interp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
@@ -28,7 +28,7 @@ func (interp *Interpreter) CompilePath(path string) (*Program, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(path)
|
b, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
254
interp/run.go
254
interp/run.go
@@ -616,6 +616,34 @@ func convert(n *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assignFromCall assigns values from a function call.
|
||||||
|
func assignFromCall(n *node) {
|
||||||
|
ncall := n.lastChild()
|
||||||
|
l := len(n.child) - 1
|
||||||
|
if n.anc.kind == varDecl && n.child[l-1].isType(n.scope) {
|
||||||
|
// Ignore the type in the assignment if it is part of a variable declaration.
|
||||||
|
l--
|
||||||
|
}
|
||||||
|
dvalue := make([]func(*frame) reflect.Value, l)
|
||||||
|
for i := range dvalue {
|
||||||
|
if n.child[i].ident == "_" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dvalue[i] = genValue(n.child[i])
|
||||||
|
}
|
||||||
|
next := getExec(n.tnext)
|
||||||
|
n.exec = func(f *frame) bltn {
|
||||||
|
for i, v := range dvalue {
|
||||||
|
if v == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s := f.data[ncall.findex+i]
|
||||||
|
v(f).Set(s)
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func assign(n *node) {
|
func assign(n *node) {
|
||||||
next := getExec(n.tnext)
|
next := getExec(n.tnext)
|
||||||
dvalue := make([]func(*frame) reflect.Value, n.nleft)
|
dvalue := make([]func(*frame) reflect.Value, n.nleft)
|
||||||
@@ -957,7 +985,7 @@ func genFunctionWrapper(n *node) func(*frame) reflect.Value {
|
|||||||
} else {
|
} else {
|
||||||
// Copy method receiver as first argument.
|
// Copy method receiver as first argument.
|
||||||
src, dest := rcvr(f), d[numRet]
|
src, dest := rcvr(f), d[numRet]
|
||||||
sk, dk := src.Type().Kind(), dest.Type().Kind()
|
sk, dk := src.Kind(), dest.Kind()
|
||||||
switch {
|
switch {
|
||||||
case sk == reflect.Ptr && dk != reflect.Ptr:
|
case sk == reflect.Ptr && dk != reflect.Ptr:
|
||||||
dest.Set(src.Elem())
|
dest.Set(src.Elem())
|
||||||
@@ -1058,7 +1086,7 @@ func genInterfaceWrapper(n *node, typ reflect.Type) func(*frame) reflect.Value {
|
|||||||
for i, m := range methods {
|
for i, m := range methods {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
// First direct method lookup on field.
|
// First direct method lookup on field.
|
||||||
if r := methodByName(v, names[i]); r.IsValid() {
|
if r := methodByName(v, names[i], indexes[i]); r.IsValid() {
|
||||||
w.Field(i + 1).Set(r)
|
w.Field(i + 1).Set(r)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1083,69 +1111,119 @@ func genInterfaceWrapper(n *node, typ reflect.Type) func(*frame) reflect.Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// methodByName return the method corresponding to name on value, or nil if not found.
|
// methodByName returns the method corresponding to name on value, or nil if not found.
|
||||||
// The search is extended on valueInterface wrapper if present.
|
// The search is extended on valueInterface wrapper if present.
|
||||||
func methodByName(value reflect.Value, name string) reflect.Value {
|
// If valid, the returned value is a method function with the receiver already set
|
||||||
|
// (no need to pass it at call).
|
||||||
|
func methodByName(value reflect.Value, name string, index []int) (v reflect.Value) {
|
||||||
if vi, ok := value.Interface().(valueInterface); ok {
|
if vi, ok := value.Interface().(valueInterface); ok {
|
||||||
if v := getConcreteValue(vi.value).MethodByName(name); v.IsValid() {
|
if v = getConcreteValue(vi.value).MethodByName(name); v.IsValid() {
|
||||||
return v
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value.MethodByName(name)
|
if v = value.MethodByName(name); v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
if checkFieldIndex(value.Type(), index) {
|
||||||
|
value = value.FieldByIndex(index)
|
||||||
|
}
|
||||||
|
if v = value.MethodByName(name); v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkFieldIndex(typ reflect.Type, index []int) bool {
|
||||||
|
if len(index) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
t := typ
|
||||||
|
for t.Kind() == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
i := index[0]
|
||||||
|
if i >= t.NumField() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(index) > 1 {
|
||||||
|
return checkFieldIndex(t.Field(i).Type, index[1:])
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func call(n *node) {
|
func call(n *node) {
|
||||||
goroutine := n.anc.kind == goStmt
|
goroutine := n.anc.kind == goStmt
|
||||||
var method bool
|
var method bool
|
||||||
value := genValue(n.child[0])
|
c0 := n.child[0]
|
||||||
|
value := genValue(c0)
|
||||||
var values []func(*frame) reflect.Value
|
var values []func(*frame) reflect.Value
|
||||||
|
|
||||||
recvIndexLater := false
|
recvIndexLater := false
|
||||||
switch {
|
switch {
|
||||||
case n.child[0].recv != nil:
|
case c0.recv != nil:
|
||||||
// Compute method receiver value.
|
// Compute method receiver value.
|
||||||
values = append(values, genValueRecv(n.child[0]))
|
values = append(values, genValueRecv(c0))
|
||||||
method = true
|
method = true
|
||||||
case len(n.child[0].child) > 0 && n.child[0].child[0].typ != nil && isInterfaceSrc(n.child[0].child[0].typ):
|
case len(c0.child) > 0 && c0.child[0].typ != nil && isInterfaceSrc(c0.child[0].typ):
|
||||||
recvIndexLater = true
|
recvIndexLater = true
|
||||||
values = append(values, genValueBinRecv(n.child[0], &receiver{node: n.child[0].child[0]}))
|
values = append(values, genValueBinRecv(c0, &receiver{node: c0.child[0]}))
|
||||||
value = genValueBinMethodOnInterface(n, value)
|
value = genValueBinMethodOnInterface(n, value)
|
||||||
method = true
|
method = true
|
||||||
case n.child[0].action == aMethod:
|
case c0.action == aMethod:
|
||||||
// Add a place holder for interface method receiver.
|
// Add a place holder for interface method receiver.
|
||||||
values = append(values, nil)
|
values = append(values, nil)
|
||||||
method = true
|
method = true
|
||||||
}
|
}
|
||||||
|
|
||||||
numRet := len(n.child[0].typ.ret)
|
numRet := len(c0.typ.ret)
|
||||||
variadic := variadicPos(n)
|
variadic := variadicPos(n)
|
||||||
child := n.child[1:]
|
child := n.child[1:]
|
||||||
tnext := getExec(n.tnext)
|
tnext := getExec(n.tnext)
|
||||||
fnext := getExec(n.fnext)
|
fnext := getExec(n.fnext)
|
||||||
|
hasVariadicArgs := n.action == aCallSlice // callSlice implies variadic call with ellipsis.
|
||||||
|
|
||||||
// Compute input argument value functions.
|
// Compute input argument value functions.
|
||||||
for i, c := range child {
|
for i, c := range child {
|
||||||
|
var arg *itype
|
||||||
|
if variadic >= 0 && i >= variadic {
|
||||||
|
arg = c0.typ.arg[variadic].val
|
||||||
|
} else {
|
||||||
|
arg = c0.typ.arg[i]
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case isBinCall(c):
|
case isBinCall(c, c.scope):
|
||||||
// Handle nested function calls: pass returned values as arguments.
|
// Handle nested function calls: pass returned values as arguments.
|
||||||
numOut := c.child[0].typ.rtype.NumOut()
|
numOut := c.child[0].typ.rtype.NumOut()
|
||||||
for j := 0; j < numOut; j++ {
|
for j := 0; j < numOut; j++ {
|
||||||
ind := c.findex + j
|
ind := c.findex + j
|
||||||
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
if hasVariadicArgs || !isInterfaceSrc(arg) || isEmptyInterface(arg) {
|
||||||
|
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
values = append(values, func(f *frame) reflect.Value {
|
||||||
|
return reflect.ValueOf(valueInterface{value: f.data[ind]})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
case isRegularCall(c):
|
case isRegularCall(c):
|
||||||
// Arguments are return values of a nested function call.
|
// Arguments are return values of a nested function call.
|
||||||
for j := range c.child[0].typ.ret {
|
cc0 := c.child[0]
|
||||||
|
for j := range cc0.typ.ret {
|
||||||
ind := c.findex + j
|
ind := c.findex + j
|
||||||
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
if hasVariadicArgs || !isInterfaceSrc(arg) || isEmptyInterface(arg) {
|
||||||
|
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
values = append(values, func(f *frame) reflect.Value {
|
||||||
|
return reflect.ValueOf(valueInterface{node: cc0.typ.ret[j].node, value: f.data[ind]})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
var arg *itype
|
|
||||||
if variadic >= 0 && i >= variadic {
|
|
||||||
arg = n.child[0].typ.arg[variadic].val
|
|
||||||
} else {
|
|
||||||
arg = n.child[0].typ.arg[i]
|
|
||||||
}
|
|
||||||
if c.kind == basicLit || c.rval.IsValid() {
|
if c.kind == basicLit || c.rval.IsValid() {
|
||||||
argType := arg.TypeOf()
|
argType := arg.TypeOf()
|
||||||
convertLiteralValue(c, argType)
|
convertLiteralValue(c, argType)
|
||||||
@@ -1153,11 +1231,12 @@ func call(n *node) {
|
|||||||
switch {
|
switch {
|
||||||
case isEmptyInterface(arg):
|
case isEmptyInterface(arg):
|
||||||
values = append(values, genValue(c))
|
values = append(values, genValue(c))
|
||||||
case isInterfaceSrc(arg) && n.action != aCallSlice:
|
case isInterfaceSrc(arg) && !hasVariadicArgs:
|
||||||
// callSlice implies variadic call with ellipsis, do not wrap in valueInterface.
|
|
||||||
values = append(values, genValueInterface(c))
|
values = append(values, genValueInterface(c))
|
||||||
case isInterfaceBin(arg):
|
case isInterfaceBin(arg):
|
||||||
values = append(values, genInterfaceWrapper(c, arg.rtype))
|
values = append(values, genInterfaceWrapper(c, arg.rtype))
|
||||||
|
case isFuncSrc(arg) && !hasVariadicArgs:
|
||||||
|
values = append(values, genValueNode(c))
|
||||||
default:
|
default:
|
||||||
values = append(values, genValue(c))
|
values = append(values, genValue(c))
|
||||||
}
|
}
|
||||||
@@ -1165,10 +1244,11 @@ func call(n *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute output argument value functions.
|
// Compute output argument value functions.
|
||||||
rtypes := n.child[0].typ.ret
|
rtypes := c0.typ.ret
|
||||||
rvalues := make([]func(*frame) reflect.Value, len(rtypes))
|
rvalues := make([]func(*frame) reflect.Value, len(rtypes))
|
||||||
switch n.anc.kind {
|
switch n.anc.kind {
|
||||||
case defineXStmt, assignXStmt:
|
case defineXStmt, assignXStmt:
|
||||||
|
l := n.level
|
||||||
for i := range rvalues {
|
for i := range rvalues {
|
||||||
c := n.anc.child[i]
|
c := n.anc.child[i]
|
||||||
switch {
|
switch {
|
||||||
@@ -1177,7 +1257,8 @@ func call(n *node) {
|
|||||||
case isInterfaceSrc(c.typ) && !isEmptyInterface(c.typ) && !isInterfaceSrc(rtypes[i]):
|
case isInterfaceSrc(c.typ) && !isEmptyInterface(c.typ) && !isInterfaceSrc(rtypes[i]):
|
||||||
rvalues[i] = genValueInterfaceValue(c)
|
rvalues[i] = genValueInterfaceValue(c)
|
||||||
default:
|
default:
|
||||||
rvalues[i] = genValue(c)
|
j := n.findex + i
|
||||||
|
rvalues[i] = func(f *frame) reflect.Value { return getFrame(f, l).data[j] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case returnStmt:
|
case returnStmt:
|
||||||
@@ -1198,7 +1279,7 @@ func call(n *node) {
|
|||||||
|
|
||||||
if n.anc.kind == deferStmt {
|
if n.anc.kind == deferStmt {
|
||||||
// Store function call in frame for deferred execution.
|
// Store function call in frame for deferred execution.
|
||||||
value = genFunctionWrapper(n.child[0])
|
value = genFunctionWrapper(c0)
|
||||||
if method {
|
if method {
|
||||||
// The receiver is already passed in the function wrapper, skip it.
|
// The receiver is already passed in the function wrapper, skip it.
|
||||||
values = values[1:]
|
values = values[1:]
|
||||||
@@ -1325,12 +1406,22 @@ func call(n *node) {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
val := v(f)
|
val := v(f)
|
||||||
// The !val.IsZero is to work around a recursive struct zero interface
|
if val.IsZero() && dest[i].Kind() != reflect.Interface {
|
||||||
// issue. Once there is a better way to handle this case, the dest
|
// Work around a recursive struct zero interface issue.
|
||||||
// can just be set.
|
// Once there is a better way to handle this case, the dest can just be set.
|
||||||
if !val.IsZero() || dest[i].Type().Kind() == reflect.Interface {
|
continue
|
||||||
dest[i].Set(val)
|
|
||||||
}
|
}
|
||||||
|
if nod, ok := val.Interface().(*node); ok && nod.recv != nil {
|
||||||
|
// An interpreted method is passed as value in a function call.
|
||||||
|
// It must be wrapped now, otherwise the receiver will be missing
|
||||||
|
// at the method call (#1332).
|
||||||
|
// TODO (marc): wrapping interpreted functions should be always done
|
||||||
|
// everywhere at runtime to simplify the whole code,
|
||||||
|
// but it requires deeper refactoring.
|
||||||
|
dest[i] = genFunctionWrapper(nod)(f)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dest[i].Set(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1404,7 +1495,7 @@ func callBin(n *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case isBinCall(c):
|
case isBinCall(c, c.scope):
|
||||||
// Handle nested function calls: pass returned values as arguments
|
// Handle nested function calls: pass returned values as arguments
|
||||||
numOut := c.child[0].typ.rtype.NumOut()
|
numOut := c.child[0].typ.rtype.NumOut()
|
||||||
for j := 0; j < numOut; j++ {
|
for j := 0; j < numOut; j++ {
|
||||||
@@ -1566,11 +1657,16 @@ func callBin(n *node) {
|
|||||||
}
|
}
|
||||||
out := callFn(value(f), in)
|
out := callFn(value(f), in)
|
||||||
for i := 0; i < len(out); i++ {
|
for i := 0; i < len(out); i++ {
|
||||||
if out[i].Type().Kind() == reflect.Func {
|
r := out[i]
|
||||||
getFrame(f, n.level).data[n.findex+i] = out[i]
|
if r.Kind() == reflect.Func {
|
||||||
} else {
|
getFrame(f, n.level).data[n.findex+i] = r
|
||||||
getFrame(f, n.level).data[n.findex+i].Set(out[i])
|
continue
|
||||||
}
|
}
|
||||||
|
dest := getFrame(f, n.level).data[n.findex+i]
|
||||||
|
if _, ok := dest.Interface().(valueInterface); ok {
|
||||||
|
r = reflect.ValueOf(valueInterface{value: r})
|
||||||
|
}
|
||||||
|
dest.Set(r)
|
||||||
}
|
}
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
@@ -1882,7 +1978,7 @@ func getMethodByName(n *node) {
|
|||||||
}
|
}
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
m, li := val.node.typ.lookupMethod(name)
|
m, li := typ.lookupMethod(name)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
panic(n.cfgErrorf("method not found: %s", name))
|
panic(n.cfgErrorf("method not found: %s", name))
|
||||||
}
|
}
|
||||||
@@ -2291,9 +2387,13 @@ func _return(n *node) {
|
|||||||
}
|
}
|
||||||
values[i] = genValueInterface(c)
|
values[i] = genValueInterface(c)
|
||||||
case valueT:
|
case valueT:
|
||||||
if t.rtype.Kind() == reflect.Interface {
|
switch t.rtype.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
values[i] = genInterfaceWrapper(c, t.rtype)
|
values[i] = genInterfaceWrapper(c, t.rtype)
|
||||||
break
|
continue
|
||||||
|
case reflect.Func:
|
||||||
|
values[i] = genFunctionWrapper(c)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
@@ -2533,7 +2633,7 @@ func doCompositeBinStruct(n *node, hasType bool) {
|
|||||||
}
|
}
|
||||||
d := value(f)
|
d := value(f)
|
||||||
switch {
|
switch {
|
||||||
case d.Type().Kind() == reflect.Ptr:
|
case d.Kind() == reflect.Ptr:
|
||||||
d.Set(s.Addr())
|
d.Set(s.Addr())
|
||||||
default:
|
default:
|
||||||
d.Set(s)
|
d.Set(s)
|
||||||
@@ -2611,7 +2711,7 @@ func doComposite(n *node, hasType bool, keyed bool) {
|
|||||||
}
|
}
|
||||||
d := value(f)
|
d := value(f)
|
||||||
switch {
|
switch {
|
||||||
case d.Type().Kind() == reflect.Ptr:
|
case d.Kind() == reflect.Ptr:
|
||||||
d.Set(a.Addr())
|
d.Set(a.Addr())
|
||||||
case destInterface:
|
case destInterface:
|
||||||
if len(destType(n).field) > 0 {
|
if len(destType(n).field) > 0 {
|
||||||
@@ -2867,13 +2967,22 @@ func _case(n *node) {
|
|||||||
if typ.cat == nilT && v.IsNil() {
|
if typ.cat == nilT && v.IsNil() {
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
if typ.TypeOf().String() == t.String() {
|
rtyp := typ.TypeOf()
|
||||||
destValue(f).Set(v.Elem())
|
if rtyp == nil {
|
||||||
|
return fnext
|
||||||
|
}
|
||||||
|
elem := v.Elem()
|
||||||
|
if rtyp.String() == t.String() && implementsInterface(v, typ) {
|
||||||
|
destValue(f).Set(elem)
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
ival := v.Interface()
|
ival := v.Interface()
|
||||||
if ival != nil && typ.TypeOf().String() == reflect.TypeOf(ival).String() {
|
if ival != nil && rtyp.String() == reflect.TypeOf(ival).String() {
|
||||||
destValue(f).Set(v.Elem())
|
destValue(f).Set(elem)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
if typ.cat == valueT && rtyp.Kind() == reflect.Interface && elem.IsValid() && elem.Type().Implements(rtyp) {
|
||||||
|
destValue(f).Set(elem)
|
||||||
return tnext
|
return tnext
|
||||||
}
|
}
|
||||||
return fnext
|
return fnext
|
||||||
@@ -2891,12 +3000,37 @@ func _case(n *node) {
|
|||||||
}
|
}
|
||||||
return fnext
|
return fnext
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// TODO(mpl): probably needs to be fixed for empty interfaces, like above.
|
|
||||||
// match against multiple types: assign var to interface value
|
|
||||||
n.exec = func(f *frame) bltn {
|
n.exec = func(f *frame) bltn {
|
||||||
val := srcValue(f)
|
val := srcValue(f)
|
||||||
if v := srcValue(f).Interface().(valueInterface).node; v != nil {
|
if t := val.Type(); t.Kind() == reflect.Interface {
|
||||||
|
for _, typ := range types {
|
||||||
|
if typ.cat == nilT && val.IsNil() {
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
rtyp := typ.TypeOf()
|
||||||
|
if rtyp == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
elem := val.Elem()
|
||||||
|
if rtyp.String() == t.String() && implementsInterface(val, typ) {
|
||||||
|
destValue(f).Set(elem)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
ival := val.Interface()
|
||||||
|
if ival != nil && rtyp.String() == reflect.TypeOf(ival).String() {
|
||||||
|
destValue(f).Set(elem)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
if typ.cat == valueT && rtyp.Kind() == reflect.Interface && elem.IsValid() && elem.Type().Implements(rtyp) {
|
||||||
|
destValue(f).Set(elem)
|
||||||
|
return tnext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fnext
|
||||||
|
}
|
||||||
|
if v := val.Interface().(valueInterface).node; v != nil {
|
||||||
for _, typ := range types {
|
for _, typ := range types {
|
||||||
if v.typ.id() == typ.id() {
|
if v.typ.id() == typ.id() {
|
||||||
destValue(f).Set(val)
|
destValue(f).Set(val)
|
||||||
@@ -2935,6 +3069,22 @@ func _case(n *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func implementsInterface(v reflect.Value, t *itype) bool {
|
||||||
|
rt := v.Type()
|
||||||
|
if t.cat == valueT {
|
||||||
|
return rt.Implements(t.rtype)
|
||||||
|
}
|
||||||
|
vt := &itype{cat: valueT, rtype: rt}
|
||||||
|
if vt.methods().contains(t.methods()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
vi, ok := v.Interface().(valueInterface)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return vi.node != nil && vi.node.typ.methods().contains(t.methods())
|
||||||
|
}
|
||||||
|
|
||||||
func appendSlice(n *node) {
|
func appendSlice(n *node) {
|
||||||
dest := genValueOutput(n, n.typ.rtype)
|
dest := genValueOutput(n, n.typ.rtype)
|
||||||
next := getExec(n.tnext)
|
next := getExec(n.tnext)
|
||||||
@@ -3169,7 +3319,7 @@ func _len(n *node) {
|
|||||||
val := value
|
val := value
|
||||||
value = func(f *frame) reflect.Value {
|
value = func(f *frame) reflect.Value {
|
||||||
v := val(f).Elem()
|
v := val(f).Elem()
|
||||||
for v.Type().Kind() == reflect.Ptr {
|
for v.Kind() == reflect.Ptr {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package interp
|
package interp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -50,7 +49,7 @@ func Test_effectivePkg(t *testing.T) {
|
|||||||
|
|
||||||
func Test_pkgDir(t *testing.T) {
|
func Test_pkgDir(t *testing.T) {
|
||||||
// create GOPATH
|
// create GOPATH
|
||||||
goPath, err := ioutil.TempDir("", "pkdir")
|
goPath, err := os.MkdirTemp("", "pkdir")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -854,6 +854,14 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.cat == valueT {
|
||||||
|
switch t.rtype.Kind() {
|
||||||
|
case reflect.Array, reflect.Ptr:
|
||||||
|
t = valueTOf(reflect.SliceOf(t.rtype.Elem()), withScope(sc))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
if t.cat == ptrT {
|
if t.cat == ptrT {
|
||||||
t = t.val
|
t = t.val
|
||||||
}
|
}
|
||||||
@@ -1819,6 +1827,7 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fieldFix := []int{} // Slice of field indices to fix for recursivity.
|
||||||
t.rtype = reflect.StructOf(fields)
|
t.rtype = reflect.StructOf(fields)
|
||||||
if ctx.isComplete() {
|
if ctx.isComplete() {
|
||||||
for _, s := range ctx.defined {
|
for _, s := range ctx.defined {
|
||||||
@@ -1826,6 +1835,9 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type {
|
|||||||
f := s.rtype.Field(i)
|
f := s.rtype.Field(i)
|
||||||
if strings.HasSuffix(f.Type.String(), "unsafe2.dummy") {
|
if strings.HasSuffix(f.Type.String(), "unsafe2.dummy") {
|
||||||
unsafe2.SetFieldType(s.rtype, i, ctx.rect.fixDummy(s.rtype.Field(i).Type))
|
unsafe2.SetFieldType(s.rtype, i, ctx.rect.fixDummy(s.rtype.Field(i).Type))
|
||||||
|
if name == s.path+"/"+s.name {
|
||||||
|
fieldFix = append(fieldFix, i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1834,13 +1846,16 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type {
|
|||||||
// The rtype has now been built, we can go back and rebuild
|
// The rtype has now been built, we can go back and rebuild
|
||||||
// all the recursive types that relied on this type.
|
// all the recursive types that relied on this type.
|
||||||
// However, as we are keyed by type name, if two or more (recursive) fields at
|
// However, as we are keyed by type name, if two or more (recursive) fields at
|
||||||
// the same depth level are of the same type, they "mask" each other, and only one
|
// the same depth level are of the same type, or a "variation" of the same type
|
||||||
// of them is in ctx.refs, which means this pass below does not fully do the job.
|
// (slice of, map of, etc), they "mask" each other, and only one
|
||||||
// Which is why we have the pass above that is done one last time, for all fields,
|
// of them is in ctx.refs. That is why the code around here is a bit convoluted,
|
||||||
// one the recursion has been fully resolved.
|
// and we need both the loop above, around all the struct fields, and the loop
|
||||||
|
// below, around the ctx.refs.
|
||||||
for _, f := range ctx.refs[name] {
|
for _, f := range ctx.refs[name] {
|
||||||
ftyp := f.typ.field[f.idx].typ.refType(&refTypeContext{defined: ctx.defined, rebuilding: true})
|
for _, index := range fieldFix {
|
||||||
unsafe2.SetFieldType(f.typ.rtype, f.idx, ftyp)
|
ftyp := f.typ.field[index].typ.refType(&refTypeContext{defined: ctx.defined, rebuilding: true})
|
||||||
|
unsafe2.SetFieldType(f.typ.rtype, index, ftyp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if z, _ := t.zero(); z.IsValid() {
|
if z, _ := t.zero(); z.IsValid() {
|
||||||
|
|||||||
@@ -850,7 +850,7 @@ func (check typecheck) builtin(name string, n *node, child []*node, ellipsis boo
|
|||||||
return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id())
|
return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id())
|
||||||
}
|
}
|
||||||
ktyp := params[1].Type()
|
ktyp := params[1].Type()
|
||||||
if !ktyp.assignableTo(typ.key) {
|
if typ.key != nil && !ktyp.assignableTo(typ.key) {
|
||||||
return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id())
|
return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id())
|
||||||
}
|
}
|
||||||
case bltnMake:
|
case bltnMake:
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ func genValueAsFunctionWrapper(n *node) func(*frame) reflect.Value {
|
|||||||
return reflect.New(typ).Elem()
|
return reflect.New(typ).Elem()
|
||||||
}
|
}
|
||||||
vn, ok := v.Interface().(*node)
|
vn, ok := v.Interface().(*node)
|
||||||
if ok && vn.rval.IsValid() && vn.rval.Type().Kind() == reflect.Func {
|
if ok && vn.rval.Kind() == reflect.Func {
|
||||||
// The node value is already a callable func, no need to wrap it.
|
// The node value is already a callable func, no need to wrap it.
|
||||||
return vn.rval
|
return vn.rval
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ func genValueAs(n *node, t reflect.Type) func(*frame) reflect.Value {
|
|||||||
|
|
||||||
return func(f *frame) reflect.Value {
|
return func(f *frame) reflect.Value {
|
||||||
v := value(f)
|
v := value(f)
|
||||||
switch v.Type().Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice, reflect.UnsafePointer:
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice, reflect.UnsafePointer:
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
return reflect.New(t).Elem()
|
return reflect.New(t).Elem()
|
||||||
@@ -338,13 +338,13 @@ func getConcreteValue(val reflect.Value) reflect.Value {
|
|||||||
if v.NumMethod() > 0 {
|
if v.NumMethod() > 0 {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
if v.Type().Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
// Search a concrete value in fields of an emulated interface.
|
// Search a concrete value in fields of an emulated interface.
|
||||||
for i := v.NumField() - 1; i >= 0; i-- {
|
for i := v.NumField() - 1; i >= 0; i-- {
|
||||||
vv := v.Field(i)
|
vv := v.Field(i)
|
||||||
if vv.Type().Kind() == reflect.Interface {
|
if vv.Kind() == reflect.Interface {
|
||||||
vv = vv.Elem()
|
vv = vv.Elem()
|
||||||
}
|
}
|
||||||
if vv.IsValid() {
|
if vv.IsValid() {
|
||||||
@@ -408,7 +408,7 @@ func genValueInterfaceValue(n *node) func(*frame) reflect.Value {
|
|||||||
|
|
||||||
return func(f *frame) reflect.Value {
|
return func(f *frame) reflect.Value {
|
||||||
v := value(f)
|
v := value(f)
|
||||||
if v.Interface().(valueInterface).node == nil {
|
if vi, ok := v.Interface().(valueInterface); ok && vi.node == nil {
|
||||||
// Uninitialized interface value, set it to a correct zero value.
|
// Uninitialized interface value, set it to a correct zero value.
|
||||||
v.Set(zeroInterfaceValue())
|
v.Set(zeroInterfaceValue())
|
||||||
v = value(f)
|
v = value(f)
|
||||||
@@ -421,7 +421,11 @@ func genValueNode(n *node) func(*frame) reflect.Value {
|
|||||||
value := genValue(n)
|
value := genValue(n)
|
||||||
|
|
||||||
return func(f *frame) reflect.Value {
|
return func(f *frame) reflect.Value {
|
||||||
return reflect.ValueOf(&node{rval: value(f)})
|
v := value(f)
|
||||||
|
if _, ok := v.Interface().(*node); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(&node{rval: v})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +434,7 @@ func vInt(v reflect.Value) (i int64) {
|
|||||||
i, _ = constant.Int64Val(constant.ToInt(c))
|
i, _ = constant.Int64Val(constant.ToInt(c))
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
switch v.Type().Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
i = v.Int()
|
i = v.Int()
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
@@ -448,7 +452,7 @@ func vUint(v reflect.Value) (i uint64) {
|
|||||||
i, _ = constant.Uint64Val(constant.ToInt(c))
|
i, _ = constant.Uint64Val(constant.ToInt(c))
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
switch v.Type().Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
i = uint64(v.Int())
|
i = uint64(v.Int())
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
@@ -468,7 +472,7 @@ func vComplex(v reflect.Value) (c complex128) {
|
|||||||
img, _ := constant.Float64Val(constant.Imag(c))
|
img, _ := constant.Float64Val(constant.Imag(c))
|
||||||
return complex(rel, img)
|
return complex(rel, img)
|
||||||
}
|
}
|
||||||
switch v.Type().Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
c = complex(float64(v.Int()), 0)
|
c = complex(float64(v.Int()), 0)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
@@ -486,7 +490,7 @@ func vFloat(v reflect.Value) (i float64) {
|
|||||||
i, _ = constant.Float64Val(constant.ToFloat(c))
|
i, _ = constant.Float64Val(constant.ToFloat(c))
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
switch v.Type().Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
i = float64(v.Int())
|
i = float64(v.Int())
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
|||||||
48
stdlib/go1_16_go_build_constraint.go
Normal file
48
stdlib/go1_16_go_build_constraint.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Code generated by 'yaegi extract go/build/constraint'. DO NOT EDIT.
|
||||||
|
|
||||||
|
// +build go1.16,!go1.17
|
||||||
|
|
||||||
|
package stdlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/build/constraint"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Symbols["go/build/constraint/constraint"] = map[string]reflect.Value{
|
||||||
|
// function, constant and variable definitions
|
||||||
|
"IsGoBuild": reflect.ValueOf(constraint.IsGoBuild),
|
||||||
|
"IsPlusBuild": reflect.ValueOf(constraint.IsPlusBuild),
|
||||||
|
"Parse": reflect.ValueOf(constraint.Parse),
|
||||||
|
"PlusBuildLines": reflect.ValueOf(constraint.PlusBuildLines),
|
||||||
|
|
||||||
|
// type definitions
|
||||||
|
"AndExpr": reflect.ValueOf((*constraint.AndExpr)(nil)),
|
||||||
|
"Expr": reflect.ValueOf((*constraint.Expr)(nil)),
|
||||||
|
"NotExpr": reflect.ValueOf((*constraint.NotExpr)(nil)),
|
||||||
|
"OrExpr": reflect.ValueOf((*constraint.OrExpr)(nil)),
|
||||||
|
"SyntaxError": reflect.ValueOf((*constraint.SyntaxError)(nil)),
|
||||||
|
"TagExpr": reflect.ValueOf((*constraint.TagExpr)(nil)),
|
||||||
|
|
||||||
|
// interface wrapper definitions
|
||||||
|
"_Expr": reflect.ValueOf((*_go_build_constraint_Expr)(nil)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _go_build_constraint_Expr is an interface wrapper for Expr type
|
||||||
|
type _go_build_constraint_Expr struct {
|
||||||
|
IValue interface{}
|
||||||
|
WEval func(ok func(tag string) bool) bool
|
||||||
|
WString func() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (W _go_build_constraint_Expr) Eval(ok func(tag string) bool) bool {
|
||||||
|
return W.WEval(ok)
|
||||||
|
}
|
||||||
|
func (W _go_build_constraint_Expr) String() string {
|
||||||
|
if W.WString == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return W.WString()
|
||||||
|
}
|
||||||
49
stdlib/go1_17_go_build_constraint.go
Normal file
49
stdlib/go1_17_go_build_constraint.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Code generated by 'yaegi extract go/build/constraint'. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build go1.17
|
||||||
|
// +build go1.17
|
||||||
|
|
||||||
|
package stdlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/build/constraint"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Symbols["go/build/constraint/constraint"] = map[string]reflect.Value{
|
||||||
|
// function, constant and variable definitions
|
||||||
|
"IsGoBuild": reflect.ValueOf(constraint.IsGoBuild),
|
||||||
|
"IsPlusBuild": reflect.ValueOf(constraint.IsPlusBuild),
|
||||||
|
"Parse": reflect.ValueOf(constraint.Parse),
|
||||||
|
"PlusBuildLines": reflect.ValueOf(constraint.PlusBuildLines),
|
||||||
|
|
||||||
|
// type definitions
|
||||||
|
"AndExpr": reflect.ValueOf((*constraint.AndExpr)(nil)),
|
||||||
|
"Expr": reflect.ValueOf((*constraint.Expr)(nil)),
|
||||||
|
"NotExpr": reflect.ValueOf((*constraint.NotExpr)(nil)),
|
||||||
|
"OrExpr": reflect.ValueOf((*constraint.OrExpr)(nil)),
|
||||||
|
"SyntaxError": reflect.ValueOf((*constraint.SyntaxError)(nil)),
|
||||||
|
"TagExpr": reflect.ValueOf((*constraint.TagExpr)(nil)),
|
||||||
|
|
||||||
|
// interface wrapper definitions
|
||||||
|
"_Expr": reflect.ValueOf((*_go_build_constraint_Expr)(nil)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _go_build_constraint_Expr is an interface wrapper for Expr type
|
||||||
|
type _go_build_constraint_Expr struct {
|
||||||
|
IValue interface{}
|
||||||
|
WEval func(ok func(tag string) bool) bool
|
||||||
|
WString func() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (W _go_build_constraint_Expr) Eval(ok func(tag string) bool) bool {
|
||||||
|
return W.WEval(ok)
|
||||||
|
}
|
||||||
|
func (W _go_build_constraint_Expr) String() string {
|
||||||
|
if W.WString == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return W.WString()
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ func init() {
|
|||||||
//go:generate ../internal/cmd/extract/extract encoding/base64 encoding/binary encoding/csv encoding/gob
|
//go:generate ../internal/cmd/extract/extract encoding/base64 encoding/binary encoding/csv encoding/gob
|
||||||
//go:generate ../internal/cmd/extract/extract encoding/hex encoding/json encoding/pem encoding/xml
|
//go:generate ../internal/cmd/extract/extract encoding/hex encoding/json encoding/pem encoding/xml
|
||||||
//go:generate ../internal/cmd/extract/extract errors expvar flag fmt
|
//go:generate ../internal/cmd/extract/extract errors expvar flag fmt
|
||||||
//go:generate ../internal/cmd/extract/extract go/ast go/build go/constant go/doc go/format go/importer
|
//go:generate ../internal/cmd/extract/extract go/ast go/build go/build/constraint go/constant go/doc go/format go/importer
|
||||||
//go:generate ../internal/cmd/extract/extract go/parser go/printer go/scanner go/token go/types
|
//go:generate ../internal/cmd/extract/extract go/parser go/printer go/scanner go/token go/types
|
||||||
//go:generate ../internal/cmd/extract/extract hash hash/adler32 hash/crc32 hash/crc64 hash/fnv hash/maphash
|
//go:generate ../internal/cmd/extract/extract hash hash/adler32 hash/crc32 hash/crc64 hash/fnv hash/maphash
|
||||||
//go:generate ../internal/cmd/extract/extract html html/template
|
//go:generate ../internal/cmd/extract/extract html html/template
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func slice(i interface{}, l int) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(i)
|
v := reflect.ValueOf(i)
|
||||||
if v.Type().Kind() != reflect.Ptr {
|
if v.Kind() != reflect.Ptr {
|
||||||
panic(errors.New("first argument to unsafe.Slice must be pointer"))
|
panic(errors.New("first argument to unsafe.Slice must be pointer"))
|
||||||
}
|
}
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
|
|||||||
Reference in New Issue
Block a user