Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
373e3204b4 | ||
|
|
5f41fcb8bc | ||
|
|
43b8594c82 | ||
|
|
4c877cc348 | ||
|
|
f199520048 | ||
|
|
4df03252f6 | ||
|
|
2dfede3b90 | ||
|
|
6191f5d38a | ||
|
|
24db786bb6 |
70
README.md
70
README.md
@@ -4,6 +4,7 @@
|
||||
|
||||
[](https://github.com/containous/yaegi/releases)
|
||||
[](https://travis-ci.com/containous/yaegi)
|
||||
[](https://godoc.org/github.com/containous/yaegi)
|
||||
|
||||
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.
|
||||
@@ -11,22 +12,22 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
|
||||
## Features
|
||||
|
||||
* Complete support of [Go specification][specs]
|
||||
* In pure Go, using only standard library
|
||||
* Written in pure Go, using only the standard library
|
||||
* Simple interpreter API: `New()`, `Eval()`, `Use()`
|
||||
* works everywhere Go works
|
||||
* Works everywhere Go works
|
||||
* All Go & runtime resources accessible from script (with control)
|
||||
* Security: `unsafe` and `syscall` packages not used or exported by default
|
||||
* Security: `unsafe` and `syscall` packages neither used nor exported by default
|
||||
* Support Go 1.11 and Go 1.12 (the latest 2 major releases)
|
||||
|
||||
## Install
|
||||
|
||||
### As library
|
||||
### Go package
|
||||
|
||||
```go
|
||||
import "github.com/containous/yaegi/interp"
|
||||
```
|
||||
|
||||
### REPL
|
||||
### Command-line executable
|
||||
|
||||
```bash
|
||||
go get -u github.com/containous/yaegi/cmd/yaegi
|
||||
@@ -37,27 +38,6 @@ and alias the `yaegi` command in `alias yaegi='rlwrap yaegi'` in your `~/.bashrc
|
||||
|
||||
## Usage
|
||||
|
||||
### As a command line interpreter
|
||||
|
||||
The Yaegi command can run an interactive Read-Eval-Print-Loop:
|
||||
|
||||
```console
|
||||
$ yaegi
|
||||
> 1 + 2
|
||||
3
|
||||
> import "fmt"
|
||||
> fmt.Println("Hello World")
|
||||
Hello World
|
||||
>
|
||||
```
|
||||
|
||||
Or interpret Go files:
|
||||
|
||||
```console
|
||||
$ yaegi cmd/yaegi/yaegi.go
|
||||
>
|
||||
```
|
||||
|
||||
### As an embedded interpreter
|
||||
|
||||
Create an interpreter with `New()`, run Go code with `Eval()`:
|
||||
@@ -80,13 +60,15 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = i.Eval(`fmt.Println("hello")`)
|
||||
_, err = i.Eval(`fmt.Println("Hello Yaegi")`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[Go Playground](https://play.golang.org/p/zzvw4VlerLP)
|
||||
|
||||
### As a dynamic extension framework
|
||||
|
||||
The following program is compiled ahead of time, except `bar()` which is interpreted, with the following steps:
|
||||
@@ -123,10 +105,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
[Go Playground](https://play.golang.org/p/6SEAoaO7n0U)
|
||||
|
||||
### As a command-line interpreter
|
||||
|
||||
The Yaegi command can run an interactive Read-Eval-Print-Loop:
|
||||
|
||||
```console
|
||||
$ yaegi
|
||||
> 1 + 2
|
||||
3
|
||||
> import "fmt"
|
||||
> fmt.Println("Hello World")
|
||||
Hello World
|
||||
>
|
||||
```
|
||||
|
||||
Or interpret Go files:
|
||||
|
||||
```console
|
||||
$ yaegi cmd/yaegi/yaegi.go
|
||||
>
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation about Yaegi commands and libraries can be found at usual [godoc.org][docs].
|
||||
|
||||
## Limitations
|
||||
|
||||
Beside the known [bugs] which are supposed to be fixed in the short term, there are some limitations not planned to be addressed soon:
|
||||
|
||||
- assembly files (`.s`) are not supported
|
||||
- calling C code is not supported (no virtual "C" package)
|
||||
- interfaces to be used from the pre-compiled code can not be added dynamically, as it is required to pre-compile interface wrappers
|
||||
- representation of types by `reflect` and printing values using %T may give different results between compiled mode and interpreted mode
|
||||
- interpreting computation intensive code is likely to remain significantly slower than in compiled mode
|
||||
|
||||
## Contributing
|
||||
|
||||
Yaegi is an open source project, and your feedback and contributions are needed and always welcome.
|
||||
@@ -143,3 +158,4 @@ Yaegi is an open source project, and your feedback and contributions are needed
|
||||
[github]: https://github.com/containous/yaegi
|
||||
[Issues]: https://github.com/containous/yaegi/issues
|
||||
[pull requests]: https://github.com/containous/yaegi/issues
|
||||
[bugs]: https://github.com/containous/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug
|
||||
|
||||
18
_test/interface9.go
Normal file
18
_test/interface9.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Int int
|
||||
|
||||
func (I Int) String() string {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
func main() {
|
||||
var i Int
|
||||
var st fmt.Stringer = i
|
||||
fmt.Println(st.String())
|
||||
}
|
||||
|
||||
// Output:
|
||||
// foo
|
||||
@@ -1,8 +1,21 @@
|
||||
//go:generate go build
|
||||
|
||||
// This program generates code to register binary program symbols to the interpreter.
|
||||
// See stdlib.go for usage
|
||||
/*
|
||||
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 (
|
||||
@@ -22,8 +35,8 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const model = `// +build {{.CurrentGoVersion}},!{{.NextGoVersion}}
|
||||
|
||||
const model = `// +build {{.BuildTags}}
|
||||
|
||||
package {{.Dest}}
|
||||
|
||||
// Code generated by 'goexports {{.PkgName}}'. DO NOT EDIT.
|
||||
@@ -120,6 +133,7 @@ func genContent(dest, pkgName string) ([]byte, error) {
|
||||
if !o.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
pname := path.Base(pkgName) + "." + name
|
||||
switch o := o.(type) {
|
||||
case *types.Const:
|
||||
@@ -137,11 +151,12 @@ func genContent(dest, pkgName string) ([]byte, error) {
|
||||
if !f.Exported() {
|
||||
continue
|
||||
}
|
||||
sig := f.Type().(*types.Signature)
|
||||
args := make([]string, sig.Params().Len())
|
||||
|
||||
sign := f.Type().(*types.Signature)
|
||||
args := make([]string, sign.Params().Len())
|
||||
params := make([]string, len(args))
|
||||
for j := range args {
|
||||
v := sig.Params().At(j)
|
||||
v := sign.Params().At(j)
|
||||
if args[j] = v.Name(); args[j] == "" {
|
||||
args[j] = fmt.Sprintf("a%d", j)
|
||||
}
|
||||
@@ -149,16 +164,19 @@ func genContent(dest, pkgName string) ([]byte, error) {
|
||||
}
|
||||
arg := "(" + strings.Join(args, ", ") + ")"
|
||||
param := "(" + strings.Join(params, ", ") + ")"
|
||||
results := make([]string, sig.Results().Len())
|
||||
|
||||
results := make([]string, sign.Results().Len())
|
||||
for j := range results {
|
||||
v := sig.Results().At(j)
|
||||
v := sign.Results().At(j)
|
||||
results[j] = v.Name() + " " + types.TypeString(v.Type(), qualify)
|
||||
}
|
||||
result := "(" + strings.Join(results, ", ") + ")"
|
||||
|
||||
ret := ""
|
||||
if sig.Results().Len() > 0 {
|
||||
if sign.Results().Len() > 0 {
|
||||
ret = "return"
|
||||
}
|
||||
|
||||
methods = append(methods, Method{f.Name(), param, result, arg, ret})
|
||||
}
|
||||
wrap[name] = Wrap{prefix + name, methods}
|
||||
@@ -181,16 +199,20 @@ func genContent(dest, pkgName string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("template parsing error: %v", err)
|
||||
}
|
||||
|
||||
buildTags := currentGoVersion + ",!" + nextGoVersion
|
||||
if pkgName == "log/syslog" {
|
||||
buildTags += ",!windows,!nacl,!plan9"
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
data := map[string]interface{}{
|
||||
"Dest": dest,
|
||||
"Imports": imports,
|
||||
"PkgName": pkgName,
|
||||
"Val": val,
|
||||
"Typ": typ,
|
||||
"Wrap": wrap,
|
||||
"CurrentGoVersion": currentGoVersion,
|
||||
"NextGoVersion": nextGoVersion,
|
||||
"Dest": dest,
|
||||
"Imports": imports,
|
||||
"PkgName": pkgName,
|
||||
"Val": val,
|
||||
"Typ": typ,
|
||||
"Wrap": wrap,
|
||||
"BuildTags": buildTags,
|
||||
}
|
||||
err = parse.Execute(b, data)
|
||||
if err != nil {
|
||||
|
||||
@@ -223,6 +223,8 @@ func assign(n *node) {
|
||||
switch {
|
||||
case dest.typ.cat == interfaceT:
|
||||
svalue[i] = genValueInterface(src)
|
||||
case dest.typ.cat == valueT && dest.typ.rtype.Kind() == reflect.Interface:
|
||||
svalue[i] = genInterfaceWrapper(src, dest.typ.rtype)
|
||||
case dest.typ.cat == valueT && src.typ.cat == funcT:
|
||||
svalue[i] = genFunctionWrapper(src)
|
||||
case src.kind == basicLit && src.val == nil:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build go1.11,!go1.12
|
||||
// +build go1.11,!go1.12,!windows,!nacl,!plan9
|
||||
|
||||
package stdlib
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build go1.12,!go1.13
|
||||
// +build go1.12,!go1.13,!windows,!nacl,!plan9
|
||||
|
||||
package stdlib
|
||||
|
||||
|
||||
Reference in New Issue
Block a user