2019-01-17 20:39:23 +03:00
|
|
|
<p align="center">
|
2019-12-20 21:25:16 +03:00
|
|
|
<img src="https://raw.githubusercontent.com/d5/tengolang-share/master/logo_400.png" width="200" height="200">
|
2019-01-17 20:39:23 +03:00
|
|
|
</p>
|
|
|
|
|
2019-01-13 08:36:50 +03:00
|
|
|
# The Tengo Language
|
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
[![GoDoc](https://godoc.org/github.com/d5/tengo?status.svg)](https://godoc.org/github.com/d5/tengo)
|
2019-01-15 14:30:32 +03:00
|
|
|
[![Go Report Card](https://goreportcard.com/badge/github.com/d5/tengo)](https://goreportcard.com/report/github.com/d5/tengo)
|
2019-12-20 22:40:38 +03:00
|
|
|
[![CircleCI](https://circleci.com/gh/d5/tengo.svg?style=svg)](https://circleci.com/gh/d5/tengo)
|
2019-04-15 19:30:34 +03:00
|
|
|
[![Sourcegraph](https://sourcegraph.com/github.com/d5/tengo/-/badge.svg)](https://sourcegraph.com/github.com/d5/tengo?badge)
|
2019-01-14 18:17:07 +03:00
|
|
|
|
2019-01-24 04:44:32 +03:00
|
|
|
**Tengo is a small, dynamic, fast, secure script language for Go.**
|
2019-01-14 16:25:04 +03:00
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
Tengo is **[fast](#benchmark)** and secure because it's compiled/executed as
|
|
|
|
bytecode on stack-based VM that's written in native Go.
|
2019-01-13 08:36:50 +03:00
|
|
|
|
2019-01-24 07:12:34 +03:00
|
|
|
```golang
|
|
|
|
/* The Tengo Language */
|
2019-03-19 08:42:50 +03:00
|
|
|
fmt := import("fmt")
|
|
|
|
|
2019-01-24 07:12:34 +03:00
|
|
|
each := func(seq, fn) {
|
|
|
|
for x in seq { fn(x) }
|
|
|
|
}
|
|
|
|
|
|
|
|
sum := func(init, seq) {
|
|
|
|
each(seq, func(x) { init += x })
|
|
|
|
return init
|
|
|
|
}
|
|
|
|
|
2019-03-19 08:42:50 +03:00
|
|
|
fmt.println(sum(0, [1, 2, 3])) // "6"
|
|
|
|
fmt.println(sum("", [1, 2, 3])) // "123"
|
2019-01-24 07:12:34 +03:00
|
|
|
```
|
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
> Test this Tengo code in the
|
|
|
|
> [Tengo Playground](https://tengolang.com/?s=0c8d5d0d88f2795a7093d7f35ae12c3afa17bea3)
|
2019-01-13 08:36:50 +03:00
|
|
|
|
2019-01-13 09:09:43 +03:00
|
|
|
## Features
|
2019-01-13 08:36:50 +03:00
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
- Simple and highly readable
|
|
|
|
[Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
|
2019-01-24 07:12:34 +03:00
|
|
|
- Dynamic typing with type coercion
|
|
|
|
- Higher-order functions and closures
|
2019-01-26 02:03:32 +03:00
|
|
|
- Immutable values
|
2019-12-20 22:40:38 +03:00
|
|
|
- [Securely Embeddable](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
|
|
|
|
and [Extensible](https://github.com/d5/tengo/blob/master/docs/objects.md)
|
2019-01-24 07:12:34 +03:00
|
|
|
- Compiler/runtime written in native Go _(no external deps or cgo)_
|
2019-12-20 22:40:38 +03:00
|
|
|
- Executable as a
|
|
|
|
[standalone](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
|
|
|
|
language / REPL
|
|
|
|
- Use cases: rules engine, [state machine](https://github.com/d5/go-fsm),
|
|
|
|
data pipeline, [transpiler](https://github.com/d5/tengo2lua)
|
2019-01-13 08:36:50 +03:00
|
|
|
|
|
|
|
## Benchmark
|
|
|
|
|
|
|
|
| | fib(35) | fibt(35) | Type |
|
|
|
|
| :--- | ---: | ---: | :---: |
|
2019-04-01 08:08:25 +03:00
|
|
|
| Go | `48ms` | `3ms` | Go (native) |
|
|
|
|
| [**Tengo**](https://github.com/d5/tengo) | `2,349ms` | `5ms` | VM on Go |
|
|
|
|
| Lua | `1,416ms` | `3ms` | Lua (native) |
|
|
|
|
| [go-lua](https://github.com/Shopify/go-lua) | `4,402ms` | `5ms` | Lua VM on Go |
|
|
|
|
| [GopherLua](https://github.com/yuin/gopher-lua) | `4,023ms` | `5ms` | Lua VM on Go |
|
|
|
|
| Python | `2,588ms` | `26ms` | Python (native) |
|
|
|
|
| [starlark-go](https://github.com/google/starlark-go) | `11,126ms` | `6ms` | Python-like Interpreter on Go |
|
|
|
|
| [gpython](https://github.com/go-python/gpython) | `15,035ms` | `4ms` | Python Interpreter on Go |
|
|
|
|
| [goja](https://github.com/dop251/goja) | `5,089ms` | `5ms` | JS VM on Go |
|
|
|
|
| [otto](https://github.com/robertkrimen/otto) | `68,377ms` | `11ms` | JS Interpreter on Go |
|
|
|
|
| [Anko](https://github.com/mattn/anko) | `92,579ms` | `18ms` | Interpreter on Go |
|
2019-01-20 18:41:57 +03:00
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
_* [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)_
|
2019-01-24 03:30:41 +03:00
|
|
|
_* **Go** does not read the source code from file, while all other cases do_
|
|
|
|
_* See [here](https://github.com/d5/tengobench) for commands/codes used_
|
2019-01-13 08:36:50 +03:00
|
|
|
|
2019-12-20 22:40:38 +03:00
|
|
|
## Quick Start
|
|
|
|
|
|
|
|
A simple Go example code that compiles/runs Tengo script code with some input/output values:
|
|
|
|
|
|
|
|
```golang
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
2019-12-30 00:38:51 +03:00
|
|
|
"github.com/d5/tengo/v2"
|
2019-12-20 22:40:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
// Tengo script code
|
|
|
|
src := `
|
|
|
|
each := func(seq, fn) {
|
|
|
|
for x in seq { fn(x) }
|
|
|
|
}
|
|
|
|
|
|
|
|
sum := 0
|
|
|
|
mul := 1
|
|
|
|
each([a, b, c, d], func(x) {
|
|
|
|
sum += x
|
|
|
|
mul *= x
|
|
|
|
})`
|
|
|
|
|
|
|
|
// create a new Script instance
|
|
|
|
script := tengo.NewScript([]byte(src))
|
|
|
|
|
|
|
|
// set values
|
|
|
|
_ = script.Add("a", 1)
|
|
|
|
_ = script.Add("b", 9)
|
|
|
|
_ = script.Add("c", 8)
|
|
|
|
_ = script.Add("d", 4)
|
|
|
|
|
|
|
|
// run the script
|
|
|
|
compiled, err := script.RunContext(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// retrieve values
|
|
|
|
sum := compiled.Get("sum")
|
|
|
|
mul := compiled.Get("mul")
|
|
|
|
fmt.Println(sum, mul) // "22 288"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2019-01-24 03:30:41 +03:00
|
|
|
## References
|
2019-01-13 08:36:50 +03:00
|
|
|
|
2019-01-24 03:30:41 +03:00
|
|
|
- [Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
|
2019-01-31 11:39:45 +03:00
|
|
|
- [Object Types](https://github.com/d5/tengo/blob/master/docs/objects.md)
|
2019-12-20 22:40:38 +03:00
|
|
|
- [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md)
|
|
|
|
and [Operators](https://github.com/d5/tengo/blob/master/docs/operators.md)
|
2019-01-24 03:30:41 +03:00
|
|
|
- [Builtin Functions](https://github.com/d5/tengo/blob/master/docs/builtins.md)
|
|
|
|
- [Interoperability](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
|
|
|
|
- [Tengo CLI](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
|
2019-01-30 08:08:21 +03:00
|
|
|
- [Standard Library](https://github.com/d5/tengo/blob/master/docs/stdlib.md)
|