Compare commits

...

41 Commits

Author SHA1 Message Date
Marc Vertes
cdf4622421 fix: assign an element in a map from runtime 2020-05-05 22:46:04 +02:00
Marc Vertes
b9720d15e1 fix: improve setting results in multiple output functions 2020-05-05 22:34:03 +02:00
Marc Vertes
7fab75fbe4 fix: correct assign from function returning an interface value (#625) 2020-05-05 13:54:36 +02:00
Marc Vertes
7eac6955b3 feature: pre-import used packages in REPL mode. 2020-05-04 16:18:05 +02:00
Marc Vertes
7070367d21 fix: handle constant declarations inside function scopes 2020-05-03 18:56:04 +02:00
Marc Vertes
22dfc8b10a fix: handle set of variadic arg list for a ... value 2020-05-03 18:44:04 +02:00
Marc Vertes
7fba3fe580 fix: improve generation of interface wrapper 2020-05-03 18:32:04 +02:00
Marc Vertes
ff36ec58b1 fix: improve switch and type switch statement processing 2020-05-03 18:20:04 +02:00
Marc Vertes
f6c8b8b14f fix: check that a function returns the correct number of values 2020-05-03 18:08:03 +02:00
Marc Vertes
e12c8b72c4 fix: store the result of a bin function call in frame 2020-05-03 17:56:04 +02:00
Marc Vertes
e4acba031d fix: improving handling of functions returning interfaces 2020-05-03 17:46:03 +02:00
Marc Vertes
7d56fb067e fix: improve setting of interface objects 2020-04-30 17:44:04 +02:00
Marc Vertes
1feece61ce fix: improve handling of function return values 2020-04-30 10:32:04 +02:00
Marc Vertes
01e2e4600e fix: handle default comm clause in select 2020-04-25 17:40:08 +02:00
Marc Vertes
92eebbade2 fix: handle function output value assigned to interface var 2020-04-25 17:28:04 +02:00
Marc Vertes
a6389aca5e fix: improve handling of nil 2020-04-25 17:16:03 +02:00
Marc Vertes
de8cb7dc3b fix: handle type conversion from pre-compiled types. 2020-04-23 19:20:04 +02:00
Marc Vertes
18b843646c fix: parsing of recursive interface types 2020-04-22 19:26:05 +02:00
Marc Vertes
71f730b3d7 fix: handle forward declaration for aliased type 2020-04-22 10:50:05 +02:00
Marc Vertes
7b2d91bcb5 fix: handling values in map of interfaces 2020-04-22 10:34:05 +02:00
Marc Vertes
3ed4ec3f6f fix: correct type assertion for bin func types (#588) 2020-04-20 23:01:01 +02:00
Marc Vertes
5e142fdedd fix: do not attempt to copy data in empty frame at func call 2020-04-18 18:36:04 +02:00
Marc Vertes
94d44e7265 fix: do not convert literal float to int at parse 2020-04-17 17:54:03 +02:00
Marc Vertes
56925e6fea fix: correct branch control flow graph for parenthesis expressions (#583) 2020-04-17 14:40:56 +02:00
Marc Vertes
c580dfdbc8 fix: correct handling of interface types in composite literals 2020-04-16 19:54:03 +02:00
Marc Vertes
29e1777d82 fix: assign composite literal by reference 2020-04-16 12:24:04 +02:00
Marc Vertes
50a34fd2a7 fix: correct control flow graph for select blocks 2020-04-15 12:24:04 +02:00
Marc Vertes
465cb578e7 fix: lookup embededded field on struct pointer 2020-04-09 01:26:03 +02:00
Marc Vertes
12942b59a0 fix: remove ambiguities in recursive type processing 2020-04-09 01:14:03 +02:00
Marc Vertes
3e76267f8e fix: method search on struct pointer in interface wrapper 2020-04-07 17:22:04 +02:00
Marc Vertes
988f0c9672 fix: better handling of recursive types and forward declarations 2020-04-07 13:06:03 +02:00
Marc Vertes
b0053c874f fix: incomplete type analysis 2020-04-03 04:14:04 +02:00
Marc Vertes
b20ad3a01d fix: checks that value implements a binary type in type assert 2020-04-03 04:02:04 +02:00
Marc Vertes
e78650d359 fix: correct branch action in parenthesis expression 2020-03-26 12:10:04 +01:00
Marc Vertes
7327ff2811 fix: correct comparison of interface type to nil 2020-03-25 13:56:05 +01:00
Marc Vertes
ebde09b47d fix: correct control flow graph for switch statement 2020-03-25 12:40:04 +01:00
Marc Vertes
4995654e04 fix: correct control flow graph for constant conditional statements 2020-03-25 12:18:05 +01:00
Marc Vertes
0a99eb48c3 fix: do not pass twice the receiver in deferred method calls 2020-03-23 13:40:03 +01:00
Ludovic Fernandez
4a22635585 doc: update supported Go version in the readme. 2020-03-20 12:36:04 +01:00
Marc Vertes
b52dd8cc08 fix: substitute recursive struct type by interface{} in function arguments 2020-03-19 12:42:05 +01:00
Marc Vertes
daaeac6e2c fix: convert literal nil to interface types 2020-03-18 10:34:05 +01:00
109 changed files with 2622 additions and 407 deletions

View File

@@ -18,7 +18,7 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
* Works everywhere Go works
* All Go & runtime resources accessible from script (with control)
* Security: `unsafe` and `syscall` packages neither used nor exported by default
* Support Go 1.12 and Go 1.13 (the latest 2 major releases)
* Support Go 1.13 and Go 1.14 (the latest 2 major releases)
## Install

9
_test/add0.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{} = 2 + 5
println(a.(int))
}
// Output:
// 7

10
_test/add1.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
b := 2
var a interface{} = 5 + b
println(a.(int))
}
// Output:
// 7

12
_test/add2.go Normal file
View File

@@ -0,0 +1,12 @@
package main
type iface interface{}
func main() {
b := 2
var a iface = 5 + b
println(a.(int))
}
// Output:
// 7

14
_test/append0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func f(a []int, b int) interface{} { return append(a, b) }
func main() {
a := []int{1, 2}
r := f(a, 3)
fmt.Println(r.([]int))
}
// Output:
// [1 2 3]

10
_test/assign11.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "fmt"
func main() {
_, _, _ = fmt.Println("test")
}
// Error:
// 6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values

11
_test/assign12.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a, b, c := fmt.Println("test")
println(a, b, c)
}
// Error:
// 6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values

