5.4 KiB
Tengo Syntax
Tengo's syntax is designed to be familiar to Go developers while being a bit simpler and more streamlined.
Comments
Tengo supports line comments (//...
) and block comments (/* ... */
).
/*
multi-line block comments
*/
a := 5 // line comments
Types and Assignment
Tengo is a dynamically typed language, and, you can initialize the variables using :=
operator.
a := 1984 // int
b := "aomame" // string
c := -9.22 // float
d := true // bool
e := '九' // char
f := [1, false, "foo"] // array
g := { // map
h: 439,
i: 12.34,
j: [0, 9, false]
}
k := func(l, m) { // function
return l + m
}
After the variable is initialized, it can be re-assigned different value using =
operator.
a := 1928 // int
a = "foo" // string
f := func() {
a := false // 'a' is defined in the function scope
a = [1, 2, 3] // and thus does not affect 'a' in global scope.
}
a == "foo" // still "foo"
Type is not directly specified, but, you can use type-coercion functions to convert between types.
s1 := string(1984) // "1984"
i2 := int("-999") // -999
f3 := float(-51) // -51.0
b4 := bool(1) // true
c5 := char("X") // 'X'
See Variable Types for more details on the variable types.
Indexing
You can use the dot selector (.
) and indexer ([]
) operator to read or write elements of arrays, strings, or maps.
["one", "two", "three"][1] // == "two"
m := {
a: 1,
b: [2, 3, 4],
c: func() { return 10 }
}
m.a // == 1
m["b"][1] // == 3
m.c() // == 10
m.x = 5 // add 'x' to map 'm'
//m.b[5] = 0 // but this is an error: index out of bounds
For sequence types (string, bytes, array), you can use slice operator ([:]
) too.
a := [1, 2, 3, 4, 5][1:3] // == [2, 3]
b := [1, 2, 3, 4, 5][3:] // == [4, 5]
c := [1, 2, 3, 4, 5][:3] // == [1, 2, 3]
d := "hello world"[2:10] // == "llo worl"
Functions
In Tengo, functions are first-class citizen, and, it also supports closures, functions that captures variables in outer scopes. In the following example, the function returned from adder
is capturing base
variable.
adder := func(base) {
return func(x) { return base + x } // capturing 'base'
}
add5 := adder(5)
nine := add5(4) // == 9
Flow Control
For flow control, Tengo currently supports if-else, for, for-in statements.
// IF-ELSE
if a < 0 {
// ...
} else if a == 0 {
// ...
} else {
// ...
}
// IF with init statement
if a := 0; a < 10 {
// ...
} else {
// ...
}
// FOR
for a:=0; a<10; a++ {
// ...
}
// FOR condition-only (like WHILE in other languages)
for a < 10 {
// ...
}
// FOR-IN
for x in [1, 2, 3] { // array: element
// ...
}
for i, x in [1, 2, 3] { // array: index and element
// ...
}
for k, v in {k1: 1, k2: 2} { // map: key and value
// ...
}
Immutable Values
A value can be marked as immutable using immutable
expression.
a := immutable([1, 2, 3]) // 'a' is immutable
b = a[1] // b == 2
a[0] = 5 // runtime error
c := immutable({d: [1, 2, 3]})
c.d[1] = 10 // runtime error as 'c.d' is also immutable
e := {f: a} // 'a' is immutable but 'e' is not
e.g = 20 // valid; e == {f: a, g: 20}
e.a[1] = 5 // runtime error as 'e.a' is immutable
Errors
An error object is created using error
expression. An error can contain value of any types, and, the underlying value can be read using .value
selector.
err1 := error("oops") // error with string value
err2 := error(1+2+3) // error with int value
if is_error(err1) { // 'is_error' builtin function
err_val := err1.value // get underlying value
}
Modules
You can load other scripts as modules using import
expression.
Main script:
mod1 := import("./mod1") // assuming mod1.tengo file exists in the current directory
// same as 'import("./mod1.tengo")' or 'import("mod1")'
mod1.func1(a) // module function
a += mod1.foo // module variable
//mod1.foo = 5 // error: module variables are read-only
mod1.tengo
file:
func1 := func(x) { print(x) }
foo := 2
Basically, import
expression returns all the global variables defined in the module as a Map-like value. One can access the functions or variables defined in the module using .
selector or ["key"]
indexer, but, module variables are immutable.
Also, you can use import
to load the Standard Library.
math := import("math")
a := math.abs(-19.84) // == 19.84