Yaegi is Another Elegant Go Interpreter

Overview

Yaegi

release Build Status GoDoc Discourse status

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.

Features

  • Complete support of Go specification
  • Written in pure Go, using only the standard library
  • Simple interpreter API: New(), Eval(), Use()
  • Works everywhere Go works
  • All Go & runtime resources accessible from script (with control)
  • Security: unsafe and syscall packages neither used nor exported by default
  • Support Go 1.13 and Go 1.14 (the latest 2 major releases)

Install

Go package

import "github.com/traefik/yaegi/interp"

Command-line executable

go get -u github.com/traefik/yaegi/cmd/yaegi

Note that you can use rlwrap (install with your favorite package manager), and alias the yaegi command in alias yaegi='rlwrap yaegi' in your ~/.bashrc, to have history and command line edition.

CI Integration

curl -sfL https://raw.githubusercontent.com/traefik/yaegi/master/install.sh | bash -s -- -b $GOPATH/bin v0.9.0

Usage

As an embedded interpreter

Create an interpreter with New(), run Go code with Eval():

package main

import (
	"github.com/traefik/yaegi/interp"
	"github.com/traefik/yaegi/stdlib"
)

func main() {
	i := interp.New(interp.Options{})

	i.Use(stdlib.Symbols)

	_, err := i.Eval(`import "fmt"`)
	if err != nil {
		panic(err)
	}

	_, err = i.Eval(`fmt.Println("Hello Yaegi")`)
	if err != nil {
		panic(err)
	}
}

Go Playground

As a dynamic extension framework

The following program is compiled ahead of time, except bar() which is interpreted, with the following steps:

  1. use of i.Eval(src) to evaluate the script in the context of interpreter
  2. use of v, err := i.Eval("foo.Bar") to get the symbol from the interpreter context, as a reflect.Value
  3. application of Interface() method and type assertion to convert v into bar, as if it was compiled
package main

import "github.com/traefik/yaegi/interp"

const src = `package foo
func Bar(s string) string { return s + "-Foo" }`

func main() {
	i := interp.New(interp.Options{})

	_, err := i.Eval(src)
	if err != nil {
		panic(err)
	}

	v, err := i.Eval("foo.Bar")
	if err != nil {
		panic(err)
	}

	bar := v.Interface().(func(string) string)

	r := bar("Kung")
	println(r)
}

Go Playground

As a command-line interpreter

The Yaegi command can run an interactive Read-Eval-Print-Loop:

$ yaegi
> 1 + 2
3
> import "fmt"
> fmt.Println("Hello World")
Hello World
>

Note that in interactive mode, all stdlib package are pre-imported, you can use them directly:

$ 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:

$ yaegi -syscall -unsafe -unrestricted github.com/traefik/yaegi/cmd/yaegi
>

Or for Go scripting in the shebang line:

$ cat /tmp/test
#!/usr/bin/env yaegi
package main

import "fmt"

func main() {
	fmt.Println("test")
}
$ ls -la /tmp/test
-rwxr-xr-x 1 dow184 dow184 93 Jan  6 13:38 /tmp/test
$ /tmp/test
test

Documentation

Documentation about Yaegi commands and libraries can be found at usual godoc.org.

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

Contributing guide.

License

Apache 2.0.