18
_test/bin4.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"strings"
)
func Bar(s string) bool {
a := strings.HasPrefix("fas", "f")
b := strings.HasPrefix("aaaaa", "a")
a_and_b := strings.HasPrefix("fas", "f") && strings.HasPrefix("aaaaa", "a")
fmt.Println(a, b, a && b, a_and_b)
return a && b
}
func main() {
println(Bar("kung"))
}

15
_test/bin5.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"net"
)
func main() {
addr := net.TCPAddr{IP: net.IPv4(1, 1, 1, 1), Port: 80}
var s fmt.Stringer = &addr
fmt.Println(s.String())
}
// Output:
// 1.1.1.1:80

13
_test/cap0.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f(a []int) interface{} {
return cap(a)
}
func main() {
a := []int{1, 2}
println(f(a).(int))
}
// Output:
// 2

20
_test/chan9.go Normal file
View File

@@ -0,0 +1,20 @@
package main
type Channel chan string
type T struct {
Channel
}
func send(c Channel) { c <- "ping" }
func main() {
t := &T{}
t.Channel = make(Channel)
go send(t.Channel)
msg := <-t.Channel
println(msg)
}
// Output:
// ping

59
_test/cli2.go Normal file
View File

@@ -0,0 +1,59 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
)
type T struct {
ln net.Listener
}
func (t *T) Close() {
t.ln.Close()
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
func server(ln net.Listener, ready chan bool) {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
var r1 *http.Request = r
fmt.Fprintln(w, "Welcome to my website!", r1.RequestURI)
})
go http.Serve(ln, nil)
ready <- true
}
func main() {
ln, err := net.Listen("tcp", "localhost:0")
t := &T{ln}
if err != nil {
log.Fatal(err)
}
defer t.Close()
// defer ln.Close()
ready := make(chan bool)
go server(ln, ready)
<-ready
client(fmt.Sprintf("http://%s/hello", ln.Addr().String()))
http.DefaultServeMux = &http.ServeMux{}
}
// Output:
// Welcome to my website! /hello

