vm

package
v0.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 4, 2021 License: MIT Imports: 9 Imported by: 88

Documentation

Overview

Package vm implements virtual-machine for anko.

Example (VmArrays)
package main

import (
	"fmt"
	"log"

	"github.com/mattn/anko/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, script)
	if err != nil {
		log.Fatalf("execute error: %v\n", err)
	}

}
Output:

true
false
true
false

true
false
true
false

false
true
Example (VmEnv)
package main

import (
	"fmt"
	"log"

	"github.com/mattn/anko/env"
)

func main() {
	// "github.com/mattn/anko/env"

	e := env.NewEnv()

	err := e.Define("a", "a")
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}

	_, err = e.Get("a")
	if err != nil {
		log.Fatalf("get error: %v\n", err)
	}

	fmt.Println(e)

}
Output:

No parent
a = "a"
Example (VmEnvDefine)
package main

import (
	"fmt"
	"log"

	"github.com/mattn/anko/env"
	"github.com/mattn/anko/vm"
)

func main() {
	// "github.com/mattn/anko/env"

	e := env.NewEnv()

	err := e.Define("println", fmt.Println)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}

	err = e.Define("a", true)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.Define("b", int64(1))
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.Define("c", float64(1.1))
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.Define("d", "d")
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.Define("e", []interface{}{true, int64(1), float64(1.1), "d"})
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.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 = vm.Execute(e, nil, 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]
Example (VmExecuteContext)
package main

import (
	"context"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/mattn/anko/env"
	"github.com/mattn/anko/vm"
)

func main() {
	var waitGroup sync.WaitGroup
	waitGroup.Add(1)
	waitChan := make(chan struct{}, 1)

	e := env.NewEnv()
	sleepMillisecond := func() { time.Sleep(time.Millisecond) }

	err := e.Define("println", fmt.Println)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.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 := vm.ExecuteContext(ctx, e, nil, script)
		fmt.Println(v, err)
		waitGroup.Done()
	}()

	<-waitChan
	cancel()

	waitGroup.Wait()

}
Output:

<nil> execution interrupted
Example (VmForLoops)
package main

import (
	"fmt"
	"log"

	"github.com/mattn/anko/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"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
	   }
	*/

	e := env.NewEnv()

	err := e.Define("println", fmt.Println)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}
	err = e.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 = e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	// "github.com/mattn/anko/env"

	e := env.NewEnv()

	err := e.Define("println", fmt.Println)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}

	script := `
println("Hello World :)")
`

	_, err = vm.Execute(e, nil, script)
	if err != nil {
		log.Fatalf("execute error: %v\n", err)
	}

}
Output:

Hello World :)
Example (VmHttp)
package main

import (
	"log"

	"github.com/mattn/anko/env"
	_ "github.com/mattn/anko/packages"
	"github.com/mattn/anko/vm"
)

func main() {
	// _ "github.com/mattn/anko/packages"

	e := env.NewEnv()

	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 := vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {

	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	// "github.com/mattn/anko/env"

	e := env.NewEnv()

	err := e.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

// struct
a = make(struct {
	A int64,
	B float64
})
a.A = 4
a.B = 5.5
println(a.A) // 4
println(a.B) // 5.5

// function
func a (x) {
	println(x + 1)
}
a(5) // 6
`

	_, err = vm.Execute(e, nil, script)
	if err != nil {
		log.Fatalf("execute error: %v\n", err)
	}

}
Output:

3
3
[1 2 3]
1
map[x:1]
2
3
4
5.5
6
Example (VmRegexp)
package main

import (
	"log"

	"github.com/mattn/anko/env"
	_ "github.com/mattn/anko/packages"
	"github.com/mattn/anko/vm"
)

func main() {
	// _ "github.com/mattn/anko/packages"

	e := env.NewEnv()

	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 := vm.Execute(e, nil, 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/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.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 = vm.Execute(e, nil, 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/env"
	_ "github.com/mattn/anko/packages"
	"github.com/mattn/anko/vm"
)

func main() {
	// _ "github.com/mattn/anko/packages"

	e := env.NewEnv()

	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 := vm.Execute(e, nil, script)
	if err != nil {
		log.Fatalf("execute error: %v\n", err)
	}

}
Output:

[f 1.1 2 3 4.4 5]
Example (VmStructs)
package main

import (
	"fmt"
	"log"

	"github.com/mattn/anko/env"
	"github.com/mattn/anko/vm"
)

func main() {
	e := env.NewEnv()

	err := e.Define("println", fmt.Println)
	if err != nil {
		log.Fatalf("define error: %v\n", err)
	}

	script := `
a = make(struct {
	A int64,
	B float64
})
println(a)

a.A = 1
println(a)
println(a.A)

a.B = 2.5
println(a)
println(a.B)
`

	_, err = vm.Execute(e, nil, script)
	if err != nil {
		log.Fatalf("execute error: %v\n", err)
	}

}
Output:

{0 0}
{1 0}
1
{1 2.5}
2.5

Index

Examples

Constants

This section is empty.

Variables

View Source
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 Execute added in v0.1.3

func Execute(env *env.Env, options *Options, script string) (interface{}, error)

Execute parses script and executes in the specified environment.

func ExecuteContext added in v0.1.3

func ExecuteContext(ctx context.Context, env *env.Env, options *Options, script string) (interface{}, error)

ExecuteContext parses script and executes in the specified environment with context.

func Run

func Run(env *env.Env, options *Options, stmt ast.Stmt) (interface{}, error)

Run executes statement in the specified environment.

func RunContext added in v0.0.9

func RunContext(ctx context.Context, env *env.Env, options *Options, stmt ast.Stmt) (interface{}, error)

RunContext executes statement in the specified environment with context.

Types

type Error

type Error struct {
	Message string
	Pos     ast.Position
}

Error is a VM run error.

func (*Error) Error

func (e *Error) Error() string

Error returns the VM error message.

type Options added in v0.1.3

type Options struct {
	Debug bool // run in Debug mode
}

Options provides options to run VM with

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL