diff --git a/.gitignore b/.gitignore index 6dd29b7f..77738287 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -bin/ \ No newline at end of file +dist/ \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 00000000..283c13c6 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,15 @@ +builds: + - env: + - CGO_ENABLED=0 + main: ./cmd/tengo/main.go + goos: + - darwin + - linux + - windows +archive: + files: + - none* +checksum: + name_template: 'checksums.txt' +changelog: + sort: asc diff --git a/.travis.yml b/.travis.yml index 295caf7e..d545268e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,10 @@ install: script: - make test + +deploy: + - provider: script + skip_cleanup: true + script: curl -sL https://git.io/goreleaser | bash + on: + tags: true \ No newline at end of file diff --git a/README.md b/README.md index f949b77b..c2995eeb 100644 --- a/README.md +++ b/README.md @@ -47,16 +47,16 @@ s := sum("", [1, 2, 3]) // == "123" | | fib(35) | fibt(35) | Type | | :--- | ---: | ---: | :---: | | Go | `58ms` | `4ms` | Go (native) | -| [**Tengo**](https://github.com/d5/tengo) | `4,334ms` | `5ms` | VM on Go | -| Lua | `1,740ms` | `3ms` | Lua (native) | -| [go-lua](https://github.com/Shopify/go-lua) | `5,229ms` | `5ms` | Lua VM on Go | -| [GopherLua](https://github.com/yuin/gopher-lua) | `5,486ms` | `5ms` | Lua VM on Go | -| Python | `3,116ms` | `27ms` | Python (native) | -| [starlark-go](https://github.com/google/starlark-go) | `15,414ms` | `5ms` | Python-like Interpreter on Go | -| [gpython](https://github.com/go-python/gpython) | `17,754ms` | `6ms` | Python Interpreter on Go | -| [goja](https://github.com/dop251/goja) | `6,843ms` | `6ms` | JS VM on Go | -| [otto](https://github.com/robertkrimen/otto) | `86,542ms` | `13ms` | JS Interpreter on Go | -| [Anko](https://github.com/mattn/anko) | `98,962ms` | `26ms` | Interpreter on Go | +| [**Tengo**](https://github.com/d5/tengo) | `4,180ms` | `5ms` | VM on Go | +| Lua | `1,695ms` | `3ms` | Lua (native) | +| [go-lua](https://github.com/Shopify/go-lua) | `5,163ms` | `5ms` | Lua VM on Go | +| [GopherLua](https://github.com/yuin/gopher-lua) | `5,525ms` | `5ms` | Lua VM on Go | +| Python | `3,097ms` | `27ms` | Python (native) | +| [starlark-go](https://github.com/google/starlark-go) | `15,307ms` | `5ms` | Python-like Interpreter on Go | +| [gpython](https://github.com/go-python/gpython) | `17,656ms` | `5ms` | Python Interpreter on Go | +| [goja](https://github.com/dop251/goja) | `6,876ms` | `5ms` | JS VM on Go | +| [otto](https://github.com/robertkrimen/otto) | `81,886ms` | `12ms` | JS Interpreter on Go | +| [Anko](https://github.com/mattn/anko) | `97,517ms` | `14ms` | Interpreter on Go | _* [fib(35)](https://github.com/d5/tengobench/blob/master/code/fib.tengo): Fibonacci(35)_ _* [fibt(35)](https://github.com/d5/tengobench/blob/master/code/fibtc.tengo): [tail-call](https://en.wikipedia.org/wiki/Tail_call) version of Fibonacci(35)_ @@ -72,24 +72,3 @@ _* See [here](https://github.com/d5/tengobench) for commands/codes used_ - [Interoperability](https://github.com/d5/tengo/blob/master/docs/interoperability.md) - [Tengo CLI](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md) - [Standard Library](https://github.com/d5/tengo/blob/master/docs/stdlib.md) - -## Roadmap - -### v0. _(Current)_ - -Things are experimental, and, the focus is on the **core language features**, **stability**, **basic interoperability**, and the **performance optimization**. - -### [v1. Tengo as a Script Language](https://github.com/d5/tengo/labels/v1.0) - -This will be the first _versioned_ release, and, the main goal for v1 is to make Tengo as a _fast_ embeddable script language for Go, which means Tengo will be comparable to other Go-based script languages such as [Starlark](https://github.com/google/starlark-go), [Lua](https://github.com/Shopify/go-lua) [VM](https://github.com/yuin/gopher-lua)s, and [other](https://github.com/robertkrimen/otto) [interpreter](https://github.com/mattn/anko)s. - -- Interoperability with Go code -- Sandbox environment -- More language features - -### v2. Tengo as a Standalone Language - -- Language-level concurrency support -- Tengo Standard Libraries -- Native executables compilation -- More language features diff --git a/cmd/tengo/main.go b/cmd/tengo/main.go index 5ebb0542..f9d19b50 100644 --- a/cmd/tengo/main.go +++ b/cmd/tengo/main.go @@ -25,15 +25,16 @@ const ( ) var ( - compile bool - showHelp bool - outputFile = flag.String("o", "", "Output file") + compileOutput string + showHelp bool + showVersion bool + version = "dev" ) func init() { flag.BoolVar(&showHelp, "help", false, "Show help") - flag.BoolVar(&compile, "compile", false, "Compile input file") - flag.BoolVar(&compile, "c", false, "Compile input file") + flag.StringVar(&compileOutput, "o", "", "Compile output file") + flag.BoolVar(&showVersion, "version", false, "Show version") flag.Parse() } @@ -41,12 +42,15 @@ func main() { if showHelp { doHelp() os.Exit(2) + } else if showVersion { + fmt.Println(version) + return } inputFile := flag.Arg(0) if inputFile == "" { // REPL - doRepl(os.Stdin, os.Stdout) + runREPL(os.Stdin, os.Stdout) return } @@ -56,18 +60,18 @@ func main() { os.Exit(1) } - if compile { - if err := doCompile(inputData, inputFile, *outputFile); err != nil { + if compileOutput != "" { + if err := compileOnly(inputData, inputFile, compileOutput); err != nil { _, _ = fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } } else if filepath.Ext(inputFile) == sourceFileExt { - if err := doCompileRun(inputData, inputFile, *outputFile); err != nil { + if err := compileAndRun(inputData, inputFile); err != nil { _, _ = fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } } else { - if err := doRun(inputData, inputFile, *outputFile); err != nil { + if err := runCompiled(inputData); err != nil { _, _ = fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } @@ -81,27 +85,32 @@ func doHelp() { fmt.Println() fmt.Println("Flags:") fmt.Println() - fmt.Println(" -c/-compile compile the input and produce bytecode file") - fmt.Println(" -o output") + fmt.Println(" -o compile output file") + fmt.Println(" -version show version") fmt.Println() fmt.Println("Examples:") fmt.Println() fmt.Println(" tengo") - fmt.Println(" : Start Tengo REPL") + fmt.Println() + fmt.Println(" Start Tengo REPL") fmt.Println() fmt.Println(" tengo myapp.tengo") - fmt.Println(" : Compile and execute source file (myapp.tengo)") fmt.Println() - fmt.Println(" tengo -c myapp myapp.tengo") - fmt.Println(" : Compile source file (myapp.tengo) and produce bytecode file (myapp)") + fmt.Println(" Compile and run source file (myapp.tengo)") + fmt.Println(" Source file must have .tengo extension") + fmt.Println() + fmt.Println(" tengo -o myapp myapp.tengo") + fmt.Println() + fmt.Println(" Compile source file (myapp.tengo) into bytecode file (myapp)") fmt.Println() fmt.Println(" tengo myapp") - fmt.Println(" : Execute bytecode file (myapp)") + fmt.Println() + fmt.Println(" Run bytecode file (myapp)") fmt.Println() fmt.Println() } -func doCompile(data []byte, inputFile, outputFile string) (err error) { +func compileOnly(data []byte, inputFile, outputFile string) (err error) { bytecode, err := compileSrc(data, filepath.Base(inputFile)) if err != nil { return @@ -133,7 +142,7 @@ func doCompile(data []byte, inputFile, outputFile string) (err error) { return } -func doCompileRun(data []byte, inputFile, _ string) (err error) { +func compileAndRun(data []byte, inputFile string) (err error) { bytecode, err := compileSrc(data, filepath.Base(inputFile)) if err != nil { return @@ -149,7 +158,7 @@ func doCompileRun(data []byte, inputFile, _ string) (err error) { return } -func doRun(data []byte, _, _ string) (err error) { +func runCompiled(data []byte) (err error) { bytecode := &compiler.Bytecode{} err = bytecode.Decode(bytes.NewReader(data)) if err != nil { @@ -166,7 +175,7 @@ func doRun(data []byte, _, _ string) (err error) { return } -func doRepl(in io.Reader, out io.Writer) { +func runREPL(in io.Reader, out io.Writer) { stdin := bufio.NewScanner(in) fileSet := source.NewFileSet() diff --git a/compiler/ast/return_stmt.go b/compiler/ast/return_stmt.go index f82f8f07..592d45b8 100644 --- a/compiler/ast/return_stmt.go +++ b/compiler/ast/return_stmt.go @@ -1,15 +1,13 @@ package ast import ( - "strings" - "github.com/d5/tengo/compiler/source" ) // ReturnStmt represents a return statement. type ReturnStmt struct { ReturnPos source.Pos - Results []Expr + Result Expr } func (s *ReturnStmt) stmtNode() {} @@ -21,21 +19,16 @@ func (s *ReturnStmt) Pos() source.Pos { // End returns the position of first character immediately after the node. func (s *ReturnStmt) End() source.Pos { - if n := len(s.Results); n > 0 { - return s.Results[n-1].End() + if s.Result != nil { + return s.Result.End() } return s.ReturnPos + 6 } func (s *ReturnStmt) String() string { - if len(s.Results) > 0 { - var res []string - for _, e := range s.Results { - res = append(res, e.String()) - } - - return "return " + strings.Join(res, ", ") + if s.Result != nil { + return "return " + s.Result.String() } return "return" diff --git a/compiler/bytecode.go b/compiler/bytecode.go index df0d2f22..93be1e25 100644 --- a/compiler/bytecode.go +++ b/compiler/bytecode.go @@ -85,4 +85,5 @@ func init() { gob.Register(&objects.MapIterator{}) gob.Register(&objects.ArrayIterator{}) gob.Register(&objects.Time{}) + gob.Register(&objects.CompiledModule{}) } diff --git a/compiler/bytecode_test.go b/compiler/bytecode_test.go index 86ac2acc..60eebb48 100644 --- a/compiler/bytecode_test.go +++ b/compiler/bytecode_test.go @@ -69,20 +69,20 @@ func TestBytecode(t *testing.T) { compiler.MakeInstruction(compiler.OpAdd), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 0, compiler.MakeInstruction(compiler.OpConstant, 2), compiler.MakeInstruction(compiler.OpSetLocal, 0), compiler.MakeInstruction(compiler.OpGetFree, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 4, 2), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 0, compiler.MakeInstruction(compiler.OpConstant, 1), compiler.MakeInstruction(compiler.OpSetLocal, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 5, 1), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) } func testBytecodeSerialization(t *testing.T, b *compiler.Bytecode) { diff --git a/compiler/compiler.go b/compiler/compiler.go index ff886d4b..9fd2a492 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -426,17 +426,14 @@ func (c *Compiler) Compile(node ast.Node) error { return fmt.Errorf("return statement outside function") } - switch len(node.Results) { - case 0: + if node.Result == nil { c.emit(OpReturn) - case 1: - if err := c.Compile(node.Results[0]); err != nil { + } else { + if err := c.Compile(node.Result); err != nil { return err } - c.emit(OpReturnValue, 1) - default: - return fmt.Errorf("multi-value return not implemented") + c.emit(OpReturnValue) } case *ast.CallExpr: diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index f05aedf5..6e16db96 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -446,7 +446,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpConstant, 0), compiler.MakeInstruction(compiler.OpConstant, 1), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `func() { 5 + 10 }`, bytecode( @@ -490,7 +490,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpConstant, 0), compiler.MakeInstruction(compiler.OpPop), compiler.MakeInstruction(compiler.OpConstant, 1), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `func() { if(true) { return 1 } else { return 2 } }`, bytecode( @@ -501,13 +501,13 @@ func TestCompiler_Compile(t *testing.T) { intObject(1), intObject(2), compiledFunction(0, 0, - compiler.MakeInstruction(compiler.OpTrue), // 0000 - compiler.MakeInstruction(compiler.OpJumpFalsy, 12), // 0001 - compiler.MakeInstruction(compiler.OpConstant, 0), // 0004 - compiler.MakeInstruction(compiler.OpReturnValue, 1), // 0007 - compiler.MakeInstruction(compiler.OpJump, 17), // 0009 - compiler.MakeInstruction(compiler.OpConstant, 1), // 0012 - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) // 0014 + compiler.MakeInstruction(compiler.OpTrue), // 0000 + compiler.MakeInstruction(compiler.OpJumpFalsy, 11), // 0001 + compiler.MakeInstruction(compiler.OpConstant, 0), // 0004 + compiler.MakeInstruction(compiler.OpReturnValue), // 0007 + compiler.MakeInstruction(compiler.OpJump, 15), // 0008 + compiler.MakeInstruction(compiler.OpConstant, 1), // 0011 + compiler.MakeInstruction(compiler.OpReturnValue))))) // 0014 expect(t, `func() { 1; if(true) { 2 } else { 3 }; 4 }`, bytecode( @@ -564,7 +564,7 @@ func TestCompiler_Compile(t *testing.T) { intObject(24), compiledFunction(0, 0, compiler.MakeInstruction(compiler.OpConstant, 0), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `noArg := func() { 24 }; noArg();`, bytecode( @@ -593,7 +593,7 @@ func TestCompiler_Compile(t *testing.T) { intObject(24), compiledFunction(0, 0, compiler.MakeInstruction(compiler.OpConstant, 0), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `n := 55; func() { n };`, bytecode( @@ -620,23 +620,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpConstant, 0), compiler.MakeInstruction(compiler.OpDefineLocal, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) - - expect(t, `func() { n := 55; n = 23; return n }`, - bytecode( - concat( - compiler.MakeInstruction(compiler.OpConstant, 2), - compiler.MakeInstruction(compiler.OpPop)), - objectsArray( - intObject(55), - intObject(23), - compiledFunction(1, 0, - compiler.MakeInstruction(compiler.OpConstant, 0), - compiler.MakeInstruction(compiler.OpDefineLocal, 0), - compiler.MakeInstruction(compiler.OpConstant, 1), - compiler.MakeInstruction(compiler.OpSetLocal, 0), - compiler.MakeInstruction(compiler.OpGetLocal, 0), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `func() { a := 55; b := 77; return a + b }`, bytecode( @@ -654,7 +638,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpGetLocal, 1), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `f1 := func(a) { return a }; f1(24);`, bytecode( @@ -668,7 +652,7 @@ func TestCompiler_Compile(t *testing.T) { objectsArray( compiledFunction(1, 1, compiler.MakeInstruction(compiler.OpGetLocal, 0), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), intObject(24)))) expect(t, `f1 := func(a, b, c) { a; b; return c; }; f1(24, 25, 26);`, @@ -689,11 +673,26 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpGetLocal, 1), compiler.MakeInstruction(compiler.OpPop), compiler.MakeInstruction(compiler.OpGetLocal, 2), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), intObject(24), intObject(25), intObject(26)))) + expect(t, `func() { n := 55; n = 23; return n }`, + bytecode( + concat( + compiler.MakeInstruction(compiler.OpConstant, 2), + compiler.MakeInstruction(compiler.OpPop)), + objectsArray( + intObject(55), + intObject(23), + compiledFunction(1, 0, + compiler.MakeInstruction(compiler.OpConstant, 0), + compiler.MakeInstruction(compiler.OpDefineLocal, 0), + compiler.MakeInstruction(compiler.OpConstant, 1), + compiler.MakeInstruction(compiler.OpSetLocal, 0), + compiler.MakeInstruction(compiler.OpGetLocal, 0), + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `len([]);`, bytecode( concat( @@ -713,7 +712,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpGetBuiltin, 3), compiler.MakeInstruction(compiler.OpArray, 0), compiler.MakeInstruction(compiler.OpCall, 1), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `func(a) { func(b) { return a + b } }`, bytecode( @@ -725,7 +724,7 @@ func TestCompiler_Compile(t *testing.T) { compiler.MakeInstruction(compiler.OpGetFree, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 1, compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 0, 1), @@ -751,16 +750,16 @@ func(a) { compiler.MakeInstruction(compiler.OpAdd), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 1, compiler.MakeInstruction(compiler.OpGetFree, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 0, 2), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 1, compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 1, 1), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, ` g := 55; @@ -799,20 +798,20 @@ func() { compiler.MakeInstruction(compiler.OpAdd), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpAdd), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 0, compiler.MakeInstruction(compiler.OpConstant, 2), compiler.MakeInstruction(compiler.OpDefineLocal, 0), compiler.MakeInstruction(compiler.OpGetFree, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 4, 2), - compiler.MakeInstruction(compiler.OpReturnValue, 1)), + compiler.MakeInstruction(compiler.OpReturnValue)), compiledFunction(1, 0, compiler.MakeInstruction(compiler.OpConstant, 1), compiler.MakeInstruction(compiler.OpDefineLocal, 0), compiler.MakeInstruction(compiler.OpGetLocal, 0), compiler.MakeInstruction(compiler.OpClosure, 5, 1), - compiler.MakeInstruction(compiler.OpReturnValue, 1))))) + compiler.MakeInstruction(compiler.OpReturnValue))))) expect(t, `for i:=0; i<10; i++ {}`, bytecode( diff --git a/compiler/opcodes.go b/compiler/opcodes.go index eaa4892d..d64a0306 100644 --- a/compiler/opcodes.go +++ b/compiler/opcodes.go @@ -157,7 +157,7 @@ var OpcodeOperands = [...][]int{ OpSliceIndex: {}, OpCall: {1}, OpReturn: {}, - OpReturnValue: {1}, + OpReturnValue: {}, OpGetLocal: {1}, OpSetLocal: {1}, OpDefineLocal: {1}, diff --git a/compiler/parser/parser.go b/compiler/parser/parser.go index df84d96f..b8ae4bad 100644 --- a/compiler/parser/parser.go +++ b/compiler/parser/parser.go @@ -862,15 +862,15 @@ func (p *Parser) parseReturnStmt() ast.Stmt { pos := p.pos p.expect(token.Return) - var x []ast.Expr + var x ast.Expr if p.token != token.Semicolon && p.token != token.RBrace { - x = p.parseExprList() + x = p.parseExpr() } p.expectSemi() return &ast.ReturnStmt{ ReturnPos: pos, - Results: x, + Result: x, } } diff --git a/compiler/parser/parser_test.go b/compiler/parser/parser_test.go index 8ad75b8c..2e975ebd 100644 --- a/compiler/parser/parser_test.go +++ b/compiler/parser/parser_test.go @@ -144,8 +144,8 @@ func emptyStmt(implicit bool, pos source.Pos) *ast.EmptyStmt { return &ast.EmptyStmt{Implicit: implicit, Semicolon: pos} } -func returnStmt(pos source.Pos, results ...ast.Expr) *ast.ReturnStmt { - return &ast.ReturnStmt{Results: results, ReturnPos: pos} +func returnStmt(pos source.Pos, result ast.Expr) *ast.ReturnStmt { + return &ast.ReturnStmt{Result: result, ReturnPos: pos} } func forStmt(init ast.Stmt, cond ast.Expr, post ast.Stmt, body *ast.BlockStmt, pos source.Pos) *ast.ForStmt { @@ -309,7 +309,7 @@ func equalStmt(t *testing.T, expected, actual ast.Stmt) bool { equalStmt(t, expected.Body, actual.(*ast.ForInStmt).Body) && assert.Equal(t, expected.ForPos, actual.(*ast.ForInStmt).ForPos) case *ast.ReturnStmt: - return equalExprs(t, expected.Results, actual.(*ast.ReturnStmt).Results) && + return equalExpr(t, expected.Result, actual.(*ast.ReturnStmt).Result) && assert.Equal(t, expected.ReturnPos, actual.(*ast.ReturnStmt).ReturnPos) case *ast.BranchStmt: return equalExpr(t, expected.Label, actual.(*ast.BranchStmt).Label) && diff --git a/docs/interoperability.md b/docs/interoperability.md index 8d450503..0be8bd56 100644 --- a/docs/interoperability.md +++ b/docs/interoperability.md @@ -62,7 +62,7 @@ func main() { } // run the compiled bytecode - // a compiled bytecode 'c' can be executed multiple without re-compiling it + // a compiled bytecode 'c' can be executed multiple times without re-compiling it if err := c.Run(); err != nil { panic(err) } diff --git a/docs/tengo-cli.md b/docs/tengo-cli.md index 337808b1..27808981 100644 --- a/docs/tengo-cli.md +++ b/docs/tengo-cli.md @@ -10,6 +10,8 @@ To install `tengo` tool, run: go get github.com/d5/tengo/cmd/tengo ``` +Or, you can download the precompiled binaries from [here](https://github.com/d5/tengo/releases/latest). + ## Compiling and Executing Tengo Code You can directly execute the Tengo source code by running `tengo` tool with your Tengo source file (`*.tengo`). @@ -21,8 +23,8 @@ tengo myapp.tengo Or, you can compile the code into a binary file and execute it later. ```bash -tengo -c -o myapp myapp.tengo # compile 'myapp.tengo' into binary file 'myapp' -tengo myapp # execute the compiled binary `myapp` +tengo -o myapp myapp.tengo # compile 'myapp.tengo' into binary file 'myapp' +tengo myapp # execute the compiled binary `myapp` ``` ## Tengo REPL diff --git a/runtime/vm.go b/runtime/vm.go index b4be7141..bbc230f0 100644 --- a/runtime/vm.go +++ b/runtime/vm.go @@ -785,16 +785,6 @@ func (v *VM) Run() error { } case compiler.OpReturnValue: - //numRets := int(compiler.ReadUint8(v.curInsts[v.ip+1:])) - //_ = int64(compiler.ReadUint8(v.curInsts[v.ip+1:])) - v.ip++ - - // TODO: multi-value return is not fully implemented yet - //var rets []*objects.Object - //for i := 0; i < numRets; i++ { - // val := v.pop() - // rets = append(rets, val) - //} retVal := v.stack[v.sp-1] //v.sp-- @@ -808,11 +798,6 @@ func (v *VM) Run() error { //v.sp = lastFrame.basePointer - 1 v.sp = lastFrame.basePointer - //for _, retVal := range rets { - // if err := v.push(retVal); err != nil { - // return err - // } - //} if v.sp-1 >= StackSize { return ErrStackOverflow }