9
_test/comp1.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{} = 1 < 2
println(a.(bool))
}
// Output:
// true

13
_test/complex4.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import "fmt"
func f(a, b float64) interface{} { return complex(a, b) }
func main() {
a := f(3, 2)
fmt.Println(a.(complex128))
}
// Output:
// (3+2i)

16
_test/composite8.go Normal file
View File

@@ -0,0 +1,16 @@
package main
type T struct{ I int }
func main() {
t := []*T{}
s := []int{1, 2}
for _, e := range s {
x := &T{e}
t = append(t, x)
}
println(t[0].I, t[1].I)
}
// Output:
// 1 2

13
_test/const11.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
const (
x = 2 * iota
dim
)
var t [dim * 2]int
println(t[0], len(t))
}
// Output:
// 0 4

16
_test/copy2.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import "fmt"
func f(a, b []int) interface{} { return copy(a, b) }
func main() {
a := []int{10, 20, 30}
b := [4]int{}
c := b[:]
r := f(c, a)
fmt.Println(r.(int))
}
// Output:
// 3

13
_test/for10.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
for a := 0; false; {
println("nok", a)
a++
break
}
println("bye")
}
// Output:
// bye

14
_test/for11.go Normal file
View File

@@ -0,0 +1,14 @@
package main
func main() {
a := 0
for ; true; a++ {
println("nok", a)
break
}
println("bye", a)
}
// Output:
// nok 0
// bye 0

12
_test/for12.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
for a := 0; false; a++ {
println("nok", a)
break
}
println("bye")
}
// Output:
// bye

13
_test/for13.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
a := 0
for ; false; a++ {
println("nok", a)
break
}
println("bye", a)
}
// Output:
// bye 0

16
_test/for14.go Normal file
View File

@@ -0,0 +1,16 @@
package main
func main() {
for a := 0; true; a++ {
println(a)
if a > 0 {
break
}
}
println("bye")
}
// Output:
// 0
// 1
// bye

12
_test/for9.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
for false {
println("nok")
break
}
println("bye")
}
// Output:
// bye

12
_test/fun12.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func use(interface{}) {}
func main() {
z := map[string]interface{}{"a": 5}
use(z)
println("bye")
}
// Output:
// bye

19
_test/fun13.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import "fmt"
type T struct{}
func newT() (T, error) { return T{}, nil }
func main() {
var (
i interface{}
err error
)
i, err = newT()
fmt.Println(i, err)
}
// Output:
// {} <nil>

13
_test/fun14.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f() (bool, int) { return true, 2 }
func g() (bool, int) { return f() }
func main() {
b, i := g()
println(b, i)
}
// Output:
// true 2

11
_test/fun15.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func f1(a int) interface{} { return a + 1 }
func main() {
c := f1(3)
println(c.(int))
}
// Output:
// 4

13
_test/fun16.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f1(a int) int { return a + 1 }
func f2(a int) interface{} { return f1(a) }
func main() {
c := f2(3)
println(c.(int))
}
// Output:
// 4

13
_test/fun17.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f1(a int) interface{} { return a + 1 }
func f2(a int) interface{} { return f1(a) }
func main() {
c := f2(3)
println(c.(int))
}
// Output:
// 4

12
_test/fun18.go Normal file
View File

@@ -0,0 +1,12 @@
package main
var m = map[string]int{"foo": 1, "bar": 2}
func f(s string) interface{} { return m[s] }
func main() {
println(f("foo").(int))
}
// Output:
// 1

17
_test/fun19.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
)
func foo() ([]string, error) {
return nil, fmt.Errorf("bar")
}
func main() {
a, b := foo()
fmt.Println(a, b)
}
// Output:
// [] bar

19
_test/fun20.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import "fmt"
var myerr error = fmt.Errorf("bar")
func ferr() error { return myerr }
func foo() ([]string, error) {
return nil, ferr()
}
func main() {
a, b := foo()
fmt.Println(a, b)
}
// Output:
// [] bar

