Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b62f9fdb6 | ||
|
|
4f66e3fe6c | ||
|
|
1335b4c64f | ||
|
|
da03c922ca | ||
|
|
9620116c30 | ||
|
|
dd7197f2a2 |
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -13,7 +13,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -21,7 +21,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -13,7 +13,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -40,7 +40,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -40,7 +40,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -41,7 +41,7 @@ func client(uri string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,12 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
file, err := ioutil.TempFile("", "yeagibench")
|
||||
file, err := os.CreateTemp("", "yeagibench")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -23,7 +22,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(file.Name())
|
||||
b, err := os.ReadFile(file.Name())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func main() {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -13,7 +12,7 @@ type sink interface {
|
||||
|
||||
func newSink() sink {
|
||||
// return os.Stdout // Stdout is special in yaegi tests
|
||||
file, err := ioutil.TempFile("", "yaegi-test.*")
|
||||
file, err := os.CreateTemp("", "yaegi-test.*")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"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 main() {
|
||||
tmpfile, err := ioutil.TempFile("", "xxx")
|
||||
tmpfile, err := os.CreateTemp("", "xxx")
|
||||
if err != nil {
|
||||
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
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
@@ -36,7 +35,7 @@ type pipe struct {
|
||||
|
||||
func newReadAutoCloser(r io.Reader) readAutoCloser {
|
||||
if _, ok := r.(io.Closer); !ok {
|
||||
return readAutoCloser{ioutil.NopCloser(r)}
|
||||
return readAutoCloser{io.NopCloser(r)}
|
||||
}
|
||||
return readAutoCloser{r.(io.ReadCloser)}
|
||||
}
|
||||
@@ -44,7 +43,7 @@ func newReadAutoCloser(r io.Reader) readAutoCloser {
|
||||
func main() {
|
||||
p := &pipe{}
|
||||
p.Reader = newReadAutoCloser(strings.NewReader("test"))
|
||||
b, err := ioutil.ReadAll(p.Reader)
|
||||
b, err := io.ReadAll(p.Reader)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := ioutil.ReadFile("__NotExisting__")
|
||||
_, err := os.ReadFile("__NotExisting__")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -135,7 +134,7 @@ func isFile(path string) bool {
|
||||
}
|
||||
|
||||
func runFile(i *interp.Interpreter, path string, noAutoImport bool) error {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -38,7 +37,7 @@ func applyCIMultiplier(timeout time.Duration) time.Duration {
|
||||
}
|
||||
|
||||
func TestYaegiCmdCancel(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "yaegi-")
|
||||
tmp, err := os.MkdirTemp("", "yaegi-")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tmp directory: %v", err)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
@@ -1183,7 +1183,7 @@ func main() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,9 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if n.scope == nil {
|
||||
n.scope = sc
|
||||
}
|
||||
switch n.kind {
|
||||
case binaryExpr, unaryExpr, parenExpr:
|
||||
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 {
|
||||
err = n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, lc.child[0].name(), r)
|
||||
}
|
||||
if isBinCall(lc, sc) {
|
||||
n.gen = nop
|
||||
} else {
|
||||
// TODO (marc): skip if no conversion or wrapping is needed.
|
||||
n.gen = assignFromCall
|
||||
}
|
||||
case indexExpr:
|
||||
lc.gen = getIndexMap2
|
||||
n.gen = nop
|
||||
@@ -970,7 +978,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
n.typ = c0.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)
|
||||
if err != nil {
|
||||
break
|
||||
@@ -2019,7 +2027,12 @@ func compDefineX(sc *scope, n *node) error {
|
||||
if len(types) != l {
|
||||
return n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, src.child[0].name(), len(types))
|
||||
}
|
||||
if isBinCall(src, sc) {
|
||||
n.gen = nop
|
||||
} else {
|
||||
// TODO (marc): skip if no conversion or wrapping is needed.
|
||||
n.gen = assignFromCall
|
||||
}
|
||||
|
||||
case indexExpr:
|
||||
types = append(types, src.typ, sc.getType("bool"))
|
||||
@@ -2468,8 +2481,19 @@ func isCall(n *node) bool {
|
||||
return n.action == aCall || n.action == aCallSlice
|
||||
}
|
||||
|
||||
func isBinCall(n *node) bool {
|
||||
return isCall(n) && n.child[0].typ.cat == valueT && n.child[0].typ.rtype.Kind() == reflect.Func
|
||||
func isBinCall(n *node, sc *scope) bool {
|
||||
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 {
|
||||
|
||||
@@ -3,7 +3,6 @@ package interp
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os/exec"
|
||||
"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.
|
||||
func dotWriter(dotCmd string) io.WriteCloser {
|
||||
if dotCmd == "" {
|
||||
return nopCloser{ioutil.Discard}
|
||||
return nopCloser{io.Discard}
|
||||
}
|
||||
fields := strings.Fields(dotCmd)
|
||||
cmd := exec.Command(fields[0], fields[1:]...)
|
||||
|
||||
@@ -2,7 +2,7 @@ package interp_test
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -26,7 +26,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
}
|
||||
|
||||
baseDir := filepath.Join("..", "_test")
|
||||
files, err := ioutil.ReadDir(baseDir)
|
||||
files, err := os.ReadDir(baseDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
if err = w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
outInterp, err := ioutil.ReadAll(r)
|
||||
outInterp, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -885,7 +884,7 @@ func TestMultiEval(t *testing.T) {
|
||||
if err = w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
outInterp, err := ioutil.ReadAll(r)
|
||||
outInterp, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -916,7 +915,7 @@ func TestMultiEvalNoName(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -26,7 +25,7 @@ func TestFile(t *testing.T) {
|
||||
_ = os.Setenv("YAEGI_SPECIAL_STDIO", "1")
|
||||
|
||||
baseDir := filepath.Join("..", "_test")
|
||||
files, err := ioutil.ReadDir(baseDir)
|
||||
files, err := os.ReadDir(baseDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package interp
|
||||
import (
|
||||
"context"
|
||||
"go/ast"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
@@ -28,7 +28,7 @@ func (interp *Interpreter) CompilePath(path string) (*Program, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
115
interp/run.go
115
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) {
|
||||
next := getExec(n.tnext)
|
||||
dvalue := make([]func(*frame) reflect.Value, n.nleft)
|
||||
@@ -957,7 +985,7 @@ func genFunctionWrapper(n *node) func(*frame) reflect.Value {
|
||||
} else {
|
||||
// Copy method receiver as first argument.
|
||||
src, dest := rcvr(f), d[numRet]
|
||||
sk, dk := src.Type().Kind(), dest.Type().Kind()
|
||||
sk, dk := src.Kind(), dest.Kind()
|
||||
switch {
|
||||
case sk == reflect.Ptr && dk != reflect.Ptr:
|
||||
dest.Set(src.Elem())
|
||||
@@ -1097,27 +1125,28 @@ func methodByName(value reflect.Value, name string) reflect.Value {
|
||||
func call(n *node) {
|
||||
goroutine := n.anc.kind == goStmt
|
||||
var method bool
|
||||
value := genValue(n.child[0])
|
||||
c0 := n.child[0]
|
||||
value := genValue(c0)
|
||||
var values []func(*frame) reflect.Value
|
||||
|
||||
recvIndexLater := false
|
||||
switch {
|
||||
case n.child[0].recv != nil:
|
||||
case c0.recv != nil:
|
||||
// Compute method receiver value.
|
||||
values = append(values, genValueRecv(n.child[0]))
|
||||
values = append(values, genValueRecv(c0))
|
||||
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
|
||||
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)
|
||||
method = true
|
||||
case n.child[0].action == aMethod:
|
||||
case c0.action == aMethod:
|
||||
// Add a place holder for interface method receiver.
|
||||
values = append(values, nil)
|
||||
method = true
|
||||
}
|
||||
|
||||
numRet := len(n.child[0].typ.ret)
|
||||
numRet := len(c0.typ.ret)
|
||||
variadic := variadicPos(n)
|
||||
child := n.child[1:]
|
||||
tnext := getExec(n.tnext)
|
||||
@@ -1125,27 +1154,40 @@ func call(n *node) {
|
||||
|
||||
// Compute input argument value functions.
|
||||
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 {
|
||||
case isBinCall(c):
|
||||
case isBinCall(c, c.scope):
|
||||
// Handle nested function calls: pass returned values as arguments.
|
||||
numOut := c.child[0].typ.rtype.NumOut()
|
||||
for j := 0; j < numOut; j++ {
|
||||
ind := c.findex + j
|
||||
if !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):
|
||||
// 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
|
||||
if !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:
|
||||
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() {
|
||||
argType := arg.TypeOf()
|
||||
convertLiteralValue(c, argType)
|
||||
@@ -1165,10 +1207,11 @@ func call(n *node) {
|
||||
}
|
||||
|
||||
// Compute output argument value functions.
|
||||
rtypes := n.child[0].typ.ret
|
||||
rtypes := c0.typ.ret
|
||||
rvalues := make([]func(*frame) reflect.Value, len(rtypes))
|
||||
switch n.anc.kind {
|
||||
case defineXStmt, assignXStmt:
|
||||
l := n.level
|
||||
for i := range rvalues {
|
||||
c := n.anc.child[i]
|
||||
switch {
|
||||
@@ -1177,7 +1220,8 @@ func call(n *node) {
|
||||
case isInterfaceSrc(c.typ) && !isEmptyInterface(c.typ) && !isInterfaceSrc(rtypes[i]):
|
||||
rvalues[i] = genValueInterfaceValue(c)
|
||||
default:
|
||||
rvalues[i] = genValue(c)
|
||||
j := n.findex + i
|
||||
rvalues[i] = func(f *frame) reflect.Value { return getFrame(f, l).data[j] }
|
||||
}
|
||||
}
|
||||
case returnStmt:
|
||||
@@ -1198,7 +1242,7 @@ func call(n *node) {
|
||||
|
||||
if n.anc.kind == deferStmt {
|
||||
// Store function call in frame for deferred execution.
|
||||
value = genFunctionWrapper(n.child[0])
|
||||
value = genFunctionWrapper(c0)
|
||||
if method {
|
||||
// The receiver is already passed in the function wrapper, skip it.
|
||||
values = values[1:]
|
||||
@@ -1328,7 +1372,7 @@ func call(n *node) {
|
||||
// The !val.IsZero is to work around a recursive struct zero interface
|
||||
// issue. 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 {
|
||||
if !val.IsZero() || dest[i].Kind() == reflect.Interface {
|
||||
dest[i].Set(val)
|
||||
}
|
||||
}
|
||||
@@ -1404,7 +1448,7 @@ func callBin(n *node) {
|
||||
}
|
||||
|
||||
switch {
|
||||
case isBinCall(c):
|
||||
case isBinCall(c, c.scope):
|
||||
// Handle nested function calls: pass returned values as arguments
|
||||
numOut := c.child[0].typ.rtype.NumOut()
|
||||
for j := 0; j < numOut; j++ {
|
||||
@@ -1566,7 +1610,7 @@ func callBin(n *node) {
|
||||
}
|
||||
out := callFn(value(f), in)
|
||||
for i := 0; i < len(out); i++ {
|
||||
if out[i].Type().Kind() == reflect.Func {
|
||||
if out[i].Kind() == reflect.Func {
|
||||
getFrame(f, n.level).data[n.findex+i] = out[i]
|
||||
} else {
|
||||
getFrame(f, n.level).data[n.findex+i].Set(out[i])
|
||||
@@ -2533,7 +2577,7 @@ func doCompositeBinStruct(n *node, hasType bool) {
|
||||
}
|
||||
d := value(f)
|
||||
switch {
|
||||
case d.Type().Kind() == reflect.Ptr:
|
||||
case d.Kind() == reflect.Ptr:
|
||||
d.Set(s.Addr())
|
||||
default:
|
||||
d.Set(s)
|
||||
@@ -2611,7 +2655,7 @@ func doComposite(n *node, hasType bool, keyed bool) {
|
||||
}
|
||||
d := value(f)
|
||||
switch {
|
||||
case d.Type().Kind() == reflect.Ptr:
|
||||
case d.Kind() == reflect.Ptr:
|
||||
d.Set(a.Addr())
|
||||
case destInterface:
|
||||
if len(destType(n).field) > 0 {
|
||||
@@ -2867,12 +2911,13 @@ func _case(n *node) {
|
||||
if typ.cat == nilT && v.IsNil() {
|
||||
return tnext
|
||||
}
|
||||
if typ.TypeOf().String() == t.String() {
|
||||
rtyp := typ.TypeOf()
|
||||
if rtyp != nil && rtyp.String() == t.String() && implementsInterface(v, typ) {
|
||||
destValue(f).Set(v.Elem())
|
||||
return tnext
|
||||
}
|
||||
ival := v.Interface()
|
||||
if ival != nil && typ.TypeOf().String() == reflect.TypeOf(ival).String() {
|
||||
if ival != nil && rtyp != nil && rtyp.String() == reflect.TypeOf(ival).String() {
|
||||
destValue(f).Set(v.Elem())
|
||||
return tnext
|
||||
}
|
||||
@@ -2935,6 +2980,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) {
|
||||
dest := genValueOutput(n, n.typ.rtype)
|
||||
next := getExec(n.tnext)
|
||||
@@ -3169,7 +3230,7 @@ func _len(n *node) {
|
||||
val := value
|
||||
value = func(f *frame) reflect.Value {
|
||||
v := val(f).Elem()
|
||||
for v.Type().Kind() == reflect.Ptr {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -50,7 +49,7 @@ func Test_effectivePkg(t *testing.T) {
|
||||
|
||||
func Test_pkgDir(t *testing.T) {
|
||||
// create GOPATH
|
||||
goPath, err := ioutil.TempDir("", "pkdir")
|
||||
goPath, err := os.MkdirTemp("", "pkdir")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
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())
|
||||
}
|
||||
case bltnMake:
|
||||
|
||||
@@ -147,7 +147,7 @@ func genValueAsFunctionWrapper(n *node) func(*frame) reflect.Value {
|
||||
return reflect.New(typ).Elem()
|
||||
}
|
||||
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.
|
||||
return vn.rval
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func genValueAs(n *node, t reflect.Type) func(*frame) reflect.Value {
|
||||
|
||||
return func(f *frame) reflect.Value {
|
||||
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:
|
||||
if v.IsNil() {
|
||||
return reflect.New(t).Elem()
|
||||
@@ -338,13 +338,13 @@ func getConcreteValue(val reflect.Value) reflect.Value {
|
||||
if v.NumMethod() > 0 {
|
||||
return v
|
||||
}
|
||||
if v.Type().Kind() != reflect.Struct {
|
||||
if v.Kind() != reflect.Struct {
|
||||
return v
|
||||
}
|
||||
// Search a concrete value in fields of an emulated interface.
|
||||
for i := v.NumField() - 1; i >= 0; i-- {
|
||||
vv := v.Field(i)
|
||||
if vv.Type().Kind() == reflect.Interface {
|
||||
if vv.Kind() == reflect.Interface {
|
||||
vv = vv.Elem()
|
||||
}
|
||||
if vv.IsValid() {
|
||||
@@ -430,7 +430,7 @@ func vInt(v reflect.Value) (i int64) {
|
||||
i, _ = constant.Int64Val(constant.ToInt(c))
|
||||
return i
|
||||
}
|
||||
switch v.Type().Kind() {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i = v.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
@@ -448,7 +448,7 @@ func vUint(v reflect.Value) (i uint64) {
|
||||
i, _ = constant.Uint64Val(constant.ToInt(c))
|
||||
return i
|
||||
}
|
||||
switch v.Type().Kind() {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i = uint64(v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
@@ -468,7 +468,7 @@ func vComplex(v reflect.Value) (c complex128) {
|
||||
img, _ := constant.Float64Val(constant.Imag(c))
|
||||
return complex(rel, img)
|
||||
}
|
||||
switch v.Type().Kind() {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
c = complex(float64(v.Int()), 0)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
@@ -486,7 +486,7 @@ func vFloat(v reflect.Value) (i float64) {
|
||||
i, _ = constant.Float64Val(constant.ToFloat(c))
|
||||
return i
|
||||
}
|
||||
switch v.Type().Kind() {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i = float64(v.Int())
|
||||
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/hex encoding/json encoding/pem encoding/xml
|
||||
//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 hash hash/adler32 hash/crc32 hash/crc64 hash/fnv hash/maphash
|
||||
//go:generate ../internal/cmd/extract/extract html html/template
|
||||
|
||||
@@ -31,7 +31,7 @@ func slice(i interface{}, l int) interface{} {
|
||||
}
|
||||
|
||||
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"))
|
||||
}
|
||||
if v.IsNil() {
|
||||
|
||||
Reference in New Issue
Block a user