Documentation
¶
Overview ¶
Package vm implements virtual-machine for anko.
Example (VmBasicOperators) ¶
package main
import (
"fmt"
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
a = nil
println(a)
a = true
println(a)
println("")
a = 2 + 1
println(a)
a = 2 - 1
println(a)
a = 2 * 1
println(a)
a = 4 / 2
println(a)
println("")
a = 1
a++
println(a)
a--
println(a)
println("")
a = 1
a += 1
println(a)
a -= 1
println(a)
a *= 4
println(a)
a /= 2
println(a)
println("")
a = 2 ** 3
println(a)
a = 1 & 3
println(a)
a = 1 | 2
println(a)
println("")
a = 2 << 3
println(a)
a = 8 >> 2
println(a)
a = 7 % 3
println(a)
println("")
a = 2 - (-2)
println(a)
a = ^2
println(a)
a = "a" * 4
println(a)
a = !true
println(a)
`
_, err = env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: <nil> true 3 1 2 2 2 1 2 1 4 2 8 1 3 16 2 1 4 -3 aaaa false
Example (VmComparisonOperators) ¶
package main
import (
"fmt"
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
a = nil == nil
println(a)
a = "a" != "a"
println(a)
a = 1 == 1.0
println(a)
a = !true
println(a)
println("")
a = 1 < 2
println(a)
a = 1 > 3
println(a)
a = 2 <= 2
println(a)
a = 2 >= 3
println(a)
println("")
a = 1 == 2 && 1 == 1
println(a)
a = 1 == 2 || 1 == 1
println(a)
`
_, err = env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: true false true false true false true false false true
Example (VmHelloWorld) ¶
package main
import (
"fmt"
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
println("Hello World :)")
`
_, err = env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: Hello World :)
Example (VmModule) ¶
package main
import (
"fmt"
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
module rectangle {
_length = 1
_width = 1
func setLength (length) {
if length <= 0 {
return
}
_length = length
}
func setWidth (width) {
if width <= 0 {
return
}
_width = width
}
func area () {
return _length * _width
}
func perimeter () {
return 2 * (_length + _width)
}
}
rectangle1 = rectangle
rectangle1.setLength(4)
rectangle1.setWidth(5)
println(rectangle1.area())
println(rectangle1.perimeter())
rectangle2 = rectangle
rectangle2.setLength(2)
rectangle2.setWidth(4)
println(rectangle2.area())
println(rectangle2.perimeter())
`
_, err = env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: 20 18 8 12
Example (VmSort) ¶
package main
import (
"log"
"github.com/mattn/anko/packages"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
packages.DefineImport(env)
script := `
fmt = import("fmt")
sort = import("sort")
a = [5, 1.1, 3, "f", "2", "4.4"]
sortFuncs = make(sort.SortFuncsStruct)
sortFuncs.LenFunc = func() { return len(a) }
sortFuncs.LessFunc = func(i, j) { return a[i] < a[j] }
sortFuncs.SwapFunc = func(i, j) { temp = a[i]; a[i] = a[j]; a[j] = temp }
sort.Sort(sortFuncs)
fmt.Println(a)
`
_, err := env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: [f 1.1 2 3 4.4 5]
Index ¶
- Variables
- func ClearInterrupt(env *Env)
- func Interrupt(env *Env)
- func Run(stmts []ast.Stmt, env *Env) (interface{}, error)
- func RunSingleStmt(stmt ast.Stmt, env *Env) (interface{}, error)
- func RunTest(t *testing.T, test Test, testingOptions *TestingOptions)
- func RunTests(t *testing.T, tests []Test, testingOptions *TestingOptions)
- func ValueEqual(v1 interface{}, v2 interface{}) bool
- type Env
- func (e *Env) AddPackage(name string, methods map[string]interface{}, types map[string]interface{}) (*Env, error)
- func (e *Env) Addr(k string) (reflect.Value, error)
- func (e *Env) Define(k string, v interface{}) error
- func (e *Env) DefineGlobal(k string, v interface{}) error
- func (e *Env) DefineGlobalReflectType(k string, t reflect.Type) error
- func (e *Env) DefineGlobalType(k string, t interface{}) error
- func (e *Env) DefineReflectType(k string, t reflect.Type) error
- func (e *Env) DefineType(k string, t interface{}) error
- func (e *Env) Delete(k string) error
- func (e *Env) DeleteGlobal(k string) error
- func (e *Env) Destroy()
- func (e *Env) Dump()
- func (e *Env) Execute(src string) (interface{}, error)
- func (e *Env) Get(k string) (interface{}, error)
- func (e *Env) GetName() string
- func (e *Env) NewEnv() *Env
- func (e *Env) NewModule(n string) *Env
- func (e *Env) NewPackage(n string) *Env
- func (e *Env) Set(k string, v interface{}) error
- func (e *Env) SetExternal(res EnvResolver)
- func (e *Env) SetName(n string)
- func (e *Env) String() string
- func (e *Env) Type(k string) (reflect.Type, error)
- type EnvResolver
- type Error
- type Test
- type TestingOptions
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrBreak when there is an unexpected break statement ErrBreak = errors.New("unexpected break statement") // ErrContinue when there is an unexpected continue statement ErrContinue = errors.New("unexpected continue statement") // ErrReturn when there is an unexpected return statement ErrReturn = errors.New("unexpected return statement") // ErrInterrupt when execution has been interrupted ErrInterrupt = errors.New("execution interrupted") )
Functions ¶
func ClearInterrupt ¶
func ClearInterrupt(env *Env)
ClearInterrupt removes the interrupt flag from specified environment. This includes all parent & child environments.
func Interrupt ¶
func Interrupt(env *Env)
Interrupt interrupts the execution of any running statements in the specified environment. This includes all parent & child environments. Note that the execution is not instantly aborted: after a call to Interrupt, the current running statement will finish, but the next statement will not run, and instead will return a nilValue and an ErrInterrupt.
Example ¶
package main
import (
"fmt"
"log"
"sync"
"time"
"github.com/mattn/anko/vm"
)
func main() {
var waitGroup sync.WaitGroup
waitGroup.Add(1)
waitChan := make(chan struct{}, 1)
env := vm.NewEnv()
sleepMillisecond := func() { time.Sleep(time.Millisecond) }
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("sleep", sleepMillisecond)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
# sleep for 10 seconds
for i = 0; i < 10000; i++ {
sleep()
}
# Should interrupt before printing the next line
println("this line should not be printed")
`
go func() {
close(waitChan)
v, err := env.Execute(script)
fmt.Println(v, err)
waitGroup.Done()
}()
<-waitChan
vm.Interrupt(env)
waitGroup.Wait()
}
Output: <nil> execution interrupted
func RunSingleStmt ¶
RunSingleStmt executes one statement in the specified environment.
func RunTest ¶ added in v0.0.4
func RunTest(t *testing.T, test Test, testingOptions *TestingOptions)
RunTest runs a VM test
func RunTests ¶ added in v0.0.4
func RunTests(t *testing.T, tests []Test, testingOptions *TestingOptions)
RunTests runs VM tests
func ValueEqual ¶ added in v0.0.4
func ValueEqual(v1 interface{}, v2 interface{}) bool
ValueEqual checks the values and returns true if equal If passed function, does extra checks otherwise just doing reflect.DeepEqual
Types ¶
type Env ¶
Env provides interface to run VM. This mean function scope and blocked-scope. If stack goes to blocked-scope, it will make new Env.
func (*Env) AddPackage ¶
func (e *Env) AddPackage(name string, methods map[string]interface{}, types map[string]interface{}) (*Env, error)
AddPackage creates a new env with a name that has methods and types in it. Created under the parent env
func (*Env) Addr ¶
Addr returns pointer value which specified symbol. It goes to upper scope until found or returns error.
func (*Env) Define ¶
Define defines symbol in current scope.
Example ¶
package main
import (
"fmt"
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
env.SetName("myName")
err := env.Define("println", fmt.Println)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("a", true)
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("b", int64(1))
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("c", float64(1.1))
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("d", "d")
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("e", []interface{}{true, int64(1), float64(1.1), "d"})
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
err = env.Define("f", map[string]interface{}{"a": true})
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
script := `
println(a)
println(b)
println(c)
println(d)
println(e)
println(f)
`
_, err = env.Execute(script)
if err != nil {
log.Fatalf("execute error: %v\n", err)
}
}
Output: true 1 1.1 d [true 1 1.1 d] map[a:true]
func (*Env) DefineGlobal ¶
DefineGlobal defines symbol in global scope.
func (*Env) DefineGlobalReflectType ¶
DefineGlobalReflectType defines type in global scope.
func (*Env) DefineGlobalType ¶
DefineGlobalType defines type in global scope.
func (*Env) DefineReflectType ¶
DefineReflectType defines type in current scope.
func (*Env) DefineType ¶
DefineType defines type in current scope.
func (*Env) DeleteGlobal ¶ added in v0.0.4
DeleteGlobal deletes the first matching symbol found in current or parent scope.
func (*Env) Dump ¶
func (e *Env) Dump()
Dump show symbol values in the scope.
Example ¶
package main
import (
"log"
"github.com/mattn/anko/vm"
)
func main() {
env := vm.NewEnv()
env.SetName("myName")
err := env.Define("a", "a")
if err != nil {
log.Fatalf("Define error: %v\n", err)
}
_, err = env.Get("a")
if err != nil {
log.Fatalf("Get error: %v\n", err)
}
env.Dump()
}
Output: Name: myName Has parent: false a = "a"
func (*Env) Get ¶
Get returns value which specified symbol. It goes to upper scope until found or returns error.
func (*Env) NewPackage ¶
NewPackage creates a new env with a name under the parent env
func (*Env) Set ¶
Set modifies value which specified as symbol. It goes to upper scope until found or returns error.
func (*Env) SetExternal ¶
func (e *Env) SetExternal(res EnvResolver)
SetExternal sets an external resolver
type EnvResolver ¶
type EnvResolver interface {
Get(string) (reflect.Value, error)
Type(string) (reflect.Type, error)
}
EnvResolver provides an interface for extrenal values and types
type Error ¶
Error provides a convenient interface for handling runtime error. It can be Error interface with type cast which can call Pos().
type Test ¶ added in v0.0.4
type Test struct {
Script string
ParseError error
ParseErrorFunc *func(*testing.T, error)
EnvSetupFunc *func(*testing.T, *Env)
Types map[string]interface{}
Input map[string]interface{}
RunError error
RunErrorFunc *func(*testing.T, error)
RunOutput interface{}
Output map[string]interface{}
}
Test is a struct use for testing VM
type TestingOptions ¶ added in v0.0.4
TestingOptions are options to pass to RunTests or RunTest