17
_test/if3.go Normal file
View File

@@ -0,0 +1,17 @@
package main
func main() {
a := 0
if false {
println("false")
a = 1
} else {
println("true")
a = -1
}
println(a)
}
// Output:
// true
// -1

19
_test/if4.go Normal file
View File

@@ -0,0 +1,19 @@
package main
const bad = false
func main() {
a := 0
if bad {
println("false")
a = 1
} else {
println("true")
a = -1
}
println(a)
}
// Output:
// true
// -1

12
_test/if5.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
if true {
println("ok")
}
println("bye")
}
// Output:
// ok
// bye

11
_test/if6.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
if false {
println("nok")
}
println("bye")
}
// Output:
// bye

15
_test/if7.go Normal file
View File

@@ -0,0 +1,15 @@
package main
func main() {
a := 0
b := false
if (b) {
a = 1
} else {
a = -1
}
println(a)
}
// Output:
// -1

14
_test/imag0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func f(c complex128) interface{} { return imag(c) }
func main() {
c := complex(3, 2)
a := f(c)
fmt.Println(a.(float64))
}
// Output:
// 2

12
_test/interface27.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
var errs = map[int]error{0: nil}
func main() {
fmt.Println(errs)
}
// Output:
// map[0:<nil>]

12
_test/interface28.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
var errs = []error{nil}
func main() {
fmt.Println(errs)
}
// Output:
// [<nil>]

9
_test/interface29.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{}
println(a == nil)
}
// Output:
// true

9
_test/interface30.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{}
println(a != nil)
}
// Output:
// false

11
_test/interface31.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
s := []interface{}{"test", 2}
fmt.Println(s[0], s[1])
}
// Output:
// test 2

11
_test/interface32.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
s := [2]interface{}{"test", 2}
fmt.Println(s[0], s[1])
}
// Output:
// test 2

11
_test/interface33.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
var a = map[string]interface{}{"test": "test"}
fmt.Println(a["test"])
}
// Output:
// test

11
_test/interface34.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
s := [2]interface{}{1: "test", 0: 2}
fmt.Println(s[0], s[1])
}
// Output:
// 2 test

15
_test/interface35.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
type T struct {
I interface{}
}
func main() {
t := T{"test"}
fmt.Println(t)
}
// Output:
// {test}

37
_test/interface36.go Normal file
View File

@@ -0,0 +1,37 @@
package main
import "fmt"
var (
t *S
_ I = t
_ J = t
)
type S struct {
Name string
}
func (s *S) F() int { return len(s.Name) }
func (s *S) G() int { return s.F() }
func (s *S) Ri() I { return s }
func (s *S) Rj() J { return s }
type J interface {
I
G() int
Rj() J
}
type I interface {
F() int
Ri() I
}
func main() {
var j J
fmt.Println(j)
}
// Output:
// <nil>

23
_test/interface37.go Normal file
View File

@@ -0,0 +1,23 @@
package main
type I interface {
A() string
B() string
}
type s struct{}
func NewS() (I, error) {
return &s{}, nil
}
func (c *s) A() string { return "a" }
func (c *s) B() string { return "b" }
func main() {
s, _ := NewS()
println(s.A())
}
// Output:
// a

55
_test/issue-558.go Normal file
View File

@@ -0,0 +1,55 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"strings"
)
type readAutoCloser struct {
r io.ReadCloser
}
func (a readAutoCloser) Read(b []byte) (n int, err error) {
if a.r == nil {
return 0, io.EOF
}
n, err = a.r.Read(b)
if err == io.EOF {
a.Close()
}
return n, err
}
func (a readAutoCloser) Close() error {
if a.r == nil {
return nil
}
return a.r.(io.Closer).Close()
}
type pipe struct {
Reader readAutoCloser
}
func newReadAutoCloser(r io.Reader) readAutoCloser {
if _, ok := r.(io.Closer); !ok {
return readAutoCloser{ioutil.NopCloser(r)}
}
return readAutoCloser{r.(io.ReadCloser)}
}
func main() {
p := &pipe{}
p.Reader = newReadAutoCloser(strings.NewReader("test"))
b, err := ioutil.ReadAll(p.Reader)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
// Output:
// test

13
_test/len0.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f(a []int) interface{} {
return len(a)
}
func main() {
a := []int{1, 2}
println(f(a).(int))
}
// Output:
// 2

13
_test/make0.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f() interface{} {
return make([]int, 2)
}
func main() {
a := f()
println(len(a.([]int)))
}
// Output:
// 2

15
_test/make1.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
func f() interface{} {
return make(map[int]int)
}
func main() {
a, ok := f().(map[int]int)
fmt.Println(a, ok)
}
// Output:
// map[] true

18
_test/map24.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"encoding/json"
"fmt"
)
func main() {
jb := []byte(`{"property": "test"}`)
params := map[string]interface{}{"foo": 1}
if err := json.Unmarshal(jb, &params); err != nil {
panic("marshal failed.")
}
fmt.Println(params["foo"], params["property"])
}
// Output:
// 1 test

