Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d494f9e420 | ||
|
|
6da1107c39 | ||
|
|
38a7331bf9 | ||
|
|
13783889cb | ||
|
|
ed626f3fb9 | ||
|
|
d0a34d467b | ||
|
|
83676577ac | ||
|
|
f0fc907269 | ||
|
|
61f4704925 | ||
|
|
b1ccfbf47f | ||
|
|
0ed4b362dc | ||
|
|
98807387a4 | ||
|
|
c817823ba1 | ||
|
|
3cb8bca81a | ||
|
|
a38d19288f | ||
|
|
7f8ffa6719 | ||
|
|
513f5e37aa | ||
|
|
9520a92241 | ||
|
|
d47821bfaa | ||
|
|
d7ede8ed5c | ||
|
|
22c63b225c | ||
|
|
c0eaab0891 | ||
|
|
c74d050c5a | ||
|
|
804664c631 | ||
|
|
f6d8261a8a | ||
|
|
68c02ce054 | ||
|
|
4b3e9ee231 | ||
|
|
8916618a81 | ||
|
|
57b49f40d6 | ||
|
|
190dade469 | ||
|
|
6b652ea485 | ||
|
|
473bc63588 | ||
|
|
e32da38ad0 | ||
|
|
b2b519c2fd | ||
|
|
9491e58920 | ||
|
|
f362237ac5 | ||
|
|
a83ec1f925 | ||
|
|
155ca4e6ad | ||
|
|
ca196a5768 | ||
|
|
b78d55c66b | ||
|
|
16f5586a11 | ||
|
|
c3cf301c60 | ||
|
|
0dde990d0b | ||
|
|
4cfeb1946e | ||
|
|
ec64b006cf | ||
|
|
f36d4e01eb | ||
|
|
5dfc3b86dc | ||
|
|
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 | ||
|
|
b0cd93a936 | ||
|
|
611a8c37fa | ||
|
|
e71ddc7edd | ||
|
|
1fe75f149d | ||
|
|
cdc352cee2 | ||
|
|
88569f5df7 | ||
|
|
2ac0c6f70b | ||
|
|
bd4ce37baa | ||
|
|
9c4d3d1e5a | ||
|
|
25c681c1e6 | ||
|
|
9c51f6bb69 | ||
|
|
589b2a0cd2 | ||
|
|
68911f8b4e | ||
|
|
e5a7b0de11 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,7 +3,7 @@
|
|||||||
*.dot
|
*.dot
|
||||||
.idea/
|
.idea/
|
||||||
/yaegi
|
/yaegi
|
||||||
cmd/goexports/goexports
|
internal/cmd/extract/extract
|
||||||
example/inception/inception
|
example/inception/inception
|
||||||
_test/tmp/
|
_test/tmp/
|
||||||
/dist
|
/dist
|
||||||
|
|||||||
@@ -41,6 +41,8 @@
|
|||||||
"testpackage",
|
"testpackage",
|
||||||
"goerr113",
|
"goerr113",
|
||||||
"nestif",
|
"nestif",
|
||||||
|
"exhaustive",
|
||||||
|
"nlreturn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[issues]
|
[issues]
|
||||||
|
|||||||
@@ -3,32 +3,7 @@ project_name: yaegi
|
|||||||
builds:
|
builds:
|
||||||
- id: yaegi
|
- id: yaegi
|
||||||
binary: yaegi
|
binary: yaegi
|
||||||
main: ./cmd/yaegi/yaegi.go
|
main: ./cmd/yaegi/
|
||||||
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
- linux
|
|
||||||
# - windows
|
|
||||||
- freebsd
|
|
||||||
- openbsd
|
|
||||||
- solaris
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- 386
|
|
||||||
- arm
|
|
||||||
- arm64
|
|
||||||
goarm:
|
|
||||||
- 7
|
|
||||||
- 6
|
|
||||||
- 5
|
|
||||||
|
|
||||||
ignore:
|
|
||||||
- goos: darwin
|
|
||||||
goarch: 386
|
|
||||||
|
|
||||||
- id: goexports
|
|
||||||
binary: goexports
|
|
||||||
main: ./cmd/goexports/goexports.go
|
|
||||||
|
|
||||||
goos:
|
goos:
|
||||||
- darwin
|
- darwin
|
||||||
@@ -70,3 +45,19 @@ archives:
|
|||||||
format: zip
|
format: zip
|
||||||
files:
|
files:
|
||||||
- LICENSE
|
- LICENSE
|
||||||
|
|
||||||
|
brews:
|
||||||
|
- github:
|
||||||
|
owner: traefik
|
||||||
|
name: homebrew-tap
|
||||||
|
commit_author:
|
||||||
|
name: traefiker
|
||||||
|
email: 30906710+traefiker@users.noreply.github.com
|
||||||
|
folder: Formula
|
||||||
|
homepage: https://github.com/traefik/yaegi
|
||||||
|
description: |
|
||||||
|
Yaegi is Another Elegant Go Interpreter.
|
||||||
|
It powers executable Go scripts and plugins, in embedded interpreters
|
||||||
|
or interactive shells, on top of the Go runtime.
|
||||||
|
test: |
|
||||||
|
system "#{bin}/yaegi version"
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ cache:
|
|||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
include:
|
include:
|
||||||
- go: 1.13.x
|
|
||||||
- go: 1.14.x
|
- go: 1.14.x
|
||||||
|
- go: 1.15.x
|
||||||
env: STABLE=true
|
env: STABLE=true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- GO111MODULE=on
|
- GO111MODULE=on
|
||||||
|
|
||||||
go_import_path: github.com/containous/yaegi
|
go_import_path: github.com/traefik/yaegi
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
# Install linters and misspell
|
# Install linters and misspell
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Yaegi is an open source project, and your feedback and contributions
|
Yaegi is an open source project, and your feedback and contributions
|
||||||
are needed and always welcome.
|
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
|
Non trivial changes should be discussed with the project maintainers by
|
||||||
opening a [Feature Request] clearly explaining rationale, background
|
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
|
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].
|
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
|
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.
|
agreement will be presented to you in the web interface of the pull request.
|
||||||
|
|
||||||
[Issues]: https://github.com/containous/yaegi/issues
|
[Issues]: https://github.com/traefik/yaegi/issues
|
||||||
[Pull Requests]: https://github.com/containous/yaegi/issues
|
[Pull Requests]: https://github.com/traefik/yaegi/issues
|
||||||
[Feature Request]: https://github.com/containous/yaegi/issues/new?template=feature_request.md
|
[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/
|
[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.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2019 Containous SAS
|
Copyright 2019 Containous SAS
|
||||||
|
Copyright 2020 Traefik Labs SAS
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
27
Makefile
27
Makefile
@@ -3,21 +3,28 @@ check:
|
|||||||
golangci-lint run
|
golangci-lint run
|
||||||
|
|
||||||
# Generate stdlib/syscall/syscall_GOOS_GOARCH.go for all platforms
|
# Generate stdlib/syscall/syscall_GOOS_GOARCH.go for all platforms
|
||||||
gen_all_syscall: cmd/goexports/goexports
|
gen_all_syscall: internal/cmd/extract/extract
|
||||||
@cd stdlib/syscall && \
|
@for v in $$(go tool dist list); do \
|
||||||
for v in $$(go tool dist list); do \
|
|
||||||
echo syscall_$${v%/*}_$${v#*/}.go; \
|
echo syscall_$${v%/*}_$${v#*/}.go; \
|
||||||
GOOS=$${v%/*} GOARCH=$${v#*/} go generate; \
|
GOOS=$${v%/*} GOARCH=$${v#*/} go generate ./stdlib/syscall ./stdlib/unrestricted; \
|
||||||
done
|
done
|
||||||
|
|
||||||
cmd/goexports/goexports: cmd/goexports/goexports.go
|
internal/cmd/extract/extract:
|
||||||
go generate cmd/goexports/goexports.go
|
rm -f internal/cmd/extract/extract
|
||||||
|
go generate ./internal/cmd/extract
|
||||||
|
|
||||||
generate: gen_all_syscall
|
generate: gen_all_syscall
|
||||||
go generate
|
go generate
|
||||||
|
|
||||||
tests:
|
install:
|
||||||
GO111MODULE=off go test -v ./...
|
GOFLAGS=-ldflags=-X=main.version=$$(git describe --tags) go install ./...
|
||||||
GO111MODULE=off go test -race ./interp
|
|
||||||
|
|
||||||
.PHONY: check gen_all_syscall gen_tests
|
tests:
|
||||||
|
go test -v ./...
|
||||||
|
go test -race ./interp
|
||||||
|
|
||||||
|
# https://github.com/goreleaser/godownloader
|
||||||
|
install.sh: .goreleaser.yml
|
||||||
|
godownloader --repo=traefik/yaegi -o install.sh .goreleaser.yml
|
||||||
|
|
||||||
|
.PHONY: check gen_all_syscall gen_tests generate_downloader internal/cmd/extract/extract install
|
||||||
|
|||||||
58
README.md
58
README.md
@@ -2,9 +2,9 @@
|
|||||||
<img width="400" src="doc/images/yaegi.png" alt="Yaegi" title="Yaegi" />
|
<img width="400" src="doc/images/yaegi.png" alt="Yaegi" title="Yaegi" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[](https://github.com/containous/yaegi/releases)
|
[](https://github.com/traefik/yaegi/releases)
|
||||||
[](https://travis-ci.com/containous/yaegi)
|
[](https://travis-ci.com/traefik/yaegi)
|
||||||
[](https://godoc.org/github.com/containous/yaegi)
|
[](https://godoc.org/github.com/traefik/yaegi)
|
||||||
[](https://community.containo.us/c/yaegi)
|
[](https://community.containo.us/c/yaegi)
|
||||||
|
|
||||||
Yaegi is Another Elegant Go Interpreter.
|
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 package
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/containous/yaegi/interp"
|
import "github.com/traefik/yaegi/interp"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Command-line executable
|
### Command-line executable
|
||||||
|
|
||||||
```bash
|
```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),
|
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.
|
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
|
## Usage
|
||||||
|
|
||||||
### As an embedded interpreter
|
### As an embedded interpreter
|
||||||
@@ -47,8 +53,8 @@ Create an interpreter with `New()`, run Go code with `Eval()`:
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
"github.com/containous/yaegi/stdlib"
|
"github.com/traefik/yaegi/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -68,7 +74,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[Go Playground](https://play.golang.org/p/zzvw4VlerLP)
|
[Go Playground](https://play.golang.org/p/2n-EpZbMYI9)
|
||||||
|
|
||||||
### As a dynamic extension framework
|
### As a dynamic extension framework
|
||||||
|
|
||||||
@@ -81,7 +87,7 @@ The following program is compiled ahead of time, except `bar()` which is interpr
|
|||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/interp"
|
import "github.com/traefik/yaegi/interp"
|
||||||
|
|
||||||
const src = `package foo
|
const src = `package foo
|
||||||
func Bar(s string) string { return s + "-Foo" }`
|
func Bar(s string) string { return s + "-Foo" }`
|
||||||
@@ -106,7 +112,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[Go Playground](https://play.golang.org/p/6SEAoaO7n0U)
|
[Go Playground](https://play.golang.org/p/WvwH4JqrU-p)
|
||||||
|
|
||||||
### As a command-line interpreter
|
### As a command-line interpreter
|
||||||
|
|
||||||
@@ -122,10 +128,20 @@ Hello World
|
|||||||
>
|
>
|
||||||
```
|
```
|
||||||
|
|
||||||
Or interpret Go files:
|
Note that in interactive mode, all stdlib package are pre-imported,
|
||||||
|
you can use them directly:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ yaegi cmd/yaegi/yaegi.go
|
$ yaegi
|
||||||
|
> reflect.TypeOf(time.Date)
|
||||||
|
: func(int, time.Month, int, int, int, int, int, *time.Location) time.Time
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Or interpret Go packages, directories or files, including itself:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ yaegi -syscall -unsafe -unrestricted github.com/traefik/yaegi/cmd/yaegi
|
||||||
>
|
>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -155,11 +171,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:
|
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
|
- Assembly files (`.s`) are not supported.
|
||||||
- calling C code is not supported (no virtual "C" package)
|
- 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
|
- 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
|
- 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
|
- Interpreting computation intensive code is likely to remain significantly slower than in compiled mode.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -170,7 +186,7 @@ Beside the known [bugs] which are supposed to be fixed in the short term, there
|
|||||||
[Apache 2.0][License].
|
[Apache 2.0][License].
|
||||||
|
|
||||||
[specs]: https://golang.org/ref/spec
|
[specs]: https://golang.org/ref/spec
|
||||||
[docs]: https://godoc.org/github.com/containous/yaegi
|
[docs]: https://godoc.org/github.com/traefik/yaegi
|
||||||
[license]: https://github.com/containous/yaegi/blob/master/LICENSE
|
[license]: https://github.com/traefik/yaegi/blob/master/LICENSE
|
||||||
[github]: https://github.com/containous/yaegi
|
[github]: https://github.com/traefik/yaegi
|
||||||
[bugs]: https://github.com/containous/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug
|
[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]
|
||||||
17
_test/a43.go
Normal file
17
_test/a43.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type T [l1 + l2]int
|
||||||
|
|
||||||
|
const (
|
||||||
|
l1 = 2
|
||||||
|
l2 = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(T{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [0 0 0 0 0]
|
||||||
12
_test/a44.go
Normal file
12
_test/a44.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var a = [max]int{}
|
||||||
|
|
||||||
|
const max = 32
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(len(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 32
|
||||||
25
_test/addr0.go
Normal file
25
_test/addr0.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type extendedRequest struct {
|
||||||
|
http.Request
|
||||||
|
|
||||||
|
Data string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := extendedRequest{}
|
||||||
|
req := &r.Request
|
||||||
|
|
||||||
|
|
||||||
|
fmt.Println(r)
|
||||||
|
fmt.Println(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>} }
|
||||||
|
// &{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>}
|
||||||
22
_test/addr1.go
Normal file
22
_test/addr1.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
A int
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := &[]T{
|
||||||
|
{1, 2},
|
||||||
|
{3, 4},
|
||||||
|
}
|
||||||
|
fmt.Println("a:", a)
|
||||||
|
x := &(*a)[1:][0]
|
||||||
|
fmt.Println("x:", x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a: &[{1 2} {3 4}]
|
||||||
|
// x: &{3 4}
|
||||||
15
_test/append1.go
Normal file
15
_test/append1.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := bufio.NewScanner(bytes.NewReader([]byte("Hello\nTest\nLine3")))
|
||||||
|
s.Scan()
|
||||||
|
println(string(append(s.Bytes(), []byte(" World")...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello World
|
||||||
15
_test/append2.go
Normal file
15
_test/append2.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := bufio.NewScanner(bytes.NewReader([]byte("Hello\nTest\nLine3")))
|
||||||
|
s.Scan()
|
||||||
|
println(string(append(s.Bytes(), " World"...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello World
|
||||||
15
_test/assign16.go
Normal file
15
_test/assign16.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type H struct {
|
||||||
|
bits uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := &H{8}
|
||||||
|
var x uint = (1 << h.bits) >> 6
|
||||||
|
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package foo
|
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"
|
var Desc = "in b1/foo"
|
||||||
|
|
||||||
|
|||||||
17
_test/binstruct_ptr_map0.go
Normal file
17
_test/binstruct_ptr_map0.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v := map[string]*image.Point{
|
||||||
|
"foo": {X: 3, Y: 2},
|
||||||
|
"bar": {X: 4, Y: 5},
|
||||||
|
}
|
||||||
|
fmt.Println(v["foo"], v["bar"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// (3,2) (4,5)
|
||||||
17
_test/binstruct_ptr_slice0.go
Normal file
17
_test/binstruct_ptr_slice0.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v := []*image.Point{
|
||||||
|
{X: 3, Y: 2},
|
||||||
|
{X: 4, Y: 5},
|
||||||
|
}
|
||||||
|
fmt.Println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [(3,2) (4,5)]
|
||||||
16
_test/binstruct_slice0.go
Normal file
16
_test/binstruct_slice0.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v := []image.Point{
|
||||||
|
{X: 3, Y: 2},
|
||||||
|
}
|
||||||
|
fmt.Println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [(3,2)]
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
package c1
|
package c1
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/c2"
|
import "github.com/traefik/yaegi/_test/c2"
|
||||||
|
|
||||||
var C1 = c2.C2 + "x"
|
var C1 = c2.C2 + "x"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package c2
|
package c2
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/c1"
|
import "github.com/traefik/yaegi/_test/c1"
|
||||||
|
|
||||||
var C2 = c1.C1 + "Y"
|
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
|
||||||
15
_test/composite14.go
Normal file
15
_test/composite14.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
b []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := T{nil}
|
||||||
|
fmt.Println(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {[]}
|
||||||
@@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containous/yaegi/_test/ct1"
|
"github.com/traefik/yaegi/_test/ct1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type T struct {
|
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
|
||||||
12
_test/const16.go
Normal file
12
_test/const16.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(7 / 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2
|
||||||
14
_test/const17.go
Normal file
14
_test/const17.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var t [7/3]int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t[0] = 3/2
|
||||||
|
t[1] = 5/2
|
||||||
|
fmt.Println(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2]
|
||||||
11
_test/const18.go
Normal file
11
_test/const18.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := int64(time.Second)
|
||||||
|
println(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1000000000
|
||||||
17
_test/const19.go
Normal file
17
_test/const19.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func get10Hours() time.Duration {
|
||||||
|
return 10 * time.Hour
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(get10Hours().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10h0m0s
|
||||||
12
_test/const20.go
Normal file
12
_test/const20.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const maxLen = int64(int(^uint(0) >> 1))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(maxLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 9223372036854775807
|
||||||
12
_test/const21.go
Normal file
12
_test/const21.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const a = 64
|
||||||
|
|
||||||
|
var b uint = a * a / 2
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2048
|
||||||
21
_test/convert0.go
Normal file
21
_test/convert0.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
v int
|
||||||
|
}
|
||||||
|
|
||||||
|
type comparator func(T, T) bool
|
||||||
|
|
||||||
|
func sort(items []T, comp comparator) {
|
||||||
|
println("in sort")
|
||||||
|
}
|
||||||
|
|
||||||
|
func compT(t0, t1 T) bool { return t0.v < t1.v }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := []T{}
|
||||||
|
sort(a, comparator(compT))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// in sort
|
||||||
17
_test/convert1.go
Normal file
17
_test/convert1.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
type atoidef func(s string) (int, error)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
stdatoi := atoidef(strconv.Atoi)
|
||||||
|
n, err := stdatoi("7")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
println(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 7
|
||||||
19
_test/convert2.go
Normal file
19
_test/convert2.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "bufio"
|
||||||
|
|
||||||
|
func fakeSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
|
return 7, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
splitfunc := bufio.SplitFunc(fakeSplitFunc)
|
||||||
|
n, _, err := splitfunc(nil, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
println(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 7
|
||||||
@@ -2,13 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(log.Lshortfile)
|
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 {
|
if _, err := i.Eval(`func f() (int, int) { return 1, 2 }`); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package foo
|
package foo
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/foo/boo"
|
import "github.com/traefik/yaegi/_test/foo/boo"
|
||||||
|
|
||||||
var Bar = "BARR"
|
var Bar = "BARR"
|
||||||
var Boo = boo.Boo
|
var Boo = boo.Boo
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package foo
|
package foo
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/foo/boo"
|
import "github.com/traefik/yaegi/_test/foo/boo"
|
||||||
|
|
||||||
var Bir = boo.Boo + "22"
|
var Bir = boo.Boo + "22"
|
||||||
|
|||||||
16
_test/for15.go
Normal file
16
_test/for15.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func f() int { println("in f"); return 1 }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for i := f(); ; {
|
||||||
|
println("in loop")
|
||||||
|
if i > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// in f
|
||||||
|
// in loop
|
||||||
16
_test/for16.go
Normal file
16
_test/for16.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
max := 1
|
||||||
|
for ; ; max-- {
|
||||||
|
if max == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println("in for")
|
||||||
|
}
|
||||||
|
println("bye")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// in for
|
||||||
|
// bye
|
||||||
10
_test/fun23.go
Normal file
10
_test/fun23.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func f(x int) { return x }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// 3:17: too many arguments to return
|
||||||
10
_test/fun24.go
Normal file
10
_test/fun24.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func f(x int) (int, int) { return x, "foo" }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// cannot use "foo" (type stringT) as type intT in return argument
|
||||||
10
_test/fun25.go
Normal file
10
_test/fun25.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func f(x string) (a int, b int) { return x, 5 }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error:
|
||||||
|
// cannot use x (type stringT) as type intT in return argument
|
||||||
17
_test/fun26.go
Normal file
17
_test/fun26.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type F func() (int, error)
|
||||||
|
|
||||||
|
func f1() (int, error) { return 3, nil }
|
||||||
|
|
||||||
|
func f2(a string, f F) {
|
||||||
|
c, _ := f()
|
||||||
|
println(a, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f2("hello", F(f1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello 3
|
||||||
12
_test/goto1.go
Normal file
12
_test/goto1.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if true {
|
||||||
|
goto here
|
||||||
|
}
|
||||||
|
here:
|
||||||
|
println("ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/foo"
|
import "github.com/traefik/yaegi/_test/foo"
|
||||||
|
|
||||||
func main() { println(foo.Bar, foo.Boo) }
|
func main() { println(foo.Bar, foo.Boo) }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/p1"
|
import "github.com/traefik/yaegi/_test/p1"
|
||||||
|
|
||||||
func main() { println("num:", p1.Uint32()) }
|
func main() { println("num:", p1.Uint32()) }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
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) }
|
func main() { println(boo.Bar, boo.Boo, boo.Bir) }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/c1"
|
import "github.com/traefik/yaegi/_test/c1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(c1.C1)
|
println(c1.C1)
|
||||||
@@ -8,4 +8,4 @@ func main() {
|
|||||||
|
|
||||||
// Error:
|
// Error:
|
||||||
// import cycle not allowed
|
// import cycle not allowed
|
||||||
// imports github.com/containous/yaegi/_test/c1
|
// imports github.com/traefik/yaegi/_test/c1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/foo-bar"
|
import bar "github.com/traefik/yaegi/_test/foo-bar"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(bar.Name)
|
println(bar.Name)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/b1/foo"
|
import "github.com/traefik/yaegi/_test/b1/foo"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(foo.Desc)
|
println(foo.Desc)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/baz-bat"
|
import "github.com/traefik/yaegi/_test/baz-bat"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(baz.Name)
|
println(baz.Name)
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(log.Lshortfile)
|
log.SetFlags(log.Lshortfile)
|
||||||
i := interp.New(interp.Options{})
|
i := interp.New(interp.Options{})
|
||||||
i.Use(interp.Symbols)
|
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)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := i.Eval(`i := interp.New(interp.Options{})`); err != nil {
|
if _, err := i.Eval(`i := interp.New(interp.Options{})`); err != nil {
|
||||||
@@ -20,6 +20,3 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 42
|
|
||||||
|
|||||||
35
_test/interface46.go
Normal file
35
_test/interface46.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
Foo() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Printer struct {
|
||||||
|
i I
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(i I) *Printer {
|
||||||
|
return &Printer{
|
||||||
|
i: i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Printer) Print() {
|
||||||
|
fmt.Println(p.i.Foo())
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct{}
|
||||||
|
|
||||||
|
func (t *T) Foo() string {
|
||||||
|
return "test"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
g := New(&T{})
|
||||||
|
g.Print()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
i := interp.New(interp.Opt{})
|
i := interp.New(interp.Opt{})
|
||||||
i.Use(interp.ExportValue, interp.ExportType)
|
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 := interp.New(interp.Opt{})`)
|
||||||
i.Eval(`i.Eval("println(42)")`)
|
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
|
||||||
25
_test/issue-770.go
Normal file
25
_test/issue-770.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
Foo() int
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t T) Foo() int { return 0 }
|
||||||
|
|
||||||
|
func f(v reflect.Value) int {
|
||||||
|
i := v.Interface().(I)
|
||||||
|
return i.Foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
14
_test/issue-782.go
Normal file
14
_test/issue-782.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
|
from := uint32(2)
|
||||||
|
to := uint32(4)
|
||||||
|
b := a[from:to]
|
||||||
|
fmt.Print(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 4]
|
||||||
39
_test/issue-784.go
Normal file
39
_test/issue-784.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Filter is a filter interface
|
||||||
|
type Filter interface {
|
||||||
|
Bounds(srcBounds string) (dstBounds string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GIFT type
|
||||||
|
type GIFT struct {
|
||||||
|
Filters []Filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new filter list and initializes it with the given slice of filters.
|
||||||
|
func New(filters ...Filter) *GIFT {
|
||||||
|
return &GIFT{
|
||||||
|
Filters: filters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bounds calculates the appropriate bounds for the result image after applying all the added filters.
|
||||||
|
func (g *GIFT) Bounds(srcBounds string) (dstBounds string) {
|
||||||
|
dstBounds = srcBounds
|
||||||
|
for _, f := range g.Filters {
|
||||||
|
dstBounds = f.Bounds(dstBounds)
|
||||||
|
}
|
||||||
|
return dstBounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var filters []Filter
|
||||||
|
bounds := "foo"
|
||||||
|
g := New(filters...)
|
||||||
|
fmt.Println(g.Bounds(bounds))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo
|
||||||
23
_test/issue-880.go
Normal file
23
_test/issue-880.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var buf1 = make([]byte, 1024)
|
||||||
|
var buf2 []byte
|
||||||
|
buf1 = []byte("Hallo\nTest\nLine3")
|
||||||
|
|
||||||
|
s := bufio.NewScanner(bytes.NewReader(buf1))
|
||||||
|
for s.Scan() {
|
||||||
|
buf2 = append(buf2, append(s.Bytes(), []byte("\n")...)...)
|
||||||
|
}
|
||||||
|
print(string(buf2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hallo
|
||||||
|
// Test
|
||||||
|
// Line3
|
||||||
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")
|
||||||
|
}
|
||||||
32
_test/math3.go
Normal file
32
_test/math3.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func md5Crypt(password, salt, magic []byte) []byte {
|
||||||
|
d := md5.New()
|
||||||
|
d.Write(password)
|
||||||
|
d.Write(magic)
|
||||||
|
d.Write(salt)
|
||||||
|
|
||||||
|
d2 := md5.New()
|
||||||
|
d2.Write(password)
|
||||||
|
d2.Write(salt)
|
||||||
|
|
||||||
|
for i, mixin := 0, d2.Sum(nil); i < len(password); i++ {
|
||||||
|
d.Write([]byte{mixin[i%16]})
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.Sum(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := md5Crypt([]byte("1"), []byte("2"), []byte("3"))
|
||||||
|
|
||||||
|
fmt.Println(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [187 141 73 89 101 229 33 106 226 63 117 234 117 149 230 21]
|
||||||
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
|
||||||
28
_test/nil3.go
Normal file
28
_test/nil3.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
Hello()
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
h I
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Hello() { println("Hello") }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := &T{}
|
||||||
|
println(t.h != nil)
|
||||||
|
println(t.h == nil)
|
||||||
|
t.h = t
|
||||||
|
println(t.h != nil)
|
||||||
|
println(t.h == nil)
|
||||||
|
t.h.Hello()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// Hello
|
||||||
@@ -7,4 +7,4 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error:
|
// Error:
|
||||||
// 5:2: illegal operand types for '+=' operator
|
// 5:2: invalid operation: mismatched types int and float64
|
||||||
|
|||||||
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:
|
// 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
|
||||||
12
_test/rune1.go
Normal file
12
_test/rune1.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := make([]byte, 2)
|
||||||
|
t[0] = '$'
|
||||||
|
fmt.Println(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [36 0]
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
import "fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c1 := make(chan string)
|
c1 := make(chan string)
|
||||||
c2 := make(chan string)
|
c2 := make(chan string)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(1e9)
|
time.Sleep(1e7)
|
||||||
c1 <- "one"
|
c1 <- "one"
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(2e9)
|
time.Sleep(2e7)
|
||||||
c2 <- "two"
|
c2 <- "two"
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
44
_test/select14.go
Normal file
44
_test/select14.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
period = 100 * time.Millisecond
|
||||||
|
precision = 5 * time.Millisecond
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
counter := 0
|
||||||
|
p := time.Now()
|
||||||
|
ticker := time.NewTicker(period)
|
||||||
|
ch := make(chan int)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
select {
|
||||||
|
case t := <-ticker.C:
|
||||||
|
counter = counter + 1
|
||||||
|
ch <- counter
|
||||||
|
if d := t.Sub(p) - period; d < -precision || d > precision {
|
||||||
|
fmt.Println("wrong delay", d)
|
||||||
|
}
|
||||||
|
p = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ch <- 0
|
||||||
|
}()
|
||||||
|
for c := range ch {
|
||||||
|
if c == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
23
_test/select15.go
Normal file
23
_test/select15.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
c1 chan string
|
||||||
|
c2 chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := &T{}
|
||||||
|
t.c2 = make(chan string)
|
||||||
|
|
||||||
|
go func(c chan string) { c <- "done" }(t.c2)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case msg := <-t.c1:
|
||||||
|
println("received from c1:", msg)
|
||||||
|
case <-t.c2:
|
||||||
|
}
|
||||||
|
println("Bye")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Bye
|
||||||
11
_test/slice.go
Normal file
11
_test/slice.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := [2][2]int{{0, 1}, {2, 3}}
|
||||||
|
fmt.Println(a[0][0:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [0 1]
|
||||||
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}
|
||||||
24
_test/struct58.go
Normal file
24
_test/struct58.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type A struct {
|
||||||
|
Test string `tag:"test"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := A{}
|
||||||
|
t := reflect.TypeOf(a)
|
||||||
|
f, ok := t.FieldByName("Test")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(f.Tag.Get("tag"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// test
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import _ "github.com/containous/yaegi/_test/ct"
|
import _ "github.com/traefik/yaegi/_test/ct"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println("bye")
|
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()
|
||||||
|
}
|
||||||
20
_test/time14.go
Normal file
20
_test/time14.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var t time.Time
|
||||||
|
|
||||||
|
func f() time.Time {
|
||||||
|
time := t
|
||||||
|
return time
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(f())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0001-01-01 00:00:00 +0000 UTC
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/containous/yaegi/_test/vars"
|
import "github.com/traefik/yaegi/_test/vars"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println(vars.A)
|
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
|
||||||
@@ -1,402 +0,0 @@
|
|||||||
//go:generate go build
|
|
||||||
|
|
||||||
/*
|
|
||||||
Goexports generates wrappers of package exported symbols.
|
|
||||||
|
|
||||||
Output files are written in the current directory, and prefixed with the go version.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
goexports package...
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
goexports github.com/containous/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.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/constant"
|
|
||||||
"go/format"
|
|
||||||
"go/importer"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"math/big"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
const model = `// Code generated by 'goexports {{.PkgName}}'. DO NOT EDIT.
|
|
||||||
|
|
||||||
{{.License}}
|
|
||||||
|
|
||||||
{{if .BuildTags}}// +build {{.BuildTags}}{{end}}
|
|
||||||
|
|
||||||
package {{.Dest}}
|
|
||||||
|
|
||||||
import (
|
|
||||||
{{- range $key, $value := .Imports }}
|
|
||||||
{{- if $value}}
|
|
||||||
"{{$key}}"
|
|
||||||
{{- end}}
|
|
||||||
{{- end}}
|
|
||||||
"{{.PkgName}}"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
Symbols["{{.PkgName}}"] = map[string]reflect.Value{
|
|
||||||
{{- if .Val}}
|
|
||||||
// function, constant and variable definitions
|
|
||||||
{{range $key, $value := .Val -}}
|
|
||||||
{{- if $value.Addr -}}
|
|
||||||
"{{$key}}": reflect.ValueOf(&{{$value.Name}}).Elem(),
|
|
||||||
{{else -}}
|
|
||||||
"{{$key}}": reflect.ValueOf({{$value.Name}}),
|
|
||||||
{{end -}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{- end}}
|
|
||||||
{{- if .Typ}}
|
|
||||||
// type definitions
|
|
||||||
{{range $key, $value := .Typ -}}
|
|
||||||
"{{$key}}": reflect.ValueOf((*{{$value}})(nil)),
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{- end}}
|
|
||||||
{{- if .Wrap}}
|
|
||||||
// interface wrapper definitions
|
|
||||||
{{range $key, $value := .Wrap -}}
|
|
||||||
"_{{$key}}": reflect.ValueOf((*{{$value.Name}})(nil)),
|
|
||||||
{{end}}
|
|
||||||
{{- end}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{{range $key, $value := .Wrap -}}
|
|
||||||
// {{$value.Name}} is an interface wrapper for {{$key}} type
|
|
||||||
type {{$value.Name}} struct {
|
|
||||||
{{range $m := $value.Method -}}
|
|
||||||
W{{$m.Name}} func{{$m.Param}} {{$m.Result}}
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
{{range $m := $value.Method -}}
|
|
||||||
func (W {{$value.Name}}) {{$m.Name}}{{$m.Param}} {{$m.Result}} { {{$m.Ret}} W.W{{$m.Name}}{{$m.Arg}} }
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
`
|
|
||||||
|
|
||||||
// Val store the value name and addressable status of symbols.
|
|
||||||
type Val struct {
|
|
||||||
Name string // "package.name"
|
|
||||||
Addr bool // true if symbol is a Var
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method store information for generating interface wrapper method.
|
|
||||||
type Method struct {
|
|
||||||
Name, Param, Result, Arg, Ret string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap store information for generating interface wrapper.
|
|
||||||
type Wrap struct {
|
|
||||||
Name string
|
|
||||||
Method []Method
|
|
||||||
}
|
|
||||||
|
|
||||||
// restricted map defines symbols for which a special implementation is provided.
|
|
||||||
var restricted = map[string]bool{
|
|
||||||
"osExit": true,
|
|
||||||
"osFindProcess": true,
|
|
||||||
"logFatal": true,
|
|
||||||
"logFatalf": true,
|
|
||||||
"logFatalln": true,
|
|
||||||
"logLogger": true,
|
|
||||||
"logNew": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func genContent(dest, pkgName, license string, skip map[string]bool) ([]byte, error) {
|
|
||||||
p, err := importer.ForCompiler(token.NewFileSet(), "source", nil).Import(pkgName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix := "_" + pkgName + "_"
|
|
||||||
prefix = strings.NewReplacer("/", "_", "-", "_", ".", "_").Replace(prefix)
|
|
||||||
|
|
||||||
typ := map[string]string{}
|
|
||||||
val := map[string]Val{}
|
|
||||||
wrap := map[string]Wrap{}
|
|
||||||
imports := map[string]bool{}
|
|
||||||
sc := p.Scope()
|
|
||||||
|
|
||||||
for _, pkg := range p.Imports() {
|
|
||||||
imports[pkg.Path()] = false
|
|
||||||
}
|
|
||||||
qualify := func(pkg *types.Package) string {
|
|
||||||
if pkg.Path() != pkgName {
|
|
||||||
imports[pkg.Path()] = true
|
|
||||||
}
|
|
||||||
return pkg.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range sc.Names() {
|
|
||||||
o := sc.Lookup(name)
|
|
||||||
if !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pname := path.Base(pkgName) + "." + name
|
|
||||||
if skip[pname] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if rname := path.Base(pkgName) + name; restricted[rname] {
|
|
||||||
// Restricted symbol, locally provided by stdlib wrapper.
|
|
||||||
pname = rname
|
|
||||||
}
|
|
||||||
|
|
||||||
switch o := o.(type) {
|
|
||||||
case *types.Const:
|
|
||||||
if b, ok := o.Type().(*types.Basic); ok && (b.Info()&types.IsUntyped) != 0 {
|
|
||||||
// convert untyped constant to right type to avoid overflow
|
|
||||||
val[name] = Val{fixConst(pname, o.Val(), imports), false}
|
|
||||||
} else {
|
|
||||||
val[name] = Val{pname, false}
|
|
||||||
}
|
|
||||||
case *types.Func:
|
|
||||||
val[name] = Val{pname, false}
|
|
||||||
case *types.Var:
|
|
||||||
val[name] = Val{pname, true}
|
|
||||||
case *types.TypeName:
|
|
||||||
typ[name] = pname
|
|
||||||
if t, ok := o.Type().Underlying().(*types.Interface); ok {
|
|
||||||
var methods []Method
|
|
||||||
for i := 0; i < t.NumMethods(); i++ {
|
|
||||||
f := t.Method(i)
|
|
||||||
if !f.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sign := f.Type().(*types.Signature)
|
|
||||||
args := make([]string, sign.Params().Len())
|
|
||||||
params := make([]string, len(args))
|
|
||||||
for j := range args {
|
|
||||||
v := sign.Params().At(j)
|
|
||||||
if args[j] = v.Name(); args[j] == "" {
|
|
||||||
args[j] = fmt.Sprintf("a%d", j)
|
|
||||||
}
|
|
||||||
params[j] = args[j] + " " + types.TypeString(v.Type(), qualify)
|
|
||||||
}
|
|
||||||
arg := "(" + strings.Join(args, ", ") + ")"
|
|
||||||
param := "(" + strings.Join(params, ", ") + ")"
|
|
||||||
|
|
||||||
results := make([]string, sign.Results().Len())
|
|
||||||
for j := range results {
|
|
||||||
v := sign.Results().At(j)
|
|
||||||
results[j] = v.Name() + " " + types.TypeString(v.Type(), qualify)
|
|
||||||
}
|
|
||||||
result := "(" + strings.Join(results, ", ") + ")"
|
|
||||||
|
|
||||||
ret := ""
|
|
||||||
if sign.Results().Len() > 0 {
|
|
||||||
ret = "return"
|
|
||||||
}
|
|
||||||
|
|
||||||
methods = append(methods, Method{f.Name(), param, result, arg, ret})
|
|
||||||
}
|
|
||||||
wrap[name] = Wrap{prefix + name, methods}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buildTags string
|
|
||||||
if runtime.Version() != "devel" {
|
|
||||||
parts := strings.Split(runtime.Version(), ".")
|
|
||||||
|
|
||||||
minorRaw := getMinor(parts[1])
|
|
||||||
|
|
||||||
currentGoVersion := parts[0] + "." + minorRaw
|
|
||||||
|
|
||||||
minor, errParse := strconv.Atoi(minorRaw)
|
|
||||||
if errParse != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse version: %v", errParse)
|
|
||||||
}
|
|
||||||
|
|
||||||
nextGoVersion := parts[0] + "." + strconv.Itoa(minor+1)
|
|
||||||
|
|
||||||
buildTags = currentGoVersion + ",!" + nextGoVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
base := template.New("goexports")
|
|
||||||
parse, err := base.Parse(model)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("template parsing error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pkgName == "log/syslog" {
|
|
||||||
buildTags += ",!windows,!nacl,!plan9"
|
|
||||||
}
|
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"Dest": dest,
|
|
||||||
"Imports": imports,
|
|
||||||
"PkgName": pkgName,
|
|
||||||
"Val": val,
|
|
||||||
"Typ": typ,
|
|
||||||
"Wrap": wrap,
|
|
||||||
"BuildTags": buildTags,
|
|
||||||
"License": license,
|
|
||||||
}
|
|
||||||
err = parse.Execute(b, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("template error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
source, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to format source: %v: %s", err, b.Bytes())
|
|
||||||
}
|
|
||||||
return source, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// fixConst checks untyped constant value, converting it if necessary to avoid overflow.
|
|
||||||
func fixConst(name string, val constant.Value, imports map[string]bool) string {
|
|
||||||
var (
|
|
||||||
tok string
|
|
||||||
str string
|
|
||||||
)
|
|
||||||
switch val.Kind() {
|
|
||||||
case constant.Int:
|
|
||||||
tok = "INT"
|
|
||||||
str = val.ExactString()
|
|
||||||
case constant.Float:
|
|
||||||
v := constant.Val(val) // v is *big.Rat or *big.Float
|
|
||||||
f, ok := v.(*big.Float)
|
|
||||||
if !ok {
|
|
||||||
f = new(big.Float).SetRat(v.(*big.Rat))
|
|
||||||
}
|
|
||||||
|
|
||||||
tok = "FLOAT"
|
|
||||||
str = f.Text('g', int(f.Prec()))
|
|
||||||
case constant.Complex:
|
|
||||||
// TODO: not sure how to parse this case
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
imports["go/constant"] = true
|
|
||||||
imports["go/token"] = true
|
|
||||||
|
|
||||||
return fmt.Sprintf("constant.MakeFromLiteral(\"%s\", token.%s, 0)", str, tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// genLicense generates the correct LICENSE header text from the provided
|
|
||||||
// path to a LICENSE file.
|
|
||||||
func genLicense(fname string) (string, error) {
|
|
||||||
if fname == "" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(fname)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("could not open LICENSE file: %v", err)
|
|
||||||
}
|
|
||||||
defer func() { _ = f.Close() }()
|
|
||||||
|
|
||||||
license := new(strings.Builder)
|
|
||||||
sc := bufio.NewScanner(f)
|
|
||||||
for sc.Scan() {
|
|
||||||
txt := sc.Text()
|
|
||||||
if txt != "" {
|
|
||||||
txt = " " + txt
|
|
||||||
}
|
|
||||||
license.WriteString("//" + txt + "\n")
|
|
||||||
}
|
|
||||||
if sc.Err() != nil {
|
|
||||||
return "", fmt.Errorf("could not scan LICENSE file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return license.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
licenseFlag := flag.String("license", "", "path to a LICENSE file")
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if flag.NArg() == 0 {
|
|
||||||
flag.Usage()
|
|
||||||
log.Fatalf("missing package path")
|
|
||||||
}
|
|
||||||
|
|
||||||
license, err := genLicense(*licenseFlag)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
dest := path.Base(dir)
|
|
||||||
|
|
||||||
for _, pkg := range flag.Args() {
|
|
||||||
var oFile string
|
|
||||||
skip := map[string]bool{}
|
|
||||||
if pkg == "syscall" {
|
|
||||||
goos, arch := os.Getenv("GOOS"), os.Getenv("GOARCH")
|
|
||||||
oFile = strings.Replace(pkg, "/", "_", -1) + "_" + goos + "_" + arch + ".go"
|
|
||||||
if goos == "solaris" {
|
|
||||||
skip["syscall.RawSyscall6"] = true
|
|
||||||
skip["syscall.Syscall6"] = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oFile = strings.Replace(pkg, "/", "_", -1) + ".go"
|
|
||||||
}
|
|
||||||
|
|
||||||
content, err := genContent(dest, pkg, license, skip)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix := runtime.Version()
|
|
||||||
if runtime.Version() != "devel" {
|
|
||||||
parts := strings.Split(runtime.Version(), ".")
|
|
||||||
|
|
||||||
prefix = parts[0] + "_" + getMinor(parts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(prefix+"_"+oFile, content, 0666)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMinor(part string) string {
|
|
||||||
minor := part
|
|
||||||
index := strings.Index(minor, "beta")
|
|
||||||
if index < 0 {
|
|
||||||
index = strings.Index(minor, "rc")
|
|
||||||
}
|
|
||||||
if index > 0 {
|
|
||||||
minor = minor[:index]
|
|
||||||
}
|
|
||||||
|
|
||||||
return minor
|
|
||||||
}
|
|
||||||
123
cmd/yaegi/extract.go
Normal file
123
cmd/yaegi/extract.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/traefik/yaegi/extract"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractCmd(arg []string) error {
|
||||||
|
var licensePath string
|
||||||
|
var name string
|
||||||
|
var exclude string
|
||||||
|
var include string
|
||||||
|
|
||||||
|
eflag := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||||
|
eflag.StringVar(&licensePath, "license", "", "path to a LICENSE file")
|
||||||
|
eflag.StringVar(&name, "name", "", "the namespace for the extracted symbols")
|
||||||
|
eflag.StringVar(&exclude, "exclude", "", "comma separated list of regexp matching symbols to exclude")
|
||||||
|
eflag.StringVar(&include, "include", "", "comma separated list of regexp matching symbols to include")
|
||||||
|
eflag.Usage = func() {
|
||||||
|
fmt.Println("Usage: yaegi extract [options] packages...")
|
||||||
|
fmt.Println("Options:")
|
||||||
|
eflag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := eflag.Parse(arg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
args := eflag.Args()
|
||||||
|
if len(args) == 0 {
|
||||||
|
return fmt.Errorf("missing package")
|
||||||
|
}
|
||||||
|
|
||||||
|
license, err := genLicense(licensePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
name = path.Base(wd)
|
||||||
|
}
|
||||||
|
ext := extract.Extractor{
|
||||||
|
Dest: name,
|
||||||
|
License: license,
|
||||||
|
}
|
||||||
|
|
||||||
|
if exclude != "" {
|
||||||
|
ext.Exclude = strings.Split(exclude, ",")
|
||||||
|
}
|
||||||
|
if include != "" {
|
||||||
|
ext.Include = strings.Split(include, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
r := strings.NewReplacer("/", "-", ".", "_")
|
||||||
|
|
||||||
|
for _, pkgIdent := range args {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
importPath, err := ext.Extract(pkgIdent, name, &buf)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
oFile := r.Replace(importPath) + ".go"
|
||||||
|
f, err := os.Create(oFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(f, &buf); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// genLicense generates the correct LICENSE header text from the provided
|
||||||
|
// path to a LICENSE file.
|
||||||
|
func genLicense(fname string) (string, error) {
|
||||||
|
if fname == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(fname)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not open LICENSE file: %v", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
|
license := new(strings.Builder)
|
||||||
|
sc := bufio.NewScanner(f)
|
||||||
|
for sc.Scan() {
|
||||||
|
txt := sc.Text()
|
||||||
|
if txt != "" {
|
||||||
|
txt = " " + txt
|
||||||
|
}
|
||||||
|
license.WriteString("//" + txt + "\n")
|
||||||
|
}
|
||||||
|
if sc.Err() != nil {
|
||||||
|
return "", fmt.Errorf("could not scan LICENSE file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return license.String(), nil
|
||||||
|
}
|
||||||
47
cmd/yaegi/help.go
Normal file
47
cmd/yaegi/help.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const usage = `Yaegi is a Go interpreter.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
yaegi [command] [arguments]
|
||||||
|
|
||||||
|
The commands are:
|
||||||
|
|
||||||
|
extract generate a wrapper file from a source package
|
||||||
|
help print usage information
|
||||||
|
run execute a Go program from source
|
||||||
|
test execute test functions in a Go package
|
||||||
|
version print version
|
||||||
|
|
||||||
|
Use "yaegi help <command>" for more information about a command.
|
||||||
|
|
||||||
|
If no command is given or if the first argument is not a command, then
|
||||||
|
the run command is assumed.
|
||||||
|
`
|
||||||
|
|
||||||
|
func help(arg []string) error {
|
||||||
|
var cmd string
|
||||||
|
if len(arg) > 0 {
|
||||||
|
cmd = arg[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cmd {
|
||||||
|
case Extract:
|
||||||
|
return extractCmd([]string{"-h"})
|
||||||
|
case Help, "", "-h", "--help":
|
||||||
|
fmt.Print(usage)
|
||||||
|
return nil
|
||||||
|
case Run:
|
||||||
|
return run([]string{"-h"})
|
||||||
|
case Test:
|
||||||
|
return test([]string{"-h"})
|
||||||
|
case Version:
|
||||||
|
fmt.Println("Usage: yaegi version")
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("help: invalid yaegi command: %v", cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
135
cmd/yaegi/run.go
Normal file
135
cmd/yaegi/run.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/build"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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 {
|
||||||
|
var interactive bool
|
||||||
|
var tags string
|
||||||
|
var cmd string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// The following flags are initialized from environment.
|
||||||
|
useSyscall, _ := strconv.ParseBool(os.Getenv("YAEGI_SYSCALL"))
|
||||||
|
useUnrestricted, _ := strconv.ParseBool(os.Getenv("YAEGI_UNRESTRICTED"))
|
||||||
|
useUnsafe, _ := strconv.ParseBool(os.Getenv("YAEGI_UNSAFE"))
|
||||||
|
|
||||||
|
rflag := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||||
|
rflag.BoolVar(&interactive, "i", false, "start an interactive REPL")
|
||||||
|
rflag.BoolVar(&useSyscall, "syscall", useSyscall, "include syscall symbols")
|
||||||
|
rflag.BoolVar(&useUnrestricted, "unrestricted", useUnrestricted, "include unrestricted symbols")
|
||||||
|
rflag.StringVar(&tags, "tags", "", "set a list of build tags")
|
||||||
|
rflag.BoolVar(&useUnsafe, "unsafe", useUnsafe, "include unsafe symbols")
|
||||||
|
rflag.StringVar(&cmd, "e", "", "set the command to be executed (instead of script or/and shell)")
|
||||||
|
rflag.Usage = func() {
|
||||||
|
fmt.Println("Usage: yaegi run [options] [path] [args]")
|
||||||
|
fmt.Println("Options:")
|
||||||
|
rflag.PrintDefaults()
|
||||||
|
}
|
||||||
|
if err = rflag.Parse(arg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
args := rflag.Args()
|
||||||
|
|
||||||
|
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)
|
||||||
|
// Using a environment var allows a nested interpreter to import the syscall package.
|
||||||
|
if err := os.Setenv("YAEGI_SYSCALL", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if useUnsafe {
|
||||||
|
i.Use(unsafe.Symbols)
|
||||||
|
if err := os.Setenv("YAEGI_UNSAFE", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if useUnrestricted {
|
||||||
|
// Use of unrestricted symbols should always follow stdlib and syscall symbols, to update them.
|
||||||
|
i.Use(unrestricted.Symbols)
|
||||||
|
if err := os.Setenv("YAEGI_UNRESTRICTED", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd != "" {
|
||||||
|
_, err = i.Eval(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) == 0 {
|
||||||
|
if interactive || cmd == "" {
|
||||||
|
showError(err)
|
||||||
|
_, err = i.REPL()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip first os arg to set command line as expected by interpreted main
|
||||||
|
path := args[0]
|
||||||
|
os.Args = arg
|
||||||
|
flag.CommandLine = flag.NewFlagSet(path, flag.ExitOnError)
|
||||||
|
|
||||||
|
if isFile(path) {
|
||||||
|
err = runFile(i, path)
|
||||||
|
} else {
|
||||||
|
_, err = i.EvalPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if interactive {
|
||||||
|
_, err = i.REPL()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFile(path string) bool {
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
return err == nil && fi.Mode().IsRegular()
|
||||||
|
}
|
||||||
|
|
||||||
|
func runFile(i *interp.Interpreter, path string) error {
|
||||||
|
b, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s := string(b); strings.HasPrefix(s, "#!") {
|
||||||
|
// Allow executable go scripts, Have the same behavior as in interactive mode.
|
||||||
|
s = strings.Replace(s, "#!", "//", 1)
|
||||||
|
_, 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
149
cmd/yaegi/test.go
Normal file
149
cmd/yaegi/test.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/build"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"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
|
||||||
|
timeout string
|
||||||
|
verbose bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following flags are initialized from environment.
|
||||||
|
useSyscall, _ := strconv.ParseBool(os.Getenv("YAEGI_SYSCALL"))
|
||||||
|
useUnrestricted, _ := strconv.ParseBool(os.Getenv("YAEGI_UNRESTRICTED"))
|
||||||
|
useUnsafe, _ := strconv.ParseBool(os.Getenv("YAEGI_UNSAFE"))
|
||||||
|
|
||||||
|
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", useUnrestricted, "Include unrestricted symbols.")
|
||||||
|
tflag.BoolVar(&useUnsafe, "unsafe", useUnsafe, "Include usafe symbols.")
|
||||||
|
tflag.BoolVar(&useSyscall, "syscall", useSyscall, "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)
|
||||||
|
// Using a environment var allows a nested interpreter to import the syscall package.
|
||||||
|
if err := os.Setenv("YAEGI_SYSCALL", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if useUnrestricted {
|
||||||
|
i.Use(unrestricted.Symbols)
|
||||||
|
if err := os.Setenv("YAEGI_UNRESTRICTED", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if useUnsafe {
|
||||||
|
i.Use(unsafe.Symbols)
|
||||||
|
if err := os.Setenv("YAEGI_UNSAFE", "1"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = i.EvalTest(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarks := []testing.InternalBenchmark{}
|
||||||
|
tests := []testing.InternalTest{}
|
||||||
|
syms, ok := i.Symbols(path)[path]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("No tests found")
|
||||||
|
}
|
||||||
|
for name, sym := range syms {
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -71,7 +71,16 @@ Options:
|
|||||||
-unsafe
|
-unsafe
|
||||||
include unsafe symbols.
|
include unsafe symbols.
|
||||||
|
|
||||||
Debugging support (may be removed at any time):
|
Environment variables:
|
||||||
|
YAEGI_SYSCALL=1
|
||||||
|
Include syscall symbols (same as -syscall flag).
|
||||||
|
YAEGI_UNRESTRICTED=1
|
||||||
|
Include unrestricted symbols (same as -unrestricted flag).
|
||||||
|
YAEGI_UNSAFE=1
|
||||||
|
Include unsafe symbols (same as -unsafe flag).
|
||||||
|
YAEGI_PROMPT=1
|
||||||
|
Force enable the printing of the REPL prompt and the result of last instruction,
|
||||||
|
even if stdin is not a terminal.
|
||||||
YAEGI_AST_DOT=1
|
YAEGI_AST_DOT=1
|
||||||
Generate and display graphviz dot of AST with dotty(1)
|
Generate and display graphviz dot of AST with dotty(1)
|
||||||
YAEGI_CFG_DOT=1
|
YAEGI_CFG_DOT=1
|
||||||
@@ -85,94 +94,62 @@ Debugging support (may be removed at any time):
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containous/yaegi/interp"
|
"github.com/traefik/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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Extract = "extract"
|
||||||
|
Help = "help"
|
||||||
|
Run = "run"
|
||||||
|
Test = "test"
|
||||||
|
Version = "version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var version = "devel" // This may be overwritten at build time.
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var interactive bool
|
|
||||||
var useSyscall bool
|
|
||||||
var useUnrestricted bool
|
|
||||||
var useUnsafe bool
|
|
||||||
var tags string
|
|
||||||
var cmd string
|
var cmd string
|
||||||
flag.BoolVar(&interactive, "i", false, "start an interactive REPL")
|
var err error
|
||||||
flag.BoolVar(&useSyscall, "syscall", false, "include syscall symbols")
|
var exitCode int
|
||||||
flag.BoolVar(&useUnrestricted, "unrestricted", false, "include unrestricted symbols")
|
|
||||||
flag.StringVar(&tags, "tags", "", "set a list of build tags")
|
|
||||||
flag.BoolVar(&useUnsafe, "unsafe", false, "include usafe symbols")
|
|
||||||
flag.StringVar(&cmd, "e", "", "set the command to be executed (instead of script or/and shell)")
|
|
||||||
flag.Usage = func() {
|
|
||||||
fmt.Println("Usage:", os.Args[0], "[options] [script] [args]")
|
|
||||||
fmt.Println("Options:")
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
flag.Parse()
|
|
||||||
args := flag.Args()
|
|
||||||
log.SetFlags(log.Lshortfile)
|
|
||||||
|
|
||||||
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, BuildTags: strings.Split(tags, ",")})
|
log.SetFlags(log.Lshortfile) // Ease debugging.
|
||||||
i.Use(stdlib.Symbols)
|
|
||||||
i.Use(interp.Symbols)
|
if len(os.Args) > 1 {
|
||||||
if useSyscall {
|
cmd = os.Args[1]
|
||||||
i.Use(syscall.Symbols)
|
|
||||||
}
|
|
||||||
if useUnsafe {
|
|
||||||
i.Use(unsafe.Symbols)
|
|
||||||
}
|
|
||||||
if useUnrestricted {
|
|
||||||
// Use of unrestricted symbols should always follow use of stdlib symbols, to update them.
|
|
||||||
i.Use(unrestricted.Symbols)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd != `` {
|
switch cmd {
|
||||||
i.REPL(strings.NewReader(cmd), os.Stderr)
|
case Extract:
|
||||||
|
err = extractCmd(os.Args[2:])
|
||||||
|
case Help, "-h", "--help":
|
||||||
|
err = help(os.Args[2:])
|
||||||
|
case Run:
|
||||||
|
err = run(os.Args[2:])
|
||||||
|
case Test:
|
||||||
|
err = test(os.Args[2:])
|
||||||
|
case Version:
|
||||||
|
fmt.Println(version)
|
||||||
|
default:
|
||||||
|
// If no command is given, fallback to default "run" command.
|
||||||
|
// This allows scripts starting with "#!/usr/bin/env yaegi",
|
||||||
|
// as passing more than 1 argument to #! executable may be not supported
|
||||||
|
// on all platforms.
|
||||||
|
cmd = Run
|
||||||
|
err = run(os.Args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if err != nil && !errors.Is(err, flag.ErrHelp) {
|
||||||
if interactive || cmd == `` {
|
fmt.Fprintln(os.Stderr, fmt.Errorf("%s: %w", cmd, err))
|
||||||
i.REPL(os.Stdin, os.Stdout)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip first os arg to set command line as expected by interpreted main
|
|
||||||
os.Args = os.Args[1:]
|
|
||||||
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(args[0])
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Could not read file: ", args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = args[0]
|
|
||||||
_, err := i.Eval(s)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
if p, ok := err.(interp.Panic); ok {
|
if p, ok := err.(interp.Panic); ok {
|
||||||
fmt.Println(string(p.Stack))
|
fmt.Fprintln(os.Stderr, string(p.Stack))
|
||||||
}
|
}
|
||||||
|
exitCode = 1
|
||||||
}
|
}
|
||||||
}
|
os.Exit(exitCode)
|
||||||
|
|
||||||
if interactive {
|
|
||||||
i.REPL(os.Stdin, os.Stdout)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user