Issues
  • Discussion: Interactive debugger interface

    Discussion: Interactive debugger interface

    Proposal

    Discuss introducing a mechanism for interactively debugging Yaegi scripts. For example, some script.go, I want some interface parallel to interp.EvalPath("script.go") that provides a way to step through the Go statements in script.go.

    I am happy to develop the debugger myself, as part of this repo, or another traefik project, or a completely separate project. I would do this as a Debug Adapter Protocol implementation.

    Background

    I created the Go Notebook Kernel extension for Visual Studio Code. I would like to add the capability to debug Go notebook cells. Since the notebook kernel is driven by Yaegi, this would require interfaces for debugging Interpreter.Eval, so that I could implement a debug adapter for it. I have previously developed the VSCode Byebug Debugger, which relies on my implementation of the debug adapter protocol for Byebug.

    Workarounds

    N/A. Other than debugging Yaegi itself, there's no way to debug a Yaegi script.

    proposal 
    opened by firelizzard18 21
  • use built in golang tooling to resolve imports

    use built in golang tooling to resolve imports

    fixes #422 but using the golang toolings builtin path resolution instead of the logic in pkgDir. could use a once over in a old style gopath environment not 100% sure on using "." for the srcDir within the yaegi context.

    when yaegi interpreter is running in a go module environment pkgDir cannot locate packages modules because they are not located anywhere in the gopath.

    opened by james-lawrence 12
  • interp: produce meaningful output for file statements

    interp: produce meaningful output for file statements

    This MR modifies interp.eval to produce meaningful result values for file statements. Currently, the return value of interp.eval for file-like input is effectively new(interface{}) (as a reflect.Value). With these changes, interp.eval for file-like input will return meaningful values.

    • At the top level, a file-like input will produce a struct with an array of statement results
    • Import specs will produce a struct with the import path, and name if specified
    • Top-level function declarations will produce a struct with the function name
    • Top-level type declarations will produce a struct with the type name

    Variable and constant declarations do not currently produce any result.

    Motivation

    I am working on a notebook extension for Visual Studio Code, powered by Yaegi. This MR is a step towards enabling me to improve the user experience. Specifically, I want to be able to intelligently detect whether the user expects the evaluation result to be displayed. If the input is file-like, I will assume that the user does not wish to inspect/display some value. For my purposes, it doesn't matter exactly what result file-like inputs produce (as long as I can detect it), so I chose to implement something simple that could be extended in the future.

    enhancement contributor/waiting-for-corrections status/1-needs-design-review area/core proposal 
    opened by firelizzard18 11
  • `mismatched types gioui.org/ui.pc and .` when importing Gio package

    `mismatched types gioui.org/ui.pc and .` when importing Gio package

    Possibly related to #90 or #308.

    I am trying to run the Gio "hello, world" program from within Yaegi. (Toplevel here.) Yaegi throws an error on this line:

    func (r *OpsReader) Decode() (EncodedOp, bool) {
    	if r.ops == nil {
    		return EncodedOp{}, false
    	}
    	for {
    		if len(r.stack) > 0 {
    			b := r.stack[len(r.stack)-1]
    			if r.pc == b.endPC {
    			// ^^^ error here
    			// /path/to/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .
    

    As indicated, the error is mismatched types gioui.org/ui.pc and . .

    So first of all, the error message appears to be truncated. And second of all, r.pc and b.endPC are the same type.

    If I try to import the package multiple times, it fails twice, then succeeds, and then panics:

    % rlwrap yaegi
    > import    "gioui.org/ui"
    /Users/lmc/src/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .
    > import    "gioui.org/ui"
    /Users/lmc/src/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .
    > import    "gioui.org/ui"
    0xc0000a14e0
    > import    "gioui.org/ui"
    /Users/lmc/src/gioui.org/ui/internal/ops/ops.go:6:7: panic
    panic: reflect.Set: value of type int is not assignable to type uint8 [recovered]
    	panic: reflect.Set: value of type int is not assignable to type uint8
    
    bug area/core 
    opened by theclapp 11
  • Review current test cases

    Review current test cases

    https://github.com/containous/dyngo/commit/a316f40ca7b6da6268f1c3c76b4e13097f28f6bc

    • [ ] chan6.go ?
    Got: "123 false\n"
    want: "123 true\n"
    
    • [ ] select1.go ?
    Got:  "start for\nreceived one\nfinish 1\nend for\nstart for\nreceived #2  false\nend for\nBye\n",
    want: "start for\nreceived one\nfinish 1\nend for\nstart for\nreceived #2 two true\nend for\nBye\n"
    
    • [ ] ret1.go
    Got: "<nil>\n"
    want: "5\n"
    
    • [x] run0.go
    # command-line-arguments
    ../_test/run11.go:4:11: multiple-value f() in single-value context
        
    exit status 2
    
    • [x] run11.go
    # command-line-arguments
    ../_test/run11.go:4:11: multiple-value f() in single-value context
        
    exit status 2
    
    • [ ] time3.go
    Got: "20\n"
    want: "20 24 43\n"
    
    • [ ] type5.go
    Got: "int\n"
    want: "main.T\n"
    
    • [ ] type6.go
    Got: "int\n"
    want: "main.T\n"
    
    opened by ldez 10
  • PkgPath contains vendor path prefix

    PkgPath contains vendor path prefix

    PkgPath can contain the vendor path prefix when using vendored dependencies in a traefik plugin.

    equals then tries to compare an id with the prefix with one without it:

    "*github.com/rsteube/traefik-plugin-brotli/vendor/github.com/andybalholm/brotli.encoderDictionary" == "`*github.com/andybalholm/brotli.encoderDictionary"
    

    The following triggers an unexpected error:

    # hash.go
    type hasherCommon struct {
    	params           hasherParams
    	is_prepared_     bool
    	dict_num_lookups uint
    	dict_num_matches uint
    }
    
    type hasherHandle interface {
    	Common() *hasherCommon
    	Initialize(params *encoderParams)
    	Prepare(one_shot bool, input_size uint, data []byte)
    	StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint)
    	HashTypeLength() uint
    	StoreLookahead() uint
    	PrepareDistanceCache(distance_cache []int)
    	FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult)
    	StoreRange(data []byte, mask uint, ix_start uint, ix_end uint)
    	Store(data []byte, mask uint, ix uint)
    }
    
    # h10.go
    type h10 struct {
    	hasherCommon
    	window_mask_ uint
    	buckets_     [1 << 17]uint32
    	invalid_pos_ uint32
    	forest       []uint32
    }
    
    func (*h10) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) {
    	panic("unimplemented")
    }
    
    
    # encode.go -  where the error occurs
    createZopfliBackwardReferences(uint(bytes), uint(wrapped_last_processed_pos), data, uint(mask), &s.params, s.hasher_.(*h10), s.dist_cache_[:], &s.last_insert_len_, &s.commands, &s.num_literals_)
    
    

    Expected result:

    executes without error
    

    Got:

    /plugins/go/src/github.com/rsteube/traefik-plugin-brotli/vendor/github.com/andybalholm/brotli/encode.go:812:110:
    impossible type assertion: *github.com/andybalholm/brotli.h10
    does not implement github.com/rsteube/traefik-plugin-brotli/vendor/github.com/andybalholm/brotli.hasherHandle
    

    To fix this the prefix might be removed from PkgPath as others have done.

    see also https://github.com/golang/go/issues/12739

    opened by rsteube 9
  • Failing tests on Arch Linux with yaegi 0.7.6-1

    Failing tests on Arch Linux with yaegi 0.7.6-1

    Hi, I am the yaegi package maintainer for Arch Linux. When I do go test ./... I get failing checks for yaegi 0.7.6-1 on Arch Linux in a systemd-nspawn container:

    ?   	github.com/containous/yaegi	[no test files]
    ?   	github.com/containous/yaegi/cmd/goexports	[no test files]
    --- FAIL: TestYaegiCmdCancel (9.91s)
        yaegi_test.go:67: failed to probe race: write |1: broken pipe
        yaegi_test.go:82: error running yaegi command for "for {}\n": exit status 2
        yaegi_test.go:67: failed to probe race: write |1: broken pipe
        yaegi_test.go:82: error running yaegi command for "select {}\n": exit status 2
    FAIL
    FAIL	github.com/containous/yaegi/cmd/yaegi	9.925s
    ok  	github.com/containous/yaegi/example/closure	0.014s
    ok  	github.com/containous/yaegi/example/getfunc	0.016s
    ok  	github.com/containous/yaegi/example/pkg	0.024s
    ?   	github.com/containous/yaegi/internal/genop	[no test files]
    --- FAIL: TestInterpConsistencyBuild (187.04s)
        --- FAIL: TestInterpConsistencyBuild/composite6.go (0.00s)
            interp_consistent_test.go:92: ../_test/composite6.go:6:2: import "github.com/containous/yaegi/_test/ct1" error: unable to find source related to: "github.com/containous/yaegi/_test/ct1"
        --- FAIL: TestInterpConsistencyBuild/import3.go (0.00s)
            interp_consistent_test.go:92: ../_test/import3.go:3:8: import "github.com/containous/yaegi/_test/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/foo"
        --- FAIL: TestInterpConsistencyBuild/import4.go (0.00s)
            interp_consistent_test.go:92: ../_test/import4.go:3:8: import "github.com/containous/yaegi/_test/p1" error: unable to find source related to: "github.com/containous/yaegi/_test/p1"
        --- FAIL: TestInterpConsistencyBuild/import5.go (0.00s)
            interp_consistent_test.go:92: ../_test/import5.go:3:8: import "github.com/containous/yaegi/_test/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/foo"
        --- FAIL: TestInterpConsistencyBuild/import7.go (0.00s)
            interp_consistent_test.go:92: ../_test/import7.go:3:8: import "github.com/containous/yaegi/_test/foo-bar" error: unable to find source related to: "github.com/containous/yaegi/_test/foo-bar"
        --- FAIL: TestInterpConsistencyBuild/import8.go (0.00s)
            interp_consistent_test.go:92: ../_test/import8.go:3:8: import "github.com/containous/yaegi/_test/b1/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/b1/foo"
        --- FAIL: TestInterpConsistencyBuild/tag0.go (0.00s)
            interp_consistent_test.go:92: ../_test/tag0.go:6:8: import "github.com/containous/yaegi/_test/ct" error: unable to find source related to: "github.com/containous/yaegi/_test/ct"
    --- FAIL: TestInterpErrorConsistency (0.62s)
        --- FAIL: TestInterpErrorConsistency/import6.go (0.03s)
            interp_consistent_test.go:210: got "../_test/import6.go:3:8: import \"github.com/containous/yaegi/_test/c1\" error: unable to find source related to: \"github.com/containous/yaegi/_test/c1\"", want: "import cycle not allowed"
    Hello
    In Hi:
    hello from Myint 4
    --- FAIL: TestFile (2.16s)
        --- FAIL: TestFile/composite6.go (0.00s)
            interp_file_test.go:72: ../_test/composite6.go:6:2: import "github.com/containous/yaegi/_test/ct1" error: unable to find source related to: "github.com/containous/yaegi/_test/ct1"
        --- FAIL: TestFile/import3.go (0.00s)
            interp_file_test.go:72: ../_test/import3.go:3:8: import "github.com/containous/yaegi/_test/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/foo"
        --- FAIL: TestFile/import4.go (0.00s)
            interp_file_test.go:72: ../_test/import4.go:3:8: import "github.com/containous/yaegi/_test/p1" error: unable to find source related to: "github.com/containous/yaegi/_test/p1"
        --- FAIL: TestFile/import5.go (0.00s)
            interp_file_test.go:72: ../_test/import5.go:3:8: import "github.com/containous/yaegi/_test/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/foo"
        --- FAIL: TestFile/import6.go (0.00s)
            interp_file_test.go:66: got "../_test/import6.go:3:8: import \"github.com/containous/yaegi/_test/c1\" error: unable to find source related to: \"github.com/containous/yaegi/_test/c1\"", want: "import cycle not allowed\n\timports github.com/containous/yaegi/_test/c1"
        --- FAIL: TestFile/import7.go (0.00s)
            interp_file_test.go:72: ../_test/import7.go:3:8: import "github.com/containous/yaegi/_test/foo-bar" error: unable to find source related to: "github.com/containous/yaegi/_test/foo-bar"
        --- FAIL: TestFile/import8.go (0.00s)
            interp_file_test.go:72: ../_test/import8.go:3:8: import "github.com/containous/yaegi/_test/b1/foo" error: unable to find source related to: "github.com/containous/yaegi/_test/b1/foo"
        --- FAIL: TestFile/tag0.go (0.00s)
            interp_file_test.go:72: ../_test/tag0.go:6:8: import "github.com/containous/yaegi/_test/ct" error: unable to find source related to: "github.com/containous/yaegi/_test/ct"
    FAIL
    FAIL	github.com/containous/yaegi/interp	190.556s
    ?   	github.com/containous/yaegi/stdlib	[no test files]
    ?   	github.com/containous/yaegi/stdlib/syscall	[no test files]
    ?   	github.com/containous/yaegi/stdlib/unsafe	[no test files]
    FAIL
    

    When I build the binary without the tests, everything works as expected. But it would be nice if we could get this tests working.

    question contributor/waiting-for-feedback 
    opened by shibumi 9
  • panic when import `golang.org/x/text`

    panic when import `golang.org/x/text`

    The following program sample.go triggers a panic:

    package main
    
    import (
    	"golang.org/x/text/language"
    	"log"
    )
    
    func main() {
    	log.Println(language.English)
    }
    
    

    Expected result:

    $ go run ./sample.go
    
    2021/06/19 21:42:46 en
    

    Got: panic run: language: tag is not well-formed Links to panic line number

    $ yaegi ./sample.go
    
    
    /Users/wlun/go/src/golang.org/x/text/internal/language/tags.go:12:3: panic
    /Users/wlun/go/src/golang.org/x/text/internal/language/compact/compact.go:59:20: panic
    run: language: tag is not well-formed
    goroutine 1 [running]:
    runtime/debug.Stack(0x1, 0xc0013c6800, 0x40)
    	/usr/local/Cellar/go/1.16.3/libexec/src/runtime/debug/stack.go:24 +0x9f
    github.com/traefik/yaegi/interp.(*Interpreter).eval.func1(0xc00223fc18)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:503 +0xc8
    panic(0x1b3a800, 0xc001a3dc20)
    	/usr/local/Cellar/go/1.16.3/libexec/src/runtime/panic.go:965 +0x1b9
    github.com/traefik/yaegi/interp.runCfg.func1(0xc001bccfd0, 0xc002052100, 0xc00223de68)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:185 +0x253
    panic(0x1b3a800, 0xc001a3dc20)
    	/usr/local/Cellar/go/1.16.3/libexec/src/runtime/panic.go:965 +0x1b9
    github.com/traefik/yaegi/interp.runCfg.func1(0xc001bcd130, 0xc001295900, 0xc00223dc58)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:185 +0x253
    panic(0x1b3a800, 0xc001a3dc20)
    	/usr/local/Cellar/go/1.16.3/libexec/src/runtime/panic.go:965 +0x1b9
    github.com/traefik/yaegi/interp._panic.func1(0xc001bcd130, 0xc0018fa550)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:838 +0x7f
    github.com/traefik/yaegi/interp.runCfg(0xc001295900, 0xc001bcd130)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:191 +0x87
    github.com/traefik/yaegi/interp.call.func7(0xc001bccfd0, 0xc0015b16c0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:1272 +0xd05
    github.com/traefik/yaegi/interp.runCfg(0xc002052100, 0xc001bccfd0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:191 +0x87
    github.com/traefik/yaegi/interp.(*Interpreter).run(0xc000366000, 0xc001ea5800, 0xc000368000)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/run.go:122 +0x2b0
    github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc000366000, 0x0, 0x0, 0xc001d0ac91, 0x2b, 0x1078e01, 0xc0004a6158, 0x8, 0x0, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:156 +0xad9
    github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc0014ffd00, 0xc00223ec48)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:222 +0x12e5
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0014ffd00, 0xc00223ec48, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:232 +0xb5
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0014fef00, 0xc00223ec48, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:236 +0x66
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0014fe800, 0xc00223ec48, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:236 +0x66
    github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc000366000, 0xc0014fe800, 0xc00011e580, 0x1a, 0xc000488041, 0x1a, 0xc001bbfc28, 0x8, 0xc0014fe800, 0x0, ...)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:20 +0x21f
    github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc000366000, 0x0, 0x0, 0xc000488041, 0x1a, 0x1, 0x16, 0xc000211300, 0xca, 0xc000212510)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:100 +0xf57
    github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc000210400, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:222 +0x12e5
    github.com/traefik/yaegi/interp.(*node).Walk(0xc000210400, 0xc00223f9b8, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:232 +0xb5
    github.com/traefik/yaegi/interp.(*node).Walk(0xc000210300, 0xc00223f9b8, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:236 +0x66
    github.com/traefik/yaegi/interp.(*node).Walk(0xc000210100, 0xc00223f9b8, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:236 +0x66
    github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc000366000, 0xc000210100, 0xc00020d9d0, 0x4, 0xc00020d9d0, 0x4, 0x10, 0xc000200240, 0x0, 0xc0002063e0, ...)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:20 +0x21f
    github.com/traefik/yaegi/interp.(*Interpreter).gtaRetry(0xc000366000, 0xc00223fb88, 0x1, 0x1, 0xc00020d9d0, 0x4, 0xc00020d9d0, 0x4)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:311 +0x12c
    github.com/traefik/yaegi/interp.(*Interpreter).eval(0xc000366000, 0xc0002c6310, 0x6e, 0x7ffeefbffb2e, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:525 +0x2a5
    github.com/traefik/yaegi/interp.(*Interpreter).EvalPath(0xc000366000, 0x7ffeefbffb2e, 0x9, 0xc0002c6200, 0x6e, 0x0, 0x0, 0xc0001b1cb0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:417 +0x105
    main.runFile(0xc000366000, 0x7ffeefbffb2e, 0x9, 0x0, 0x1, 0x0)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/cmd/yaegi/run.go:139 +0xb1
    main.run(0xc000032050, 0x1, 0x1, 0xc00000a501, 0xc000001680)
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/cmd/yaegi/run.go:102 +0x99d
    main.main()
    	/Users/wlun/go/pkg/mod/github.com/traefik/[email protected]/cmd/yaegi/yaegi.go:144 +0x415
    
    bug area/core 
    opened by WLun001 8
  • Way to check if function is accesible from yaegi?

    Way to check if function is accesible from yaegi?

    Hello, thanks for the nice project. Because the script that yaegi evaluates could be dynamic, how can we check if a function exists before using it in yaegi?

    question 
    opened by onthegit 8
  • Entering 1=1 triggers a panic

    Entering 1=1 triggers a panic

    OS: macOS 10.14.4 Commit: 2dfede3b90b40723cb2c015adb2f2ab5227825cd

    Using the repl:

    ~> yaegi
    > 1=1    
    1:28: panic
    panic: reflect: reflect.Value.Set using unaddressable value [recovered]
    	panic: reflect: reflect.Value.Set using unaddressable value
    
    goroutine 1 [running]:
    github.com/containous/yaegi/interp.runCfg.func1(0xc00018a050, 0xc000112a00)
    	/Users/max/go/src/github.com/containous/yaegi/interp/run.go:107 +0x1e9
    panic(0x17fc540, 0xc000180250)
    	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/panic.go:522 +0x1b5
    reflect.flag.mustBeAssignable(0x82)
    	/usr/local/Cellar/go/1.12.1/libexec/src/reflect/value.go:234 +0x13a
    reflect.Value.Set(0x17fb400, 0xc0000ee650, 0x82, 0x17fb400, 0xc0000ee660, 0x82)
    	/usr/local/Cellar/go/1.12.1/libexec/src/reflect/value.go:1467 +0x2f
    github.com/containous/yaegi/interp.assign.func3(0xc00018a050, 0x1945db0)
    	/Users/max/go/src/github.com/containous/yaegi/interp/run.go:256 +0xb6
    github.com/containous/yaegi/interp.runCfg(0xc000112a00, 0xc00018a050)
    	/Users/max/go/src/github.com/containous/yaegi/interp/run.go:112 +0x70
    github.com/containous/yaegi/interp.(*Interpreter).run(0xc0000ce180, 0xc000112900, 0x0)
    	/Users/max/go/src/github.com/containous/yaegi/interp/run.go:93 +0x126
    github.com/containous/yaegi/interp.(*Interpreter).Eval(0xc0000ce180, 0xc0000ee5f0, 0x6, 0xc0001c9df0, 0x5, 0x19136b5, 0x1, 0xc0000ee5f0)
    	/Users/max/go/src/github.com/containous/yaegi/interp/interp.go:277 +0x2f9
    github.com/containous/yaegi/interp.(*Interpreter).Repl(0xc0000ce180, 0xc000010010, 0xc0000d0000)
    	/Users/max/go/src/github.com/containous/yaegi/interp/interp.go:320 +0x1c3
    main.main()
    	/Users/max/go/src/github.com/containous/yaegi/cmd/yaegi/yaegi.go:85 +0x4e2
    
    bug area/cli 
    opened by maxhawkins 8
  • non-constant array bound

    non-constant array bound

    The following code should trigger "non-constant array bound xte"

    xte:=10
    ute:=[xte]byte{1,2}
    fmt.Println(ute)
    

    however it compiles and displays the result in yaegi. However leaving it as it is, could be used for creating maps with dynamic length arrays as keys.

    bug area/core 
    opened by onthegit 7
  • mismatched types error when comparing aliased types

    mismatched types error when comparing aliased types

    The following program sample.go triggers an unexpected result

    package main
    
    type Number = int
    
    func main() {
    	println(Number(1) < int(2))
    }
    

    Expected result

    $ go run ./sample.go
    true
    

    Got

    $ yaegi ./sample.go
    run: ./sample.go:6:10: invalid operation: mismatched types main.Number and int
    

    Yaegi Version

    v0.13.0

    Additional Notes

    No response

    opened by RussellLuo 0
  • feat: support type alias

    feat: support type alias

    I expect the following code to be supported.

    type TT http.Header
    
    func (t TT) Set(key, val string) {
    
    }
    
    func (t TT) Get(key string) string {
    
    }
    

    So, I pushed this PR. Do I need to add some test cases? I don't see the relevant test files ....

    opened by tttoad 1
  • Problem with go-chi/chi

    Problem with go-chi/chi

    The following program sample.go triggers an unexpected result

    package main
      
    import "github.com/go-chi/chi"
    
    func main() {
    	router := chi.NewRouter()
    	println("router:", router)
    }
    

    Expected result

    $ go run ./sample.go
    router: 0xc000129e80
    

    Got

    $ yaegi ./sample.go
    panic: reflect: call of reflect.Value.Int on uint8 Value
    
    goroutine 1 [running]:
    reflect.Value.Int(...)
    	/usr/local/go/src/reflect/value.go:1413
    github.com/traefik/yaegi/interp.nodeType2(0xc000171b00, 0xc00016c990, 0xc00070cb40, {0xc0004d3b40, 0x4, 0x8})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:433 +0x44de
    github.com/traefik/yaegi/interp.nodeType2(0xc000171b00, 0xc00016c990, 0xc0005a4b40, {0xc000525c60, 0x3, 0x4})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:902 +0x4abe
    github.com/traefik/yaegi/interp.nodeType2(0xc000171b00, 0xc00016c990, 0xc000713200, {0xc000525c60, 0x2, 0x4})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:715 +0x550e
    github.com/traefik/yaegi/interp.nodeType2(0xc000171b00, 0xc00016c990, 0xc0007130e0, {0xc000502f90, 0x1, 0x2})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:403 +0x129f
    github.com/traefik/yaegi/interp.nodeType2(0xc000171b00, 0xc00016c990, 0xc000712000, {0xc0000ab560, 0x0, 0x1})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:681 +0x3acd
    github.com/traefik/yaegi/interp.nodeType(...)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/type.go:378
    github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc0007117a0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/gta.go:144 +0x385
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0007117a0, 0xc00056eb70, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:288 +0x34
    github.com/traefik/yaegi/interp.(*node).Walk(0xc000348b40, 0xc00056eb70, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:292 +0x75
    github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc000171b00, 0xc000348b40, {0xc000038240, 0x15}, {0xc0000381f9, 0x15}, {0xc000360c30, 0x3})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/gta.go:20 +0x22b
    github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc000171b00, {0xc000360ac0, 0x4}, {0xc0000381f9, 0x15}, 0x1)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/src.go:108 +0x100a
    github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc0003ce5a0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/gta.go:248 +0x1e95
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0003ce5a0, 0xc00056f910, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:288 +0x34
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0003ce480, 0xc00056f910, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:292 +0x75
    github.com/traefik/yaegi/interp.(*node).Walk(0xc0003ce240, 0xc00056f910, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:292 +0x75
    github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc000171b00, 0xc0003ce240, {0xc000360ac0, 0x4}, {0xc000360ac0, 0x4}, {0xc000360ac0, 0x4})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/gta.go:20 +0x22b
    github.com/traefik/yaegi/interp.(*Interpreter).gtaRetry(0xc000171b00?, {0xc0001b7af0?, 0xc00013c880?, 0xc0001b7a38?}, {0xc000360ac0, 0x4}, {0xc000360ac0, 0x4})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/gta.go:361 +0x155
    github.com/traefik/yaegi/interp.(*Interpreter).CompileAST(0xc000171b00, {0x1c1f078?, 0xc00013c880?})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/program.go:87 +0x17f
    github.com/traefik/yaegi/interp.(*Interpreter).compileSrc(0xc000171b00, {0xc0002e1400?, 0x0?}, {0x7ffeefbff9c6?, 0xc0002e1400?}, 0x75?)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/program.go:59 +0xb8
    github.com/traefik/yaegi/interp.(*Interpreter).eval(0xc000171b00, {0xc0002e1400?, 0x75?}, {0x7ffeefbff9c6?, 0xc0002e1300?}, 0x75?)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:610 +0x28
    github.com/traefik/yaegi/interp.(*Interpreter).EvalPath(0xc000171b00, {0x7ffeefbff9c6, 0x7})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/interp/interp.go:512 +0xab
    main.runFile(0x7ffeefbff9c6?, {0x7ffeefbff9c6, 0x7}, 0x0)
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/cmd/yaegi/run.go:153 +0xee
    main.run({0xc000032050?, 0x1, 0x1})
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/cmd/yaegi/run.go:116 +0xbec
    main.main()
    	/Users/russellluo/Labs/learn_go/projects/src/github.com/traefik/yaegi/cmd/yaegi/yaegi.go:144 +0x2dc
    

    Yaegi Version

    v0.13.0

    Additional Notes

    No response

    bug area/core 
    opened by RussellLuo 1
  • Method definition on aliased type

    Method definition on aliased type

    The following program sample.go triggers an unexpected result

    package main
    
    type Number int32
    
    type Number1 = Number
    
    type Number2 = Number1
    
    func (n Number2) IsValid() bool { return true }
    
    func main() {
    	a := Number(5)
    	println(a.IsValid())
    }
    

    Expected result

    % go run ./main.go 
    true
    

    Got

    % yaegi run ./sample.go 
    run: ./sample.go:9:1: cannot define new methods on non-local type int32
    

    Yaegi Version

    master

    Additional Notes

    Opposite situation of #1411

    bug area/core 
    opened by mpl 0
  • append slice of slices not working correctly

    append slice of slices not working correctly

    The following program sample.go triggers an unexpected result

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    func main() {
    	arr := make([]interface{}, 0)
    	arr = append(arr, []interface{}{1, 2, 3})
    	arr = append(arr, []interface{}{5, 6, 7})
    	bytes, _ := json.Marshal(arr)
    	fmt.Println("array: " + string(bytes))
    }
    

    Expected result

    $ go run ./sample.go
    array: [[1,2,3],[5,6,7]]
    

    Got

    $ yaegi ./sample.go
    array: [1,2,3,5,6,7]
    

    Yaegi Version

    v0.10.0

    Additional Notes

    No response

    bug area/core 
    opened by brucengdev 0
Releases(v0.13.0)
gpython is a python interpreter written in go "batteries not included"

gpython gpython is a part re-implementation / part port of the Python 3.4 interpreter to the Go language, "batteries not included". It includes: runti

go-python 591 Jun 23, 2022
wagon, a WebAssembly-based Go interpreter, for Go.

wagon wagon is a WebAssembly-based interpreter in Go, for Go. As of 2020/05/11 Wagon is in read-only mode, and looking for a maintainer. You may want

Go Interpreter 901 May 30, 2022
A BASIC interpreter written in golang.

05 PRINT "Index" 10 PRINT "GOBASIC!" 20 PRINT "Limitations" Arrays Line Numbers IF Statement DATA / READ Statements Builtin Functions Types 30 PRINT "

Steve Kemp 279 Jun 29, 2022
Lisp Interpreter

golisp Lisp Interpreter Usage $ golisp < foo.lisp Installation $ go get github.com/mattn/golisp/cmd/golisp Features Call Go functions. Print random in

mattn 117 Apr 29, 2022
A simple interpreter

类型: 基础类型: 整形,浮点,字符串,布尔,空值(nil) 符合类型: 数组,只读数组(元组),字典 支持语句: if, elif, else, for, foreach, break, continue, return 支持类型定义: class, func 语法格式: 赋值语句---> ```

null 18 Mar 16, 2022
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

mattn 1.2k Jun 20, 2022
Yaegi is Another Elegant Go Interpreter

Yaegi is Another Elegant Go Interpreter. It powers executable Go scripts and plugins, in embedded interpreters or interactive shells, on top of the Go

Traefik Labs 4.6k Jun 25, 2022
Interpreter - The Official Interpreter for the Infant Lang written in Go

Infant Lang Interpreter Infant Lang Minimalistic Less Esoteric Programming Langu

Infant Lang 2 Jan 10, 2022
The interpreter for qiitan script. Yet another dialect of the Tengo language.

Qiitan は、Qiita ™️ の SNS である「Qiitadonβ」のマスコット・キャラクターです。 キーたん(Qiitan) @ Qiitadon Qiitan-go は Qiitan のファン・アプリであり、Qiita ™️ とは一切関係がありません。 Qiitan-goalpha キー

Qithub - QiitaとQiitadonとGitHubをつなげるBOT 1 Feb 6, 2022
Amber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade

amber Notice While Amber is perfectly fine and stable to use, I've been working on a direct Pug.js port for Go. It is somewhat hacky at the moment but

Ekin Koc 894 Jul 1, 2022
Elegant Scraper and Crawler Framework for Golang

Colly Lightning Fast and Elegant Scraping Framework for Gophers Colly provides a clean interface to write any kind of crawler/scraper/spider. With Col

Colly 16.9k Jun 30, 2022
Elegant generics for Go

genny - Generics for Go Install: go get github.com/cheekybits/genny ===== (pron. Jenny) by Mat Ryer (@matryer) and Tyler Bunnell (@TylerJBunnell). Un

null 1.6k Jun 28, 2022
🍐 Elegant Golang REST API Framework

An Elegant Golang Web Framework Goyave is a progressive and accessible web application framework focused on REST APIs, aimed at making backend develop

SystemGlitch 1.1k Jun 23, 2022
A modern, fast and scalable websocket framework with elegant API written in Go

About neffos Neffos is a cross-platform real-time framework with expressive, elegant API written in Go. Neffos takes the pain out of development by ea

Gerasimos (Makis) Maropoulos 387 Jun 29, 2022
A modern, fast and scalable websocket framework with elegant API written in Go

About neffos Neffos is a cross-platform real-time framework with expressive, elegant API written in Go. Neffos takes the pain out of development by ea

Gerasimos (Makis) Maropoulos 386 Jun 22, 2022
Elegant Scraper and Crawler Framework for Golang

Colly Lightning Fast and Elegant Scraping Framework for Gophers Colly provides a clean interface to write any kind of crawler/scraper/spider. With Col

Colly 16.8k Jun 26, 2022
🍐 Elegant Golang REST API Framework

An Elegant Golang Web Framework Goyave is a progressive and accessible web application framework focused on REST APIs, aimed at making backend develop

Goyave 1.1k Jun 29, 2022
🍐 Elegant Golang Web Framework

Goyave Template A template project to get started with the Goyave framework. Getting Started Requirements Go 1.13+ Go modules Running the project Firs

Goyave 14 Apr 10, 2022
📖 Elegant changelog generator

English | 中文简体 whatchanged An elegant changelog generator. Focus on Elegant/Simple/Efficient/Scalable Feel the magic online Feature: Cross-platform su

Axetroy 43 Jun 8, 2022
Chore is a elegant and simple tool for executing common tasks on remote servers.

Chore is a tool for executing common tasks you run on your remote servers. You can easily setup tasks for deployment, commands, and more.

Ahmed waleed 39 May 20, 2022
CasaOS - A simple, easy-to-use, elegant open-source home server system.

CasaOS - A simple, easy-to-use, elegant open-source home server system. CasaOS is an open-source home server system based on the Docker ecosystem and

IceWhale 4k Jun 22, 2022
Database Access Layer for Golang - Testable, Extendable and Crafted Into a Clean and Elegant API

REL Modern Database Access Layer for Golang. REL is golang orm-ish database layer for layered architecture. It's testable and comes with its own test

REL 542 Jun 30, 2022
Elegant CLI wrapper for kubeseal CLI

Overview This is a wrapper CLI ofkubeseal CLI, specifically the raw mode. If you just need to encrypt your secret on RAW mode, this CLI will be the ea

Elm 4 Jan 8, 2022
A more elegant Client for huobi API with golang

huobi A more elegant Client for huobi API example package main import ( "context" "log" "os" "github.com/zhenzou/huobi" "github.com/zhenzou/huo

september 0 Dec 28, 2021
This package attempts to use an elegant (although potentially inefficient) approach to streams in go.

This package attempts to use an elegant (although potentially inefficient) approach to streams in goThis package attempts to use an elegant (although potentially inefficient) approach to streams in go

null 1 Mar 24, 2022
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

mattn 1.2k Jun 20, 2022
A shell parser, formatter, and interpreter with bash support; includes shfmt

sh A shell parser, formatter, and interpreter. Supports POSIX Shell, Bash, and mksh. Requires Go 1.14 or later. Quick start To parse shell scripts, in

Daniel Martí 4.9k Jun 26, 2022
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

mattn 1.2k Jun 20, 2022
A POSIX-compliant AWK interpreter written in Go

GoAWK: an AWK interpreter written in Go AWK is a fascinating text-processing language, and somehow after reading the delightfully-terse The AWK Progra

Ben Hoyt 1.5k Jun 28, 2022