26
_test/map25.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"encoding/json"
"strconv"
)
func main() {
jb := []byte(`{"num": "2"}`)
params := map[string]interface{}{"foo": "1"}
if err := json.Unmarshal(jb, &params); err != nil {
panic(err)
}
sum := 0
for _, v := range params {
i, err := strconv.Atoi(v.(string))
if err != nil {
panic(err)
}
sum += i
}
println(sum)
}
// Output:
// 3

11
_test/map26.go Normal file
View File

@@ -0,0 +1,11 @@
package main
var m = map[string]int{"foo": 1, "bar": 2}
func main() {
var a interface{} = m["foo"]
println(a.(int))
}
// Output:
// 1

24
_test/map27.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"fmt"
"text/template"
)
type fm map[string]interface{}
type foo struct{}
func main() {
a := make(fm)
a["foo"] = &foo{}
fmt.Println(a["foo"])
b := make(template.FuncMap) // type FuncMap map[string]interface{}
b["foo"] = &foo{}
fmt.Println(b["foo"])
}
// Output:
// &{}
// &{}

13
_test/new2.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f() interface{} {
return new(int)
}
func main() {
a := f()
println(*(a.(*int)))
}
// Output:
// 0

12
_test/nil2.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func test() error { return nil }
func main() {
if err := test(); nil == err {
println("err is nil")
}
}
// Output:
// err is nil

16
_test/not0.go Normal file
View File

@@ -0,0 +1,16 @@
package main
func main() {
a := 0
b := true
c := false
if b && c {
a = 1
} else {
a = -1
}
println(a)
}
// Output:
// -1

15
_test/not1.go Normal file
View File

@@ -0,0 +1,15 @@
package main
func main() {
a := 0
b := true
if (!b) {
a = 1
} else {
a = -1
}
println(a)
}
// Output:
// -1

9
_test/not2.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var b interface{} = !(1 == 2)
println(b.(bool))
}
// Output:
// true

10
_test/num0.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "fmt"
func main() {
fmt.Printf("%g\n", 1.0)
}
// Output:
// 1

View File

@@ -1,9 +1,9 @@
package main
func main() {
i := 100
println(i % 1e2)
i := 102
println(i % -1e2)
}
// Output:
// 0
// 2

12
_test/op5.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
i := 100
j := i % 1e2
fmt.Printf("%T %v\n", j, j)
}
// Output:
// int 0

14
_test/real0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func f(c complex128) interface{} { return real(c) }
func main() {
c := complex(3, 2)
a := f(c)
fmt.Println(a.(float64))
}
// Output:
// 3

14
_test/select10.go Normal file
View File

@@ -0,0 +1,14 @@
package main
func main() {
c := make(chan string)
select {
case <-c:
println("unexpected")
default:
}
println("bye")
}
// Output:
// bye

16
_test/select11.go Normal file
View File

@@ -0,0 +1,16 @@
package main
func main() {
c := make(chan string)
select {
case <-c:
println("unexpected")
default:
println("nothing received")
}
println("bye")
}
// Output:
// nothing received
// bye

17
_test/select4.go Normal file
View File

@@ -0,0 +1,17 @@
package main
func main() {
c1 := make(chan string)
go func() { c1 <- "done" }()
select {
case msg1 := <-c1:
println("received from c1:", msg1)
}
println("Bye")
}
// Output:
// received from c1: done
// Bye

