Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ae01a2af3 | ||
|
|
c06f83f34a | ||
|
|
a6d9c84a30 | ||
|
|
6346d11286 | ||
|
|
1edb6a1424 | ||
|
|
a2f56431ea | ||
|
|
42abedb25d | ||
|
|
151699ef9f | ||
|
|
f1f3ca7e06 | ||
|
|
9ddecfa121 | ||
|
|
04770a4b81 | ||
|
|
341c69d922 | ||
|
|
f4cc059e3e | ||
|
|
535e7e1c42 | ||
|
|
cb0f3a77bb | ||
|
|
b1279d0a21 | ||
|
|
f3f9ffaea7 | ||
|
|
e332a6b3be | ||
|
|
358a57b4b9 | ||
|
|
3640f2f820 | ||
|
|
3faa47c61e | ||
|
|
896bfeb5a1 | ||
|
|
1029d102e5 | ||
|
|
065d4fa4d7 | ||
|
|
332becf95d | ||
|
|
da9e6a0d6c | ||
|
|
913680d1ed | ||
|
|
a004809fc2 |
@@ -3,7 +3,7 @@ project_name: yaegi
|
||||
builds:
|
||||
- id: yaegi
|
||||
binary: yaegi
|
||||
main: ./cmd/yaegi/yaegi.go
|
||||
main: ./cmd/yaegi/
|
||||
|
||||
goos:
|
||||
- darwin
|
||||
@@ -28,7 +28,7 @@ builds:
|
||||
|
||||
- id: goexports
|
||||
binary: goexports
|
||||
main: ./cmd/goexports/goexports.go
|
||||
main: ./cmd/goexports/
|
||||
|
||||
goos:
|
||||
- darwin
|
||||
|
||||
@@ -27,7 +27,7 @@ env:
|
||||
global:
|
||||
- GO111MODULE=on
|
||||
|
||||
go_import_path: github.com/containous/yaegi
|
||||
go_import_path: github.com/traefik/yaegi
|
||||
|
||||
before_install:
|
||||
# Install linters and misspell
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Yaegi is an open source project, and your feedback and contributions
|
||||
are needed and always welcome.
|
||||
|
||||
[Issues] and [Pull Requests] are opened at https://github.com/containous/yaegi.
|
||||
[Issues] and [Pull Requests] are opened at https://github.com/traefik/yaegi.
|
||||
|
||||
Non trivial changes should be discussed with the project maintainers by
|
||||
opening a [Feature Request] clearly explaining rationale, background
|
||||
@@ -13,12 +13,12 @@ discussions.
|
||||
Once the proposal is approved, a Pull Request can be opened. If you want
|
||||
to provide early visibility to reviewers, create a [Draft Pull Request].
|
||||
|
||||
We will also require you to sign the [Containous Contributor License Agreement]
|
||||
We will also require you to sign the [Traefik Contributor License Agreement]
|
||||
after you submit your first pull request to this project. The link to sign the
|
||||
agreement will be presented to you in the web interface of the pull request.
|
||||
|
||||
[Issues]: https://github.com/containous/yaegi/issues
|
||||
[Pull Requests]: https://github.com/containous/yaegi/issues
|
||||
[Feature Request]: https://github.com/containous/yaegi/issues/new?template=feature_request.md
|
||||
[Issues]: https://github.com/traefik/yaegi/issues
|
||||
[Pull Requests]: https://github.com/traefik/yaegi/issues
|
||||
[Feature Request]: https://github.com/traefik/yaegi/issues/new?template=feature_request.md
|
||||
[Draft Pull Request]: https://github.blog/2019-02-14-introducing-draft-pull-requests/
|
||||
[Containous Contributor License Agreement]: https://cla-assistant.io/containous/yaegi
|
||||
[Traefik Labs Contributor License Agreement]: https://cla-assistant.io/traefik/yaegi
|
||||
|
||||
1
LICENSE
1
LICENSE
@@ -187,6 +187,7 @@
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2019 Containous SAS
|
||||
Copyright 2020 Traefik Labs SAS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
6
Makefile
6
Makefile
@@ -20,4 +20,8 @@ tests:
|
||||
GO111MODULE=off go test -v ./...
|
||||
GO111MODULE=off go test -race ./interp
|
||||
|
||||
.PHONY: check gen_all_syscall gen_tests
|
||||
# https://github.com/goreleaser/godownloader
|
||||
generate_downloader:
|
||||
godownloader --repo=traefik/yaegi -o install.sh
|
||||
|
||||
.PHONY: check gen_all_syscall gen_tests generate_downloader
|
||||
|
||||
40
README.md
40
README.md
@@ -2,9 +2,9 @@
|
||||
<img width="400" src="doc/images/yaegi.png" alt="Yaegi" title="Yaegi" />
|
||||
</p>
|
||||
|
||||
[](https://github.com/containous/yaegi/releases)
|
||||
[](https://travis-ci.com/containous/yaegi)
|
||||
[](https://godoc.org/github.com/containous/yaegi)
|
||||
[](https://github.com/traefik/yaegi/releases)
|
||||
[](https://travis-ci.com/traefik/yaegi)
|
||||
[](https://godoc.org/github.com/traefik/yaegi)
|
||||
[](https://community.containo.us/c/yaegi)
|
||||
|
||||
Yaegi is Another Elegant Go Interpreter.
|
||||
@@ -25,18 +25,24 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
|
||||
### Go package
|
||||
|
||||
```go
|
||||
import "github.com/containous/yaegi/interp"
|
||||
import "github.com/traefik/yaegi/interp"
|
||||
```
|
||||
|
||||
### Command-line executable
|
||||
|
||||
```bash
|
||||
go get -u github.com/containous/yaegi/cmd/yaegi
|
||||
go get -u github.com/traefik/yaegi/cmd/yaegi
|
||||
```
|
||||
|
||||
Note that you can use [rlwrap](https://github.com/hanslub42/rlwrap) (install with your favorite package manager),
|
||||
and alias the `yaegi` command in `alias yaegi='rlwrap yaegi'` in your `~/.bashrc`, to have history and command line edition.
|
||||
|
||||
### CI Integration
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/traefik/yaegi/master/install.sh | bash -s -- -b $GOPATH/bin v0.9.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### As an embedded interpreter
|
||||
@@ -47,8 +53,8 @@ Create an interpreter with `New()`, run Go code with `Eval()`:
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/containous/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -81,7 +87,7 @@ The following program is compiled ahead of time, except `bar()` which is interpr
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/interp"
|
||||
import "github.com/traefik/yaegi/interp"
|
||||
|
||||
const src = `package foo
|
||||
func Bar(s string) string { return s + "-Foo" }`
|
||||
@@ -155,11 +161,11 @@ Documentation about Yaegi commands and libraries can be found at usual [godoc.or
|
||||
|
||||
Beside the known [bugs] which are supposed to be fixed in the short term, there are some limitations not planned to be addressed soon:
|
||||
|
||||
- assembly files (`.s`) are not supported
|
||||
- calling C code is not supported (no virtual "C" package)
|
||||
- interfaces to be used from the pre-compiled code can not be added dynamically, as it is required to pre-compile interface wrappers
|
||||
- representation of types by `reflect` and printing values using %T may give different results between compiled mode and interpreted mode
|
||||
- interpreting computation intensive code is likely to remain significantly slower than in compiled mode
|
||||
- Assembly files (`.s`) are not supported.
|
||||
- Calling C code is not supported (no virtual "C" package).
|
||||
- Interfaces to be used from the pre-compiled code can not be added dynamically, as it is required to pre-compile interface wrappers.
|
||||
- Representation of types by `reflect` and printing values using %T may give different results between compiled mode and interpreted mode.
|
||||
- Interpreting computation intensive code is likely to remain significantly slower than in compiled mode.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -170,7 +176,7 @@ Beside the known [bugs] which are supposed to be fixed in the short term, there
|
||||
[Apache 2.0][License].
|
||||
|
||||
[specs]: https://golang.org/ref/spec
|
||||
[docs]: https://godoc.org/github.com/containous/yaegi
|
||||
[license]: https://github.com/containous/yaegi/blob/master/LICENSE
|
||||
[github]: https://github.com/containous/yaegi
|
||||
[bugs]: https://github.com/containous/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug
|
||||
[docs]: https://godoc.org/github.com/traefik/yaegi
|
||||
[license]: https://github.com/traefik/yaegi/blob/master/LICENSE
|
||||
[github]: https://github.com/traefik/yaegi
|
||||
[bugs]: https://github.com/traefik/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug
|
||||
|
||||
16
_test/a42.go
Normal file
16
_test/a42.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var b [8]byte
|
||||
binary.LittleEndian.PutUint64(b[:], uint64(1))
|
||||
|
||||
fmt.Println(b)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [1 0 0 0 0 0 0 0]
|
||||
@@ -1,6 +1,6 @@
|
||||
package foo
|
||||
|
||||
import bar "github.com/containous/yaegi/_test/b2/foo"
|
||||
import bar "github.com/traefik/yaegi/_test/b2/foo"
|
||||
|
||||
var Desc = "in b1/foo"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package c1
|
||||
|
||||
import "github.com/containous/yaegi/_test/c2"
|
||||
import "github.com/traefik/yaegi/_test/c2"
|
||||
|
||||
var C1 = c2.C2 + "x"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package c2
|
||||
|
||||
import "github.com/containous/yaegi/_test/c1"
|
||||
import "github.com/traefik/yaegi/_test/c1"
|
||||
|
||||
var C2 = c1.C1 + "Y"
|
||||
|
||||
51
_test/cli4.go
Normal file
51
_test/cli4.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
type mw1 struct {
|
||||
next http.Handler
|
||||
}
|
||||
|
||||
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
|
||||
m.next.ServeHTTP(rw, rq)
|
||||
}
|
||||
|
||||
type mw0 struct{}
|
||||
|
||||
func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "Welcome to my website!")
|
||||
}
|
||||
|
||||
func main() {
|
||||
m0 := &mw0{}
|
||||
m1 := &mw1{m0}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", m1.ServeHTTP)
|
||||
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client(server.URL)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Welcome to my website!
|
||||
51
_test/cli5.go
Normal file
51
_test/cli5.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
type mw1 struct {
|
||||
next http.Handler
|
||||
}
|
||||
|
||||
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
|
||||
m.next.ServeHTTP(rw, rq)
|
||||
}
|
||||
|
||||
type mw0 struct{}
|
||||
|
||||
func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "Welcome to my website!")
|
||||
}
|
||||
|
||||
func main() {
|
||||
m0 := &mw0{}
|
||||
m1 := &mw1{next: m0}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", m1.ServeHTTP)
|
||||
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client(server.URL)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Welcome to my website!
|
||||
52
_test/cli6.go
Normal file
52
_test/cli6.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
type T struct {
|
||||
http.ResponseWriter
|
||||
}
|
||||
|
||||
type mw1 struct {
|
||||
next http.Handler
|
||||
}
|
||||
|
||||
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
|
||||
t := &T{
|
||||
ResponseWriter: rw,
|
||||
}
|
||||
x := t.Header()
|
||||
fmt.Fprint(rw, "Welcome to my website!", x)
|
||||
}
|
||||
|
||||
func main() {
|
||||
m1 := &mw1{}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", m1.ServeHTTP)
|
||||
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client(server.URL)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Welcome to my website!map[]
|
||||
19
_test/composite12.go
Normal file
19
_test/composite12.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
type A struct {
|
||||
C D
|
||||
}
|
||||
|
||||
type D struct {
|
||||
E string
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := A{}
|
||||
a.C = D{"bb"}
|
||||
|
||||
println(a.C.E)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// bb
|
||||
19
_test/composite13.go
Normal file
19
_test/composite13.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
type A struct {
|
||||
C D
|
||||
}
|
||||
|
||||
type D struct {
|
||||
E string
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := A{}
|
||||
a.C = D{E: "bb"}
|
||||
|
||||
println(a.C.E)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// bb
|
||||
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containous/yaegi/_test/ct1"
|
||||
"github.com/traefik/yaegi/_test/ct1"
|
||||
)
|
||||
|
||||
type T struct {
|
||||
|
||||
16
_test/composite8bis.go
Normal file
16
_test/composite8bis.go
Normal 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{I: e}
|
||||
t = append(t, x)
|
||||
}
|
||||
println(t[0].I, t[1].I)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 1 2
|
||||
@@ -2,13 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.Lshortfile)
|
||||
i := interp.New(interp.Options{})
|
||||
i := interp.New(interp.Options{Stdout: os.Stdout})
|
||||
if _, err := i.Eval(`func f() (int, int) { return 1, 2 }`); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package foo
|
||||
|
||||
import "github.com/containous/yaegi/_test/foo/boo"
|
||||
import "github.com/traefik/yaegi/_test/foo/boo"
|
||||
|
||||
var Bar = "BARR"
|
||||
var Boo = boo.Boo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package foo
|
||||
|
||||
import "github.com/containous/yaegi/_test/foo/boo"
|
||||
import "github.com/traefik/yaegi/_test/foo/boo"
|
||||
|
||||
var Bir = boo.Boo + "22"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/foo"
|
||||
import "github.com/traefik/yaegi/_test/foo"
|
||||
|
||||
func main() { println(foo.Bar, foo.Boo) }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/p1"
|
||||
import "github.com/traefik/yaegi/_test/p1"
|
||||
|
||||
func main() { println("num:", p1.Uint32()) }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import boo "github.com/containous/yaegi/_test/foo"
|
||||
import boo "github.com/traefik/yaegi/_test/foo"
|
||||
|
||||
func main() { println(boo.Bar, boo.Boo, boo.Bir) }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/c1"
|
||||
import "github.com/traefik/yaegi/_test/c1"
|
||||
|
||||
func main() {
|
||||
println(c1.C1)
|
||||
@@ -8,4 +8,4 @@ func main() {
|
||||
|
||||
// Error:
|
||||
// import cycle not allowed
|
||||
// imports github.com/containous/yaegi/_test/c1
|
||||
// imports github.com/traefik/yaegi/_test/c1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/foo-bar"
|
||||
import bar "github.com/traefik/yaegi/_test/foo-bar"
|
||||
|
||||
func main() {
|
||||
println(bar.Name)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/b1/foo"
|
||||
import "github.com/traefik/yaegi/_test/b1/foo"
|
||||
|
||||
func main() {
|
||||
println(foo.Desc)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/baz-bat"
|
||||
import "github.com/traefik/yaegi/_test/baz-bat"
|
||||
|
||||
func main() {
|
||||
println(baz.Name)
|
||||
|
||||
@@ -3,14 +3,14 @@ package main
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.Lshortfile)
|
||||
i := interp.New(interp.Options{})
|
||||
i.Use(interp.Symbols)
|
||||
if _, err := i.Eval(`import "github.com/containous/yaegi/interp"`); err != nil {
|
||||
if _, err := i.Eval(`import "github.com/traefik/yaegi/interp"`); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := i.Eval(`i := interp.New(interp.Options{})`); err != nil {
|
||||
@@ -20,6 +20,3 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
i := interp.New(interp.Opt{})
|
||||
i.Use(interp.ExportValue, interp.ExportType)
|
||||
i.Eval(`import "github.com/containous/yaegi/interp"`)
|
||||
i.Eval(`import "github.com/traefik/yaegi/interp"`)
|
||||
i.Eval(`i := interp.New(interp.Opt{})`)
|
||||
i.Eval(`i.Eval("println(42)")`)
|
||||
}
|
||||
|
||||
16
_test/ipp_as_key.go
Normal file
16
_test/ipp_as_key.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"guthib.com/toto" // pkg name is actually titi
|
||||
"guthib.com/tata" // pkg name is actually tutu
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello", titi.Quux())
|
||||
println("Hello", tutu.Quux())
|
||||
}
|
||||
|
||||
// GOPATH:testdata/redeclaration-global7
|
||||
// Output:
|
||||
// Hello bar
|
||||
// Hello baz
|
||||
14
_test/m1/main.go
Normal file
14
_test/m1/main.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("vim-go")
|
||||
}
|
||||
|
||||
func TestWeird(t *testing.T) {
|
||||
fmt.Println("in TestWeird")
|
||||
}
|
||||
17
_test/m1/main_test.go
Normal file
17
_test/m1/main_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
fmt.Println("in test")
|
||||
}
|
||||
|
||||
func BenchmarkMain(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
rand.Int()
|
||||
}
|
||||
}
|
||||
7
_test/m2/m2_test.go
Normal file
7
_test/m2/m2_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package m2
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestM2(t *testing.T) {
|
||||
t.Errorf("got %s, want %s", "AAA", "BBB")
|
||||
}
|
||||
14
_test/method35.go
Normal file
14
_test/method35.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "strconv"
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
_, err = strconv.Atoi("erwer")
|
||||
if _, ok := err.(*strconv.NumError); ok {
|
||||
println("here")
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// here
|
||||
16
_test/pkgname0.go
Normal file
16
_test/pkgname0.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"guthib.com/bar" // pkg name is actually quux
|
||||
baz "guthib.com/baz" // pkg name is also quux, force it to baz.
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello", quux.Quux())
|
||||
println("Hello", baz.Quux())
|
||||
}
|
||||
|
||||
// GOPATH:testdata/redeclaration-global7
|
||||
// Output:
|
||||
// Hello bar
|
||||
// Hello baz
|
||||
13
_test/pkgname1.go
Normal file
13
_test/pkgname1.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"guthib.com/bar" // pkg name is actually quux
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello", bar.Quux()) // bar should not be a known symbol.
|
||||
}
|
||||
|
||||
// GOPATH:testdata/redeclaration-global7
|
||||
// Error:
|
||||
// ../_test/pkgname1.go:8:19: undefined: bar
|
||||
13
_test/pkgname2.go
Normal file
13
_test/pkgname2.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"guthib.com/toto" // pkg name is actually titi
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello", titi.Quux())
|
||||
}
|
||||
|
||||
// GOPATH:testdata/redeclaration-global7
|
||||
// Output:
|
||||
// Hello bar
|
||||
@@ -12,4 +12,5 @@ func main() {
|
||||
}
|
||||
|
||||
// Error:
|
||||
// ../_test/redeclaration-global5.go:5:1: time redeclared in this block
|
||||
// ../_test/redeclaration-global5.go:5:6: time redeclared in this block
|
||||
// previous declaration at ../_test/redeclaration-global5.go:3:5
|
||||
|
||||
14
_test/redeclaration-global7.go
Normal file
14
_test/redeclaration-global7.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"guthib.com/bar" // pkg name is actually quux
|
||||
"guthib.com/baz" // pkg name is also quux
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello", quux.Quux())
|
||||
}
|
||||
|
||||
// GOPATH:testdata/redeclaration-global7
|
||||
// Error:
|
||||
// ../_test/redeclaration-global7.go:5:2: quux/redeclaration-global7.go redeclared as imported package name
|
||||
22
_test/struct55.go
Normal file
22
_test/struct55.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
m []*log.Logger
|
||||
}
|
||||
|
||||
func (l *Logger) Infof(format string, args ...interface{}) {
|
||||
l.m[0].Printf(format, args...)
|
||||
}
|
||||
|
||||
func main() {
|
||||
l := &Logger{m: []*log.Logger{log.New(os.Stdout, "", log.Lmsgprefix)}}
|
||||
l.Infof("test %s", "test")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// test test
|
||||
23
_test/struct56.go
Normal file
23
_test/struct56.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type A struct {
|
||||
IA InnerA
|
||||
}
|
||||
|
||||
type InnerA struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &A{}
|
||||
b, _ := json.Marshal(a)
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// {"IA":{"Timestamp":0}}
|
||||
23
_test/struct57.go
Normal file
23
_test/struct57.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type A struct {
|
||||
InnerA
|
||||
}
|
||||
|
||||
type InnerA struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &A{}
|
||||
b, _ := json.Marshal(a)
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// {"Timestamp":0}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package main
|
||||
|
||||
import _ "github.com/containous/yaegi/_test/ct"
|
||||
import _ "github.com/traefik/yaegi/_test/ct"
|
||||
|
||||
func main() {
|
||||
println("bye")
|
||||
|
||||
5
_test/testdata/redeclaration-global7/src/guthib.com/bar/quux.go
vendored
Normal file
5
_test/testdata/redeclaration-global7/src/guthib.com/bar/quux.go
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
package quux
|
||||
|
||||
func Quux() string {
|
||||
return "bar"
|
||||
}
|
||||
5
_test/testdata/redeclaration-global7/src/guthib.com/baz/quux.go
vendored
Normal file
5
_test/testdata/redeclaration-global7/src/guthib.com/baz/quux.go
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
package quux
|
||||
|
||||
func Quux() string {
|
||||
return "baz"
|
||||
}
|
||||
7
_test/testdata/redeclaration-global7/src/guthib.com/tata/tutu.go
vendored
Normal file
7
_test/testdata/redeclaration-global7/src/guthib.com/tata/tutu.go
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package tutu
|
||||
|
||||
import "guthib.com/baz"
|
||||
|
||||
func Quux() string {
|
||||
return quux.Quux()
|
||||
}
|
||||
7
_test/testdata/redeclaration-global7/src/guthib.com/toto/titi.go
vendored
Normal file
7
_test/testdata/redeclaration-global7/src/guthib.com/toto/titi.go
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package titi
|
||||
|
||||
import "guthib.com/bar"
|
||||
|
||||
func Quux() string {
|
||||
return quux.Quux()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/yaegi/_test/vars"
|
||||
import "github.com/traefik/yaegi/_test/vars"
|
||||
|
||||
func main() {
|
||||
println(vars.A)
|
||||
|
||||
16
_test/variadic10.go
Normal file
16
_test/variadic10.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := log.New(os.Stdout, "test ", log.Lmsgprefix)
|
||||
logger.Printf("args: %v %v", 1, "truc")
|
||||
logger.Printf("args: %v %v %v", 1, "truc", 2)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// test args: 1 truc
|
||||
// test args: 1 truc 2
|
||||
@@ -11,7 +11,7 @@ Usage:
|
||||
|
||||
Example:
|
||||
|
||||
goexports github.com/containous/yaegi/interp
|
||||
goexports github.com/traefik/yaegi/interp
|
||||
|
||||
The same goexport program is used for all target operating systems and architectures.
|
||||
The GOOS and GOARCH environment variables set the desired target.
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/yaegi/extract"
|
||||
"github.com/traefik/yaegi/extract"
|
||||
)
|
||||
|
||||
// genLicense generates the correct LICENSE header text from the provided
|
||||
@@ -108,9 +108,9 @@ func main() {
|
||||
|
||||
var oFile string
|
||||
if pkgIdent == "syscall" {
|
||||
oFile = strings.Replace(importPath, "/", "_", -1) + "_" + goos + "_" + goarch + ".go"
|
||||
oFile = strings.ReplaceAll(importPath, "/", "_") + "_" + goos + "_" + goarch + ".go"
|
||||
} else {
|
||||
oFile = strings.Replace(importPath, "/", "_", -1) + ".go"
|
||||
oFile = strings.ReplaceAll(importPath, "/", "_") + ".go"
|
||||
}
|
||||
|
||||
prefix := runtime.Version()
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/yaegi/extract"
|
||||
"github.com/traefik/yaegi/extract"
|
||||
)
|
||||
|
||||
func extractCmd(arg []string) error {
|
||||
@@ -58,7 +58,7 @@ func extractCmd(arg []string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
oFile := strings.Replace(importPath, "/", "_", -1) + ".go"
|
||||
oFile := strings.ReplaceAll(importPath, "/", "_") + ".go"
|
||||
f, err := os.Create(oFile)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -36,7 +36,7 @@ func help(arg []string) error {
|
||||
case Run:
|
||||
return run([]string{"-h"})
|
||||
case Test:
|
||||
return fmt.Errorf("help: test not implemented")
|
||||
return test([]string{"-h"})
|
||||
default:
|
||||
return fmt.Errorf("help: invalid yaegi command: %v", cmd)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/containous/yaegi/stdlib"
|
||||
"github.com/containous/yaegi/stdlib/syscall"
|
||||
"github.com/containous/yaegi/stdlib/unrestricted"
|
||||
"github.com/containous/yaegi/stdlib/unsafe"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/stdlib/syscall"
|
||||
"github.com/traefik/yaegi/stdlib/unrestricted"
|
||||
"github.com/traefik/yaegi/stdlib/unsafe"
|
||||
)
|
||||
|
||||
func run(arg []string) error {
|
||||
@@ -56,14 +56,16 @@ func run(arg []string) error {
|
||||
}
|
||||
|
||||
if cmd != "" {
|
||||
i.REPL(strings.NewReader(cmd), os.Stderr)
|
||||
_, err = i.Eval(cmd)
|
||||
showError(err)
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
if interactive || cmd == "" {
|
||||
i.REPL(os.Stdin, os.Stdout)
|
||||
_, err = i.REPL()
|
||||
showError(err)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip first os arg to set command line as expected by interpreted main
|
||||
@@ -71,40 +73,27 @@ func run(arg []string) error {
|
||||
os.Args = arg[1:]
|
||||
flag.CommandLine = flag.NewFlagSet(path, flag.ExitOnError)
|
||||
|
||||
if isPackageName(path) {
|
||||
err = runPackage(i, path)
|
||||
if isFile(path) {
|
||||
err = runFile(i, path)
|
||||
} else {
|
||||
if isDir(path) {
|
||||
err = runDir(i, path)
|
||||
} else {
|
||||
err = runFile(i, path)
|
||||
}
|
||||
_, err = i.EvalPath(path)
|
||||
}
|
||||
showError(err)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if interactive {
|
||||
i.REPL(os.Stdin, os.Stdout)
|
||||
_, err = i.REPL()
|
||||
showError(err)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func isPackageName(path string) bool {
|
||||
return !strings.HasPrefix(path, "/") && !strings.HasPrefix(path, "./") && !strings.HasPrefix(path, "../")
|
||||
}
|
||||
|
||||
func isDir(path string) bool {
|
||||
fi, err := os.Lstat(path)
|
||||
return err == nil && fi.IsDir()
|
||||
}
|
||||
|
||||
func runPackage(i *interp.Interpreter, path string) error {
|
||||
return fmt.Errorf("runPackage not implemented")
|
||||
}
|
||||
|
||||
func runDir(i *interp.Interpreter, path string) error {
|
||||
return fmt.Errorf("runDir not implemented")
|
||||
func isFile(path string) bool {
|
||||
fi, err := os.Stat(path)
|
||||
return err == nil && fi.Mode().IsRegular()
|
||||
}
|
||||
|
||||
func runFile(i *interp.Interpreter, path string) error {
|
||||
@@ -116,17 +105,21 @@ func runFile(i *interp.Interpreter, path string) error {
|
||||
if s := string(b); strings.HasPrefix(s, "#!") {
|
||||
// Allow executable go scripts, Have the same behavior as in interactive mode.
|
||||
s = strings.Replace(s, "#!", "//", 1)
|
||||
i.REPL(strings.NewReader(s), os.Stdout)
|
||||
} else {
|
||||
// Files not starting with "#!" are supposed to be pure Go, directly Evaled.
|
||||
i.Name = path
|
||||
_, err := i.Eval(s)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
if p, ok := err.(interp.Panic); ok {
|
||||
fmt.Println(string(p.Stack))
|
||||
}
|
||||
}
|
||||
_, err = i.Eval(s)
|
||||
return err
|
||||
}
|
||||
|
||||
// Files not starting with "#!" are supposed to be pure Go, directly Evaled.
|
||||
_, err = i.EvalPath(path)
|
||||
return err
|
||||
}
|
||||
|
||||
func showError(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
if p, ok := err.(interp.Panic); ok {
|
||||
fmt.Fprintln(os.Stderr, string(p.Stack))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
131
cmd/yaegi/test.go
Normal file
131
cmd/yaegi/test.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/stdlib/syscall"
|
||||
"github.com/traefik/yaegi/stdlib/unrestricted"
|
||||
"github.com/traefik/yaegi/stdlib/unsafe"
|
||||
)
|
||||
|
||||
func test(arg []string) (err error) {
|
||||
var (
|
||||
bench string
|
||||
benchmem bool
|
||||
benchtime string
|
||||
count string
|
||||
cpu string
|
||||
failfast bool
|
||||
run string
|
||||
short bool
|
||||
tags string
|
||||
useUnrestricted bool
|
||||
useUnsafe bool
|
||||
useSyscall bool
|
||||
timeout string
|
||||
verbose bool
|
||||
)
|
||||
|
||||
tflag := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
tflag.StringVar(&bench, "bench", "", "Run only those benchmarks matching a regular expression.")
|
||||
tflag.BoolVar(&benchmem, "benchmem", false, "Print memory allocation statistics for benchmarks.")
|
||||
tflag.StringVar(&benchtime, "benchtime", "", "Run enough iterations of each benchmark to take t.")
|
||||
tflag.StringVar(&count, "count", "", "Run each test and benchmark n times (default 1).")
|
||||
tflag.StringVar(&cpu, "cpu", "", "Specify a list of GOMAXPROCS values for which the tests or benchmarks should be executed.")
|
||||
tflag.BoolVar(&failfast, "failfast", false, "Do not start new tests after the first test failure.")
|
||||
tflag.StringVar(&run, "run", "", "Run only those tests matching a regular expression.")
|
||||
tflag.BoolVar(&short, "short", false, "Tell long-running tests to shorten their run time.")
|
||||
tflag.StringVar(&tags, "tags", "", "Set a list of build tags.")
|
||||
tflag.StringVar(&timeout, "timeout", "", "If a test binary runs longer than duration d, panic.")
|
||||
tflag.BoolVar(&useUnrestricted, "unrestricted", false, "Include unrestricted symbols.")
|
||||
tflag.BoolVar(&useUnsafe, "unsafe", false, "Include usafe symbols.")
|
||||
tflag.BoolVar(&useSyscall, "syscall", false, "Include syscall symbols.")
|
||||
tflag.BoolVar(&verbose, "v", false, "Verbose output: log all tests as they are run.")
|
||||
tflag.Usage = func() {
|
||||
fmt.Println("Usage: yaegi test [options] [path]")
|
||||
fmt.Println("Options:")
|
||||
tflag.PrintDefaults()
|
||||
}
|
||||
if err = tflag.Parse(arg); err != nil {
|
||||
return err
|
||||
}
|
||||
args := tflag.Args()
|
||||
path := "."
|
||||
if len(args) > 0 {
|
||||
path = args[0]
|
||||
}
|
||||
|
||||
// Overwrite os.Args with correct flags to setup testing.Init.
|
||||
tf := []string{""}
|
||||
if bench != "" {
|
||||
tf = append(tf, "-test.bench", bench)
|
||||
}
|
||||
if benchmem {
|
||||
tf = append(tf, "-test.benchmem")
|
||||
}
|
||||
if benchtime != "" {
|
||||
tf = append(tf, "-test.benchtime", benchtime)
|
||||
}
|
||||
if count != "" {
|
||||
tf = append(tf, "-test.count", count)
|
||||
}
|
||||
if cpu != "" {
|
||||
tf = append(tf, "-test.cpu", cpu)
|
||||
}
|
||||
if failfast {
|
||||
tf = append(tf, "-test.failfast")
|
||||
}
|
||||
if run != "" {
|
||||
tf = append(tf, "-test.run", run)
|
||||
}
|
||||
if short {
|
||||
tf = append(tf, "-test.short")
|
||||
}
|
||||
if timeout != "" {
|
||||
tf = append(tf, "-test.timeout", timeout)
|
||||
}
|
||||
if verbose {
|
||||
tf = append(tf, "-test.v")
|
||||
}
|
||||
testing.Init()
|
||||
os.Args = tf
|
||||
flag.Parse()
|
||||
|
||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, BuildTags: strings.Split(tags, ",")})
|
||||
i.Use(stdlib.Symbols)
|
||||
i.Use(interp.Symbols)
|
||||
if useSyscall {
|
||||
i.Use(syscall.Symbols)
|
||||
}
|
||||
if useUnrestricted {
|
||||
i.Use(unrestricted.Symbols)
|
||||
}
|
||||
if useUnsafe {
|
||||
i.Use(unsafe.Symbols)
|
||||
}
|
||||
if err = i.EvalTest(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
benchmarks := []testing.InternalBenchmark{}
|
||||
tests := []testing.InternalTest{}
|
||||
for name, sym := range i.Symbols(path) {
|
||||
switch fun := sym.Interface().(type) {
|
||||
case func(*testing.B):
|
||||
benchmarks = append(benchmarks, testing.InternalBenchmark{name, fun})
|
||||
case func(*testing.T):
|
||||
tests = append(tests, testing.InternalTest{name, fun})
|
||||
}
|
||||
}
|
||||
|
||||
testing.Main(regexp.MatchString, tests, benchmarks, nil)
|
||||
return nil
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func main() {
|
||||
case Run:
|
||||
err = run(os.Args[2:])
|
||||
case Test:
|
||||
err = fmt.Errorf("test not implemented")
|
||||
err = test(os.Args[2:])
|
||||
default:
|
||||
// If no command is given, fallback to default "run" command.
|
||||
// This allows scripts starting with "#!/usr/bin/env yaegi",
|
||||
|
||||
@@ -2,11 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -108,8 +110,8 @@ func TestYaegiCmdCancel(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
if outBuf.String() != "context canceled\n" {
|
||||
t.Errorf("unexpected output: %q", &outBuf)
|
||||
if strings.TrimSuffix(errBuf.String(), "\n") != context.Canceled.Error() {
|
||||
t.Errorf("unexpected error: %q", &errBuf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package clos1
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/containous/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
)
|
||||
|
||||
func TestFunctionCall(t *testing.T) {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/containous/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
)
|
||||
|
||||
func TestGetFunc(t *testing.T) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,9 +3,9 @@ package fromage
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
"guthib.com/traefik/cheese"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("Fromage %s", cheese.Hello())
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,10 +3,10 @@ package fromage
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
"guthib.com/containous/fromage/couteau"
|
||||
"guthib.com/traefik/cheese"
|
||||
"guthib.com/traefik/fromage/couteau"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("Fromage %s %s", couteau.Hello(), cheese.Hello())
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package cheese
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese/vin"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("Cheese %s", vin.Hello())
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package fromage
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
"guthib.com/containous/fromage/couteau"
|
||||
"guthib.com/traefik/cheese"
|
||||
"guthib.com/traefik/fromage/couteau"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
@@ -3,7 +3,7 @@ package cheese
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese/vin"
|
||||
"guthib.com/traefik/cheese/vin"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,7 +3,7 @@ package cheese
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese/vin"
|
||||
"guthib.com/traefik/cheese/vin"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
@@ -3,8 +3,8 @@ package fromage
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
"guthib.com/containous/fromage/couteau"
|
||||
"guthib.com/traefik/cheese"
|
||||
"guthib.com/traefik/fromage/couteau"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,8 +3,8 @@ package fromage
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
"guthib.com/containous/fromage/couteau"
|
||||
"guthib.com/traefik/cheese"
|
||||
"guthib.com/traefik/fromage/couteau"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
11
example/pkg/_pkg6/src/guthib.com/traefik/cheese/cheese.go
Normal file
11
example/pkg/_pkg6/src/guthib.com/traefik/cheese/cheese.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package cheese
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/traefik/cheese/vin"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("Cheese %s", vin.Hello())
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/vin"
|
||||
"guthib.com/traefik/vin"
|
||||
)
|
||||
|
||||
func Here() string {
|
||||
|
||||
@@ -3,9 +3,9 @@ package cheese
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/fromage"
|
||||
"guthib.com/traefik/fromage"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("cheese %s", fromage.Hello())
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package vin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"guthib.com/containous/cheese"
|
||||
|
||||
"guthib.com/traefik/cheese"
|
||||
)
|
||||
|
||||
func Hello() string {
|
||||
return fmt.Sprintf("vin %s", cheese.Hello())
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,12 @@ package pkg
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/yaegi/interp"
|
||||
"github.com/containous/yaegi/stdlib"
|
||||
"github.com/traefik/yaegi/interp"
|
||||
"github.com/traefik/yaegi/stdlib"
|
||||
)
|
||||
|
||||
func TestPackages(t *testing.T) {
|
||||
@@ -105,46 +103,16 @@ func TestPackages(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Init go interpreter
|
||||
i := interp.New(interp.Options{GoPath: goPath})
|
||||
var stdout, stderr bytes.Buffer
|
||||
i := interp.New(interp.Options{GoPath: goPath, Stdout: &stdout, Stderr: &stderr})
|
||||
i.Use(stdlib.Symbols) // Use binary standard library
|
||||
|
||||
var msg string
|
||||
if test.evalFile != "" {
|
||||
// setting i.Name as this is how it's actually done in cmd/yaegi
|
||||
i.Name = test.evalFile
|
||||
data, err := ioutil.ReadFile(test.evalFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// TODO(mpl): this is brittle if we do concurrent tests and stuff, do better later.
|
||||
stdout := os.Stdout
|
||||
defer func() { os.Stdout = stdout }()
|
||||
pr, pw, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
os.Stdout = pw
|
||||
|
||||
if _, err := i.Eval(string(data)); err != nil {
|
||||
if _, err := i.EvalPath(test.evalFile); err != nil {
|
||||
fatalStderrf(t, "%v", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
errC := make(chan error)
|
||||
go func() {
|
||||
_, err := io.Copy(&buf, pr)
|
||||
errC <- err
|
||||
}()
|
||||
|
||||
if err := pw.Close(); err != nil {
|
||||
fatalStderrf(t, "%v", err)
|
||||
}
|
||||
if err := <-errC; err != nil {
|
||||
fatalStderrf(t, "%v", err)
|
||||
}
|
||||
msg = buf.String()
|
||||
msg = stdout.String()
|
||||
} else {
|
||||
// Load pkg from sources
|
||||
topImport := "github.com/foo/pkg"
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const model = `// Code generated by 'github.com/containous/yaegi/extract {{.PkgName}}'. DO NOT EDIT.
|
||||
const model = `// Code generated by 'github.com/traefik/yaegi/extract {{.PkgName}}'. DO NOT EDIT.
|
||||
|
||||
{{.License}}
|
||||
|
||||
@@ -216,6 +216,19 @@ func genContent(dest, importPath, license string, p *types.Package, skip map[str
|
||||
buildTags += ",!windows,!nacl,!plan9"
|
||||
}
|
||||
|
||||
if importPath == "syscall" {
|
||||
// As per https://golang.org/cmd/go/#hdr-Build_constraints,
|
||||
// using GOOS=android also matches tags and files for GOOS=linux,
|
||||
// so exclude it explicitly to avoid collisions (issue #843).
|
||||
// Also using GOOS=illumos matches tags and files for GOOS=solaris.
|
||||
switch os.Getenv("GOOS") {
|
||||
case "android":
|
||||
buildTags += ",!linux"
|
||||
case "illumos":
|
||||
buildTags += ",!solaris"
|
||||
}
|
||||
}
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
data := map[string]interface{}{
|
||||
"Dest": dest,
|
||||
@@ -247,6 +260,9 @@ func fixConst(name string, val constant.Value, imports map[string]bool) string {
|
||||
str string
|
||||
)
|
||||
switch val.Kind() {
|
||||
case constant.String:
|
||||
tok = "STRING"
|
||||
str = val.ExactString()
|
||||
case constant.Int:
|
||||
tok = "INT"
|
||||
str = val.ExactString()
|
||||
@@ -269,7 +285,7 @@ func fixConst(name string, val constant.Value, imports map[string]bool) string {
|
||||
imports["go/constant"] = true
|
||||
imports["go/token"] = true
|
||||
|
||||
return fmt.Sprintf("constant.MakeFromLiteral(\"%s\", token.%s, 0)", str, tok)
|
||||
return fmt.Sprintf("constant.MakeFromLiteral(%q, token.%s, 0)", str, tok)
|
||||
}
|
||||
|
||||
// importPath checks whether pkgIdent is an existing directory relative to
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var expectedOutput = `// Code generated by 'github.com/containous/yaegi/extract guthib.com/baz'. DO NOT EDIT.
|
||||
var expectedOutput = `// Code generated by 'github.com/traefik/yaegi/extract guthib.com/baz'. DO NOT EDIT.
|
||||
|
||||
// +build BUILD_TAGS
|
||||
|
||||
|
||||
10
generate.go
10
generate.go
@@ -1,7 +1,7 @@
|
||||
package yaegi
|
||||
|
||||
//go:generate go generate github.com/containous/yaegi/interp
|
||||
//go:generate go generate github.com/containous/yaegi/cmd/goexports
|
||||
//go:generate go generate github.com/containous/yaegi/stdlib
|
||||
//go:generate go generate github.com/containous/yaegi/stdlib/syscall
|
||||
//go:generate go generate github.com/containous/yaegi/stdlib/unsafe
|
||||
//go:generate go generate github.com/traefik/yaegi/interp
|
||||
//go:generate go generate github.com/traefik/yaegi/cmd/goexports
|
||||
//go:generate go generate github.com/traefik/yaegi/stdlib
|
||||
//go:generate go generate github.com/traefik/yaegi/stdlib/syscall
|
||||
//go:generate go generate github.com/traefik/yaegi/stdlib/unsafe
|
||||
|
||||
2
go.mod
2
go.mod
@@ -1,3 +1,3 @@
|
||||
module github.com/containous/yaegi
|
||||
module github.com/traefik/yaegi
|
||||
|
||||
go 1.12
|
||||
|
||||
401
install.sh
Normal file
401
install.sh
Normal file
@@ -0,0 +1,401 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
# Code generated by godownloader on 2020-09-19T15:21:58Z. DO NOT EDIT.
|
||||
#
|
||||
|
||||
usage() {
|
||||
this=$1
|
||||
cat <<EOF
|
||||
$this: download go binaries for traefik/yaegi
|
||||
|
||||
Usage: $this [-b] bindir [-d] [tag]
|
||||
-b sets bindir or installation directory, Defaults to ./bin
|
||||
-d turns on debug logging
|
||||
[tag] is a tag from
|
||||
https://github.com/traefik/yaegi/releases
|
||||
If tag is missing, then the latest will be used.
|
||||
|
||||
Generated by godownloader
|
||||
https://github.com/goreleaser/godownloader
|
||||
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
#BINDIR is ./bin unless set be ENV
|
||||
# over-ridden by flag below
|
||||
|
||||
BINDIR=${BINDIR:-./bin}
|
||||
while getopts "b:dh?x" arg; do
|
||||
case "$arg" in
|
||||
b) BINDIR="$OPTARG" ;;
|
||||
d) log_set_priority 10 ;;
|
||||
h | \?) usage "$0" ;;
|
||||
x) set -x ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
TAG=$1
|
||||
}
|
||||
# this function wraps all the destructive operations
|
||||
# if a curl|bash cuts off the end of the script due to
|
||||
# network, either nothing will happen or will syntax error
|
||||
# out preventing half-done work
|
||||
execute() {
|
||||
tmpdir=$(mktemp -d)
|
||||
log_debug "downloading files into ${tmpdir}"
|
||||
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
||||
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
||||
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
||||
srcdir="${tmpdir}"
|
||||
(cd "${tmpdir}" && untar "${TARBALL}")
|
||||
test ! -d "${BINDIR}" && install -d "${BINDIR}"
|
||||
for binexe in $BINARIES; do
|
||||
if [ "$OS" = "windows" ]; then
|
||||
binexe="${binexe}.exe"
|
||||
fi
|
||||
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||
log_info "installed ${BINDIR}/${binexe}"
|
||||
done
|
||||
rm -rf "${tmpdir}"
|
||||
}
|
||||
get_binaries() {
|
||||
case "$PLATFORM" in
|
||||
darwin/amd64) BINARIES="yaegi goexports" ;;
|
||||
darwin/arm64) BINARIES="yaegi goexports" ;;
|
||||
darwin/armv5) BINARIES="yaegi goexports" ;;
|
||||
darwin/armv6) BINARIES="yaegi goexports" ;;
|
||||
darwin/armv7) BINARIES="yaegi goexports" ;;
|
||||
freebsd/386) BINARIES="yaegi goexports" ;;
|
||||
freebsd/amd64) BINARIES="yaegi goexports" ;;
|
||||
freebsd/arm64) BINARIES="yaegi goexports" ;;
|
||||
freebsd/armv5) BINARIES="yaegi goexports" ;;
|
||||
freebsd/armv6) BINARIES="yaegi goexports" ;;
|
||||
freebsd/armv7) BINARIES="yaegi goexports" ;;
|
||||
linux/386) BINARIES="yaegi goexports" ;;
|
||||
linux/amd64) BINARIES="yaegi goexports" ;;
|
||||
linux/arm64) BINARIES="yaegi goexports" ;;
|
||||
linux/armv5) BINARIES="yaegi goexports" ;;
|
||||
linux/armv6) BINARIES="yaegi goexports" ;;
|
||||
linux/armv7) BINARIES="yaegi goexports" ;;
|
||||
openbsd/386) BINARIES="yaegi goexports" ;;
|
||||
openbsd/amd64) BINARIES="yaegi goexports" ;;
|
||||
openbsd/arm64) BINARIES="yaegi goexports" ;;
|
||||
openbsd/armv5) BINARIES="yaegi goexports" ;;
|
||||
openbsd/armv6) BINARIES="yaegi goexports" ;;
|
||||
openbsd/armv7) BINARIES="yaegi goexports" ;;
|
||||
solaris/386) BINARIES="yaegi goexports" ;;
|
||||
solaris/amd64) BINARIES="yaegi goexports" ;;
|
||||
solaris/arm64) BINARIES="yaegi goexports" ;;
|
||||
solaris/armv5) BINARIES="yaegi goexports" ;;
|
||||
solaris/armv6) BINARIES="yaegi goexports" ;;
|
||||
solaris/armv7) BINARIES="yaegi goexports" ;;
|
||||
*)
|
||||
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
tag_to_version() {
|
||||
if [ -z "${TAG}" ]; then
|
||||
log_info "checking GitHub for latest tag"
|
||||
else
|
||||
log_info "checking GitHub for tag '${TAG}'"
|
||||
fi
|
||||
REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
|
||||
if test -z "$REALTAG"; then
|
||||
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
|
||||
exit 1
|
||||
fi
|
||||
# if version starts with 'v', remove it
|
||||
TAG="$REALTAG"
|
||||
VERSION=${TAG#v}
|
||||
}
|
||||
adjust_format() {
|
||||
# change format (tar.gz or zip) based on OS
|
||||
case ${OS} in
|
||||
windows) FORMAT=zip ;;
|
||||
esac
|
||||
true
|
||||
}
|
||||
adjust_os() {
|
||||
# adjust archive name based on OS
|
||||
true
|
||||
}
|
||||
adjust_arch() {
|
||||
# adjust archive name based on ARCH
|
||||
true
|
||||
}
|
||||
|
||||
cat /dev/null <<EOF
|
||||
------------------------------------------------------------------------
|
||||
https://github.com/client9/shlib - portable posix shell functions
|
||||
Public domain - http://unlicense.org
|
||||
https://github.com/client9/shlib/blob/master/LICENSE.md
|
||||
but credit (and pull requests) appreciated.
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
is_command() {
|
||||
command -v "$1" >/dev/null
|
||||
}
|
||||
echoerr() {
|
||||
echo "$@" 1>&2
|
||||
}
|
||||
log_prefix() {
|
||||
echo "$0"
|
||||
}
|
||||
_logp=6
|
||||
log_set_priority() {
|
||||
_logp="$1"
|
||||
}
|
||||
log_priority() {
|
||||
if test -z "$1"; then
|
||||
echo "$_logp"
|
||||
return
|
||||
fi
|
||||
[ "$1" -le "$_logp" ]
|
||||
}
|
||||
log_tag() {
|
||||
case $1 in
|
||||
0) echo "emerg" ;;
|
||||
1) echo "alert" ;;
|
||||
2) echo "crit" ;;
|
||||
3) echo "err" ;;
|
||||
4) echo "warning" ;;
|
||||
5) echo "notice" ;;
|
||||
6) echo "info" ;;
|
||||
7) echo "debug" ;;
|
||||
*) echo "$1" ;;
|
||||
esac
|
||||
}
|
||||
log_debug() {
|
||||
log_priority 7 || return 0
|
||||
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
|
||||
}
|
||||
log_info() {
|
||||
log_priority 6 || return 0
|
||||
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
|
||||
}
|
||||
log_err() {
|
||||
log_priority 3 || return 0
|
||||
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
|
||||
}
|
||||
log_crit() {
|
||||
log_priority 2 || return 0
|
||||
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
|
||||
}
|
||||
uname_os() {
|
||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
case "$os" in
|
||||
cygwin_nt*) os="windows" ;;
|
||||
mingw*) os="windows" ;;
|
||||
msys_nt*) os="windows" ;;
|
||||
esac
|
||||
echo "$os"
|
||||
}
|
||||
uname_arch() {
|
||||
arch=$(uname -m)
|
||||
case $arch in
|
||||
x86_64) arch="amd64" ;;
|
||||
x86) arch="386" ;;
|
||||
i686) arch="386" ;;
|
||||
i386) arch="386" ;;
|
||||
aarch64) arch="arm64" ;;
|
||||
armv5*) arch="armv5" ;;
|
||||
armv6*) arch="armv6" ;;
|
||||
armv7*) arch="armv7" ;;
|
||||
esac
|
||||
echo ${arch}
|
||||
}
|
||||
uname_os_check() {
|
||||
os=$(uname_os)
|
||||
case "$os" in
|
||||
darwin) return 0 ;;
|
||||
dragonfly) return 0 ;;
|
||||
freebsd) return 0 ;;
|
||||
linux) return 0 ;;
|
||||
android) return 0 ;;
|
||||
nacl) return 0 ;;
|
||||
netbsd) return 0 ;;
|
||||
openbsd) return 0 ;;
|
||||
plan9) return 0 ;;
|
||||
solaris) return 0 ;;
|
||||
windows) return 0 ;;
|
||||
esac
|
||||
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
|
||||
return 1
|
||||
}
|
||||
uname_arch_check() {
|
||||
arch=$(uname_arch)
|
||||
case "$arch" in
|
||||
386) return 0 ;;
|
||||
amd64) return 0 ;;
|
||||
arm64) return 0 ;;
|
||||
armv5) return 0 ;;
|
||||
armv6) return 0 ;;
|
||||
armv7) return 0 ;;
|
||||
ppc64) return 0 ;;
|
||||
ppc64le) return 0 ;;
|
||||
mips) return 0 ;;
|
||||
mipsle) return 0 ;;
|
||||
mips64) return 0 ;;
|
||||
mips64le) return 0 ;;
|
||||
s390x) return 0 ;;
|
||||
amd64p32) return 0 ;;
|
||||
esac
|
||||
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
|
||||
return 1
|
||||
}
|
||||
untar() {
|
||||
tarball=$1
|
||||
case "${tarball}" in
|
||||
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
||||
*.tar) tar -xf "${tarball}" ;;
|
||||
*.zip) unzip "${tarball}" ;;
|
||||
*)
|
||||
log_err "untar unknown archive format for ${tarball}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
http_download_curl() {
|
||||
local_file=$1
|
||||
source_url=$2
|
||||
header=$3
|
||||
if [ -z "$header" ]; then
|
||||
code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
|
||||
else
|
||||
code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
|
||||
fi
|
||||
if [ "$code" != "200" ]; then
|
||||
log_debug "http_download_curl received HTTP status $code"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
http_download_wget() {
|
||||
local_file=$1
|
||||
source_url=$2
|
||||
header=$3
|
||||
if [ -z "$header" ]; then
|
||||
wget -q -O "$local_file" "$source_url"
|
||||
else
|
||||
wget -q --header "$header" -O "$local_file" "$source_url"
|
||||
fi
|
||||
}
|
||||
http_download() {
|
||||
log_debug "http_download $2"
|
||||
if is_command curl; then
|
||||
http_download_curl "$@"
|
||||
return
|
||||
elif is_command wget; then
|
||||
http_download_wget "$@"
|
||||
return
|
||||
fi
|
||||
log_crit "http_download unable to find wget or curl"
|
||||
return 1
|
||||
}
|
||||
http_copy() {
|
||||
tmp=$(mktemp)
|
||||
http_download "${tmp}" "$1" "$2" || return 1
|
||||
body=$(cat "$tmp")
|
||||
rm -f "${tmp}"
|
||||
echo "$body"
|
||||
}
|
||||
github_release() {
|
||||
owner_repo=$1
|
||||
version=$2
|
||||
test -z "$version" && version="latest"
|
||||
giturl="https://github.com/${owner_repo}/releases/${version}"
|
||||
json=$(http_copy "$giturl" "Accept:application/json")
|
||||
test -z "$json" && return 1
|
||||
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
|
||||
test -z "$version" && return 1
|
||||
echo "$version"
|
||||
}
|
||||
hash_sha256() {
|
||||
TARGET=${1:-/dev/stdin}
|
||||
if is_command gsha256sum; then
|
||||
hash=$(gsha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command sha256sum; then
|
||||
hash=$(sha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command shasum; then
|
||||
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command openssl; then
|
||||
hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f a
|
||||
else
|
||||
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
hash_sha256_verify() {
|
||||
TARGET=$1
|
||||
checksums=$2
|
||||
if [ -z "$checksums" ]; then
|
||||
log_err "hash_sha256_verify checksum file not specified in arg2"
|
||||
return 1
|
||||
fi
|
||||
BASENAME=${TARGET##*/}
|
||||
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
|
||||
if [ -z "$want" ]; then
|
||||
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
|
||||
return 1
|
||||
fi
|
||||
got=$(hash_sha256 "$TARGET")
|
||||
if [ "$want" != "$got" ]; then
|
||||
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
cat /dev/null <<EOF
|
||||
------------------------------------------------------------------------
|
||||
End of functions from https://github.com/client9/shlib
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
|
||||
PROJECT_NAME="yaegi"
|
||||
OWNER=traefik
|
||||
REPO="yaegi"
|
||||
BINARY=yaegi
|
||||
FORMAT=tar.gz
|
||||
OS=$(uname_os)
|
||||
ARCH=$(uname_arch)
|
||||
PREFIX="$OWNER/$REPO"
|
||||
|
||||
# use in logging routines
|
||||
log_prefix() {
|
||||
echo "$PREFIX"
|
||||
}
|
||||
PLATFORM="${OS}/${ARCH}"
|
||||
GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download
|
||||
|
||||
uname_os_check "$OS"
|
||||
uname_arch_check "$ARCH"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
get_binaries
|
||||
|
||||
tag_to_version
|
||||
|
||||
adjust_format
|
||||
|
||||
adjust_os
|
||||
|
||||
adjust_arch
|
||||
|
||||
log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"
|
||||
|
||||
NAME=${PROJECT_NAME}_v${VERSION}_${OS}_${ARCH}
|
||||
TARBALL=${NAME}.${FORMAT}
|
||||
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
|
||||
CHECKSUM=${PROJECT_NAME}_${VERSION}_checksums.txt
|
||||
CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}
|
||||
|
||||
|
||||
execute
|
||||
@@ -32,7 +32,7 @@ func {{$name}}(n *node) {
|
||||
case reflect.String:
|
||||
switch {
|
||||
case c0.rval.IsValid():
|
||||
s0 := c0.rval.String()
|
||||
s0 := vString(c0.rval)
|
||||
v1 := genValue(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetString(s0 {{$op.Name}} v1(f).String())
|
||||
@@ -40,7 +40,7 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case c1.rval.IsValid():
|
||||
v0 := genValue(c0)
|
||||
s1 := c1.rval.String()
|
||||
s1 := vString(c1.rval)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetString(v0(f).String() {{$op.Name}} s1)
|
||||
return next
|
||||
@@ -202,7 +202,7 @@ func {{$name}}Const(n *node) {
|
||||
{{- end}}
|
||||
{{- if $op.Str}}
|
||||
case isString(t):
|
||||
n.rval.SetString(v0.String() {{$op.Name}} v1.String())
|
||||
n.rval.SetString(vString(v0) {{$op.Name}} vString(v1))
|
||||
{{- end}}
|
||||
{{- if $op.Float}}
|
||||
case isComplex(t):
|
||||
@@ -233,7 +233,7 @@ func {{$name}}Assign(n *node) {
|
||||
{{- if $op.Str}}
|
||||
case reflect.String:
|
||||
v0 := genValueString(c0)
|
||||
v1 := c1.rval.String()
|
||||
v1 := vString(c1.rval)
|
||||
n.exec = func(f *frame) bltn {
|
||||
v, s := v0(f)
|
||||
v.SetString(s {{$op.Name}} v1)
|
||||
@@ -496,7 +496,7 @@ func {{$name}}(n *node) {
|
||||
case isString(t0) || isString(t1):
|
||||
switch {
|
||||
case c0.rval.IsValid():
|
||||
s0 := c0.rval.String()
|
||||
s0 := vString(c0.rval)
|
||||
v1 := genValueString(n.child[1])
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
@@ -517,7 +517,7 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
}
|
||||
case c1.rval.IsValid():
|
||||
s1 := c1.rval.String()
|
||||
s1 := vString(c1.rval)
|
||||
v0 := genValueString(n.child[0])
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"go/token"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
@@ -339,30 +341,48 @@ func (interp *Interpreter) firstToken(src string) token.Token {
|
||||
return tok
|
||||
}
|
||||
|
||||
func ignoreError(err error, src string) bool {
|
||||
se, ok := err.(scanner.ErrorList)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if len(se) == 0 {
|
||||
return false
|
||||
}
|
||||
return ignoreScannerError(se[0], src)
|
||||
}
|
||||
|
||||
func wrapInMain(src string) string {
|
||||
return fmt.Sprintf("package main; func main() {%s}", src)
|
||||
}
|
||||
|
||||
// Note: no type analysis is performed at this stage, it is done in pre-order
|
||||
// processing of CFG, in order to accommodate forward type declarations
|
||||
// processing of CFG, in order to accommodate forward type declarations.
|
||||
|
||||
// ast parses src string containing Go code and generates the corresponding AST.
|
||||
// The package name and the AST root node are returned.
|
||||
func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
inRepl := name == ""
|
||||
// The given name is used to set the filename of the relevant source file in the
|
||||
// interpreter's FileSet.
|
||||
func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error) {
|
||||
var inFunc bool
|
||||
var mode parser.Mode
|
||||
mode := parser.DeclarationErrors
|
||||
|
||||
// Allow incremental parsing of declarations or statements, by inserting
|
||||
// them in a pseudo file package or function. Those statements or
|
||||
// declarations will be always evaluated in the global scope
|
||||
if inRepl {
|
||||
switch interp.firstToken(src) {
|
||||
// declarations will be always evaluated in the global scope.
|
||||
var tok token.Token
|
||||
if inc {
|
||||
tok = interp.firstToken(src)
|
||||
switch tok {
|
||||
case token.PACKAGE:
|
||||
// nothing to do
|
||||
// nothing to do.
|
||||
case token.CONST, token.FUNC, token.IMPORT, token.TYPE, token.VAR:
|
||||
src = "package main;" + src
|
||||
default:
|
||||
inFunc = true
|
||||
src = "package main; func main() {" + src + "}"
|
||||
src = wrapInMain(src)
|
||||
}
|
||||
// Parse comments in REPL mode, to allow tag setting
|
||||
// Parse comments in REPL mode, to allow tag setting.
|
||||
mode |= parser.ParseComments
|
||||
}
|
||||
|
||||
@@ -372,7 +392,22 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
|
||||
f, err := parser.ParseFile(interp.fset, name, src, mode)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
// only retry if we're on an expression/statement about a func
|
||||
if !inc || tok != token.FUNC {
|
||||
return "", nil, err
|
||||
}
|
||||
// do not bother retrying if we know it's an error we're going to ignore later on.
|
||||
if ignoreError(err, src) {
|
||||
return "", nil, err
|
||||
}
|
||||
// do not lose initial error, in case retrying fails.
|
||||
initialError := err
|
||||
// retry with default source code "wrapping", in the main function scope.
|
||||
src := wrapInMain(strings.TrimPrefix(src, "package main;"))
|
||||
f, err = parser.ParseFile(interp.fset, name, src, mode)
|
||||
if err != nil {
|
||||
return "", nil, initialError
|
||||
}
|
||||
}
|
||||
|
||||
setYaegiTags(&interp.context, f.Comments)
|
||||
@@ -487,20 +522,12 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
n.ident = a.Value
|
||||
switch a.Kind {
|
||||
case token.CHAR:
|
||||
// Char cannot be converted to a const here as we cannot tell the type.
|
||||
v, _, _, _ := strconv.UnquoteChar(a.Value[1:len(a.Value)-1], '\'')
|
||||
n.rval = reflect.ValueOf(v)
|
||||
case token.FLOAT:
|
||||
case token.FLOAT, token.IMAG, token.INT, token.STRING:
|
||||
v := constant.MakeFromLiteral(a.Value, a.Kind, 0)
|
||||
n.rval = reflect.ValueOf(v)
|
||||
case token.IMAG:
|
||||
v := constant.MakeFromLiteral(a.Value, a.Kind, 0)
|
||||
n.rval = reflect.ValueOf(v)
|
||||
case token.INT:
|
||||
v := constant.MakeFromLiteral(a.Value, a.Kind, 0)
|
||||
n.rval = reflect.ValueOf(v)
|
||||
case token.STRING:
|
||||
v, _ := strconv.Unquote(a.Value)
|
||||
n.rval = reflect.ValueOf(v)
|
||||
}
|
||||
st.push(n, nod)
|
||||
|
||||
@@ -859,10 +886,13 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
})
|
||||
if inFunc {
|
||||
// Incremental parsing: statements were inserted in a pseudo function.
|
||||
// Set root to function body so its statements are evaluated in global scope
|
||||
// Set root to function body so its statements are evaluated in global scope.
|
||||
root = root.child[1].child[3]
|
||||
root.anc = nil
|
||||
}
|
||||
if pkgName == "" {
|
||||
return "", root, errors.New("no package name found")
|
||||
}
|
||||
return pkgName, root, err
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user