Documentation ¶
Overview ¶
Package vm implements virtual-machine for anko.
Example (VmArrays) ¶
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 = []interface{1, 2} println(a) a += 3 println(a) a = []interface{} // this automatically appends to array a[0] = 1 println(a) println("") a = []interface{} // this would give an index out of range error // a[1] = 1 a = []interface{1, 2} b = []interface{3, 4} c = a + b println(c) c = []interface{1, 2} + []interface{3, 4} println(c) println("") c = []interface{a} + b println(c) c = []interface{a} + []interface{b} println(c) c = []interface{[]interface{1, 2}} + []interface{[]interface{3, 4}} println(c) println("") a = []interface{1, 2} println(len(a)) println(a[1]) a = [1, 2] println(a) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: [1 2] [1 2 3] [1] [1 2 3 4] [1 2 3 4] [[1 2] 3 4] [[1 2] [3 4]] [[1 2] [3 4]] 2 2 [1 2]
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 = 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 1 3 16 2 1 4 -3 aaaa false
Example (VmChannels) ¶
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 = make(chan string, 1) a <- "a" println(<- a) a = make(chan string) go func() { a <- "a" }() println(<- a) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: a a
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 (VmForLoops) ¶
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 := ` i = 0 for { println(i) i++ if i > 1 { break } } println("") for i in [0, 1] { println(i) } println("") for key, value in {"a": "b"} { println(key, value) } println("") i = 0 for i < 2 { println(i) i++ } println("") for i = 0; i < 2; i++ { println(i) } println("") for i = 0; i < 10; i++ { println(i) if i < 1 { continue } break } ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: 0 1 0 1 a b 0 1 0 1 0 1
Example (VmFunctions) ¶
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 := ` func a(b) { println(b) } a("b") a = func(b) { println(b) } a("b") func(b) { println(b) }("b") func a() { return "a" } println(a()) println("") func fib(n) { if (n <= 1) { return n } return fib(n - 1) + fib(n - 2) } println(fib(8)) func sum(n...) { t = 0 for a in n { t += a } return t } println(sum(1, 2, 3, 4)) func add(a, b) { return a + b } println(add([1, 2]...)) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: b b b a 21 10 3
Example (VmFunctionsOutside) ¶
package main import ( "fmt" "log" "github.com/mattn/anko/vm" ) func testFunc1(a interface{}) int { b, ok := a.([]interface{}) if ok { return len(b) } return 0 } func main() { /* // the following function would be uncommented func testFunc1(a interface{}) int { b, ok := a.([]interface{}) if ok { return len(b) } return 0 } */ env := vm.NewEnv() err := env.Define("println", fmt.Println) if err != nil { log.Fatalf("define error: %v\n", err) } err = env.Define("addString", func(a string, b string) string { return a + b }) if err != nil { log.Fatalf("define error: %v\n", err) } // uses the function that would be declared above err = env.Define("aFunc", testFunc1) if err != nil { log.Fatalf("define error: %v\n", err) } script := ` a = addString("a", "b") println(a) a = aFunc([1, 2, 3]) println(a) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: ab 3
Example (VmFunctionsScope) ¶
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 = 1 func () { a = 2 }() println(a) var a = 1 func () { a = 2 }() println(a) a = 1 func () { var a = 2 }() println(a) var a = 1 func () { var a = 2 }() println(a) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: 2 2 1 1
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 (VmHttp) ¶
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") io = import("io") ioutil = import("io/ioutil") net = import("net") http = import("net/http") time = import("time") func handlerRoot(responseWriter, request) { io.WriteString(responseWriter, "Hello World :)") } serveMux = http.NewServeMux() serveMux.HandleFunc("/", handlerRoot) listener, err = net.Listen("tcp", ":8080") if err != nil { fmt.Println(err) return } go http.Serve(listener, serveMux) client = http.DefaultClient response, err = client.Get("http://localhost:8080/") if err != nil { fmt.Println(err) return } body, err = ioutil.ReadAll(response.Body) if err != nil { fmt.Println(err) } response.Body.Close() fmt.Printf("%s\n", body) ` _, err := env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: Hello World :)
Example (VmIfOperators) ¶
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 = 1 b = 2 if a == 1 { println(a) } if b == 1 { println(a) } else { println(b) } if a == 3 { println(a) } else if b == 3 { println(b) } else { println(a + b) } println("") if a == 2 || b == 2 { println(4) } if a == 1 && b == 2 { println(5) } ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: 1 2 3 4 5
Example (VmMaps) ¶
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 = map[interface]interface{} println(a) a.b = 1 println(a) println(a.b) a["b"] = 2 println(a["b"]) println(len(a)) println("") b, ok = a["b"] println(b) println(ok) delete(a, "b") _, ok = a["b"] println(ok) println("") a = {} println(a) a.b = 1 println(a) println(a.b) a["b"] = 2 println(a["b"]) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: map[] map[b:1] 1 2 1 2 true false map[] map[b:1] 1 2
Example (VmModules) ¶
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 (VmQuickStart) ¶
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 := ` // declare variables x = 1 y = x + 1 // print using outside the script defined println function println(x + y) // 3 // if else statement if x < 1 || y < 1 { println(x) } else if x < 1 && y < 1 { println(y) } else { println(x + y) } // slice a = []interface{1, 2, 3} println(a) // [1 2 3] println(a[0]) // 1 // map a = map[interface]interface{"x": 1} println(a) // map[x:1] a.b = 2 a["c"] = 3 println(a["b"]) // 2 println(a.c) // 3 // function func a (x) { println(x + 1) } a(3) // 4 ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: 3 3 [1 2 3] 1 map[x:1] 2 3 4
Example (VmRegexp) ¶
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") regexp = import("regexp") re = regexp.MustCompile("^simple$") result = re.MatchString("simple") fmt.Println(result) fmt.Println("") re = regexp.MustCompile("simple") result = re.FindString("This is a simple sentence") fmt.Println(result) fmt.Println("") re = regexp.MustCompile(",") result = re.Split("a,b,c", -1) fmt.Println(result) fmt.Println("") re = regexp.MustCompile("foo") result = re.ReplaceAllString("foo", "bar") fmt.Println(result) ` _, err := env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: true simple [a b c] bar
Example (VmSlices) ¶
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 = "abc" println(a[1:]) println(a[:2]) println(a[1:2]) println("") a = [1, 2, 3] println(a[1:]) println(a[:2]) println(a[1:2]) ` _, err = env.Execute(script) if err != nil { log.Fatalf("execute error: %v\n", err) } }
Output: bc ab b [2 3] [1 2] [2]
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 Run(stmt ast.Stmt, env *Env) (interface{}, error)
- func RunContext(ctx context.Context, stmt ast.Stmt, env *Env) (interface{}, error)
- 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) Copy() *Env
- func (e *Env) DeepCopy() *Env
- 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) Dump()
- func (e *Env) Execute(src string) (interface{}, error)
- func (e *Env) ExecuteContext(ctx context.Context, 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) Run(stmt ast.Stmt) (interface{}, error)
- func (e *Env) RunContext(ctx context.Context, stmt ast.Stmt) (interface{}, error)
- 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
Examples ¶
- Package (VmArrays)
- Package (VmBasicOperators)
- Package (VmChannels)
- Package (VmComparisonOperators)
- Package (VmForLoops)
- Package (VmFunctions)
- Package (VmFunctionsOutside)
- Package (VmFunctionsScope)
- Package (VmHelloWorld)
- Package (VmHttp)
- Package (VmIfOperators)
- Package (VmMaps)
- Package (VmModules)
- Package (VmQuickStart)
- Package (VmRegexp)
- Package (VmSlices)
- Package (VmSort)
- Env.Define
- Env.Dump
- Env.ExecuteContext
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 RunContext ¶ added in v0.0.9
RunContext executes statement in the specified environment with context.
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) DeepCopy ¶ added in v0.0.5
DeepCopy copy recursively the state of the virtual machine environment
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) ExecuteContext ¶ added in v0.0.9
ExecuteContext parses and runs source in current scope.
Example ¶
package main import ( "context" "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() } # the context should cancel before printing the next line println("this line should not be printed") ` ctx, cancel := context.WithCancel(context.Background()) go func() { close(waitChan) v, err := env.ExecuteContext(ctx, script) fmt.Println(v, err) waitGroup.Done() }() <-waitChan cancel() waitGroup.Wait() }
Output: <nil> execution interrupted
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) RunContext ¶ added in v0.0.9
RunContext runs statement in current scope.
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