22
_test/select5.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type T struct {
c1 chan string
}
func main() {
t := &T{}
t.c1 = make(chan string)
go func(c chan string) { c <- "done" }(t.c1)
select {
case msg1 := <-t.c1:
println("received from c1:", msg1)
}
println("Bye")
}
// Output:
// received from c1: done
// Bye

22
_test/select6.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type T struct {
c1 chan string
}
func main() {
t := &T{}
t.c1 = make(chan string)
go func(c chan string) { c <- "done" }(t.c1)
select {
case <-t.c1:
println("received from c1")
}
println("Bye")
}
// Output:
// received from c1
// Bye

24
_test/select7.go Normal file
View File

@@ -0,0 +1,24 @@
package main
type T struct {
c1 chan string
}
func main() {
t := &T{}
t.c1 = make(chan string)
a := 0
go func() {
select {
case t.c1 <- "done":
a++
}
}()
msg1 := <-t.c1
println("received from c1:", msg1)
}
// Output:
// received from c1: done

24
_test/select8.go Normal file
View File

@@ -0,0 +1,24 @@
package main
type T struct {
c1 chan string
c2 chan string
}
func main() {
t := &T{}
t.c1 = make(chan string)
go func(c chan string) { c <- "done" }(t.c1)
select {
case msg := <-t.c1:
println("received from c1:", msg)
case <-t.c2:
}
println("Bye")
}
// Output:
// received from c1: done
// Bye

22
_test/select9.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type T struct {
c1 chan string
}
func main() {
t := &T{}
t.c1 = make(chan string)
go func() {
select {
case t.c1 <- "done":
}
}()
msg1 := <-t.c1
println("received from c1:", msg1)
}
// Output:
// received from c1: done

View File

@@ -15,3 +15,6 @@ func main() {
_, err := c.Get("url")
println(strings.Contains(err.Error(), "unsupported protocol scheme"))
}
// Output:
// true

24
_test/struct38.go Normal file
View File

@@ -0,0 +1,24 @@
package main
type T struct {
f func(t *T1)
y *xxx
}
type T1 struct {
T
}
type xxx struct{}
var (
x1 *T1 = x
x = &T1{}
)
func main() {
println("ok")
}
// Output:
// ok

22
_test/struct39.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type T struct {
t *T1
y *xxx
}
type T1 struct {
T
}
var x = &T1{}
var t = &T{}
type xxx struct{}
func main() {
println("ok")
}
// Output:
// ok

23
_test/struct40.go Normal file
View File

@@ -0,0 +1,23 @@
package main
type T struct {
t *T1
y *xxx
}
type T1 struct {
T
}
func f(t *T) { println("in f") }
var x = &T1{}
type xxx struct{}
func main() {
println("ok")
}
// Output:
// ok

26
_test/struct41.go Normal file
View File

@@ -0,0 +1,26 @@
package main
type Ti func(*T)
type T1 struct {
t Ti
}
type T struct {
t Ti
y *xxx
}
func f(t *T) { println("in f") }
type xxx struct{}
var x = &T1{t: f}
func main() {
x.t = f
println("ok")
}
// Output:
// ok

19
_test/struct42.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type T struct {
t func(*T)
y *xxx
}
func f(t *T) { println("in f") }
var x = &T{t: f}
type xxx struct{}
func main() {
println("ok")
}
// Output:
// ok

19
_test/struct43.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type T struct {
t func(*T)
y *xxx
}
func f(t *T) { println("in f") }
type xxx struct{}
func main() {
x := &T{}
x.t = f
println("ok")
}
// Output:
// ok

27
_test/struct44.go Normal file
View File

@@ -0,0 +1,27 @@
package main
type Ti func(*T) X
type T1 struct {
t Ti
}
type T struct {
t Ti
y *xxx
}
func f(t *T) X { println("in f"); return X{} }
type X struct{ Name string }
type xxx struct{}
var x = &T1{t: f}
func main() {
println("ok")
}
// Output:
// ok

18
_test/struct45.go Normal file
View File

@@ -0,0 +1,18 @@
package main
type T struct {
b bool
}
type T1 struct {
T
}
func main() {
t := &T1{}
t.b = true
println(t.b)
}
// Output:
// true

16
_test/switch27.go Normal file
View File

@@ -0,0 +1,16 @@
package main
func main() {
//a := false
switch false {
case true:
println("true")
case false:
println("false")
}
println("bye")
}
// Output:
// false
// bye

15
_test/switch28.go Normal file
View File

@@ -0,0 +1,15 @@
package main
func main() {
switch {
case true:
println("true")
case false:
println("false")
}
println("bye")
}
// Output:
// true
// bye

14
_test/switch29.go Normal file
View File

@@ -0,0 +1,14 @@
package main
func main() {
a := 3
switch a {
case 3:
println("three")
}
println("bye")
}
// Output:
// three
// bye

16
_test/switch30.go Normal file
View File

@@ -0,0 +1,16 @@
package main
func main() {
a := 3
switch a {
default:
//println("default")
case 3:
println("three")
}
println("bye")
}
// Output:
// three
// bye

10
_test/switch31.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
switch {
}
println("bye")
}
// Output:
// bye

11
_test/switch32.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
a := 1
switch a {
}
println("bye", a)
}
// Output:
// bye 1

11
_test/switch33.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
var a interface{}
switch a.(type) {
}
println("bye")
}
// Output:
// bye

13
_test/switch34.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
var a interface{}
switch a.(type) {
case []int:
case []string:
}
println("bye")
}
// Output:
// bye

15
_test/time12.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"time"
)
var twentyFourHours = time.Duration(24 * time.Hour)
func main() {
fmt.Println(twentyFourHours.Hours())
}
// Output:
// 24

18
_test/type20.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"io"
"strings"
)
func isCloser(r io.Reader) bool {
_, ok := r.(io.Closer)
return ok
}
func main() {
println(isCloser(strings.NewReader("test")))
}
// Output:
// false

16
_test/type21.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"reflect"
"time"
)
func main() {
t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC)
v := reflect.ValueOf(t.String)
f := v.Interface().(func() string)
println(f())
}
// Output:
// 2009-11-10 23:04:05 +0000 UTC

18
_test/type22.go Normal file
View File

@@ -0,0 +1,18 @@
package main
type T1 T
func foo() T1 {
return T1(T{"foo"})
}
type T struct {
Name string
}
func main() {
println(foo().Name)
}
// Output:
// foo

20
_test/variadic6.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import "fmt"
type A struct {
}
func (a A) f(vals ...bool) {
for _, v := range vals {
fmt.Println(v)
}
}
func main() {
bools := []bool{true}
a := A{}
a.f(bools...)
}
// Output:
// true

View File

@@ -1,22 +1,66 @@
/*
Yaegi interprets Go programs.
Yaegi reads Go language programs from its standard input or from a file
and evaluates them.
Yaegi reads Go language programs from standard input, string
parameters or files and run them.
If invoked with no arguments, it processes the standard input
in a Read-Eval-Print-Loop. A prompt is displayed if standard input
is a terminal.
If invoked with no arguments, it processes the standard input in
a Read-Eval-Print-Loop. A prompt is displayed if standard input is
a terminal.
Given a file, it operates on that file. If the first line starts with
"#!/usr/bin/env yaegi", and the file has exec permission, then the file
can be invoked directly from the shell.
File Mode
In file mode, as in standard Go, files are read entirely, then parsed,
then evaluated. In REPL mode, each line is parsed and evaluated separately,
at global level in an implicit main package.
In file mode, as in a standard Go compiler, source files are read entirely
before being parsed, then evaluated. It allows to handle forward
declarations and to have package code split in multiple source files.
Go specifications fully apply in this mode.
All files are interpreted in file mode except the initial file if it
starts with "#!" characters (the shebang pattern to allow executable
scripts), for example "#!/usr/bin/env yaegi". In that case, the initial
file is interpreted in REPL mode.
REPL mode
In REPL mode, the interpreter parses the code incrementally. As soon
as a statement is complete, it evaluates it. This makes the interpreter
suitable for interactive command line and scripts.
Go specifications apply with the following differences:
All local and global declarations (const, var, type, func) are allowed,
including in short form, except that all identifiers must be defined
before use (as declarations inside a standard Go function).
The statements are evaluated in the global space, within an implicit
"main" package.
It is not necessary to have a package statement, or a main function in
REPL mode. Import statements for preloaded binary packages can also
be avoided (i.e. all the standard library except the few packages
where default names collide, as "math/rand" and "crypto/rand", for which
an explicit import is still necessary).
Note that the source packages are always interpreted in file mode,
even if imported from REPL.
The following extract is a valid executable script:
#!/usr/bin/env yaegi
helloHandler := func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hello, world!\n")
}
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
Example of a one liner:
$ yaegi -e 'println(reflect.TypeOf(fmt.Print))'
Options:
-e string
evaluate the string and return.
-i
start an interactive REPL after file execution.
-tags tag,list
@@ -86,15 +130,18 @@ func main() {
s := string(b)
if s[:2] == "#!" {
// Allow executable go scripts, but fix them prior to parse
// Allow executable go scripts, Have the same behavior as in interactive mode.
s = strings.Replace(s, "#!", "//", 1)
}
i.Name = args[0]
if _, err := i.Eval(s); err != nil {
fmt.Println(err)
if p, ok := err.(interp.Panic); ok {
fmt.Println(string(p.Stack))
i.REPL(strings.NewReader(s), os.Stdout)
} else {
// Files not starting with "#!" are supposed to be pure Go, directly Evaled.
i.Name = args[0]
_, err := i.Eval(s)
if err != nil {
fmt.Println(err)
if p, ok := err.(interp.Panic); ok {
fmt.Println(string(p.Stack))
}
}
}

View File

@@ -84,7 +84,7 @@ func TestYaegiCmdCancel(t *testing.T) {
continue
}
if outBuf.String() != "context canceled\n2\n" {
if outBuf.String() != "context canceled\n" {
t.Errorf("unexpected output: %q", &outBuf)
}
}

View File

@@ -17,9 +17,9 @@ import "reflect"
// Arithmetic operators
{{range $name, $op := .Arithmetic}}
func {{$name}}(n *node) {
dest := genValue(n)
next := getExec(n.tnext)
typ := n.typ.TypeOf()
typ := n.typ.concrete().TypeOf()
dest := genValueOutput(n, typ)
c0, c1 := n.child[0], n.child[1]
switch typ.Kind() {
@@ -379,7 +379,7 @@ func {{$name}}Const(n *node) {
{{range $name, $op := .Comparison}}
func {{$name}}(n *node) {
tnext := getExec(n.tnext)
dest := genValue(n)
dest := genValueOutput(n, reflect.TypeOf(true))
c0, c1 := n.child[0], n.child[1]
switch t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf(); {

View File

@@ -6,7 +6,6 @@ import (
"go/parser"
"go/scanner"
"go/token"
"math"
"reflect"
"strconv"
"sync/atomic"
@@ -196,15 +195,18 @@ const (
aAndNot
aAndNotAssign
aBitNot
aBranch
aCall
aCase
aCompositeLit
aConvert
aDec
aEqual
aGreater
aGreaterEqual
aGetFunc
aGetIndex
aGetSym
aInc
aLand
aLor
@@ -253,14 +255,17 @@ var actions = [...]string{
aAndNot: "&^",
aAndNotAssign: "&^=",
aBitNot: "^",
aBranch: "branch",
aCall: "call",
aCase: "case",
aCompositeLit: "compositeLit",
aConvert: "convert",
aDec: "--",
aEqual: "==",
aGreater: ">",
aGetFunc: "getFunc",
aGetIndex: "getIndex",
aGetSym: ".",
aInc: "++",
aLand: "&&",
aLor: "||",
@@ -464,11 +469,7 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
n.rval = reflect.ValueOf(v)
case token.FLOAT:
v, _ := strconv.ParseFloat(a.Value, 64)
if math.Trunc(v) == v {
n.rval = reflect.ValueOf(int(v))
} else {
n.rval = reflect.ValueOf(v)
}
n.rval = reflect.ValueOf(v)
case token.IMAG:
v, _ := strconv.ParseFloat(a.Value[:len(a.Value)-1], 64)
n.rval = reflect.ValueOf(complex(0, v))

Some files were not shown because too many files have changed in this diff Show More