Embedded anko as run.
This commit is contained in:
parent
964e9b2303
commit
5251f0fbf4
140 changed files with 21692 additions and 0 deletions
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/surdeus/goblin/src/tool/wc"
|
||||
"github.com/surdeus/goblin/src/tool/whoami"
|
||||
"github.com/surdeus/goblin/src/tool/yes"
|
||||
"github.com/surdeus/goblin/src/tool/run"
|
||||
"github.com/surdeus/gomtool/src/mtool"
|
||||
)
|
||||
|
||||
|
@ -74,6 +75,11 @@ func main() {
|
|||
"link files",
|
||||
"",
|
||||
},
|
||||
"run": mtool.Tool{
|
||||
run.Run,
|
||||
"run anko script",
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
mtool.Main("goblin", tools)
|
||||
|
|
8
src/tool/run/.github/FUNDING.yml
vendored
Normal file
8
src/tool/run/.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: mattn # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: mattn # Replace with a single Patreon username
|
||||
open_collective: mattn # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: # Replace with a single custom sponsorship URL
|
22
src/tool/run/.travis.yml
Normal file
22
src/tool/run/.travis.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
|
||||
env:
|
||||
secure: "ELC4rD8nn2l5T48WYbTfcbwGGBmNxl7LAu05hgx5AB9/KA+oD3oBKIJkZqD512gJ31Gtyla/hG9QOgU7LikfWdpGuJjVILy01ZqtgP5SSKsrTdlln1D5pK1ZyHJNrEPevb3W5PYn9ahHnjKGtpobXj4/E0sCXfRPH67jv9hffYs="
|
||||
|
||||
before_install:
|
||||
- go get -u github.com/haya14busa/goverage
|
||||
|
||||
script:
|
||||
- goverage -v -coverprofile=coverage.txt -covermode=count ./vm ./env . ./ast/astutil
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
21
src/tool/run/LICENSE
Normal file
21
src/tool/run/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2018 Yasuhiro Matsumoto, http://mattn.kaoriya.net <mattn.jp@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
155
src/tool/run/README.md
Normal file
155
src/tool/run/README.md
Normal file
|
@ -0,0 +1,155 @@
|
|||
# Anko
|
||||
|
||||
[![GoDoc Reference](https://godoc.org/github.com/surdeus/goblin/src/tool/run/vm?status.svg)](http://godoc.org/github.com/surdeus/goblin/src/tool/run/vm)
|
||||
[![Build Status](https://travis-ci.org/mattn/anko.svg?branch=master)](https://travis-ci.org/mattn/anko)
|
||||
[![Financial Contributors on Open Collective](https://opencollective.com/mattn-anko/all/badge.svg?label=financial+contributors)](https://opencollective.com/mattn-anko) [![Coverage](https://codecov.io/gh/mattn/anko/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/anko)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/surdeus/goblin/src/tool/run)](https://goreportcard.com/report/github.com/surdeus/goblin/src/tool/run)
|
||||
|
||||
Anko is a scriptable interpreter written in Go.
|
||||
|
||||
![](https://raw.githubusercontent.com/mattn/anko/master/anko.png)
|
||||
|
||||
(Picture licensed under CC BY-SA 3.0, photo by Ocdp)
|
||||
|
||||
|
||||
## Usage Example - Embedded
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
"github.com/surdeus/goblin/src/tool/run/vm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
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 :)
|
||||
}
|
||||
```
|
||||
|
||||
More examples are located in the GoDoc:
|
||||
|
||||
https://godoc.org/github.com/surdeus/goblin/src/tool/run/vm
|
||||
|
||||
|
||||
## Usage Example - Command Line
|
||||
|
||||
### Building
|
||||
```
|
||||
go get github.com/surdeus/goblin/src/tool/run
|
||||
go install github.com/surdeus/goblin/src/tool/run
|
||||
```
|
||||
|
||||
### Running an Anko script file named script.ank
|
||||
```
|
||||
./anko script.ank
|
||||
```
|
||||
|
||||
## Anko Script Quick Start
|
||||
```
|
||||
// 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
|
||||
```
|
||||
|
||||
|
||||
## Please note that the master branch is not stable
|
||||
|
||||
The master branch language and API may change at any time.
|
||||
|
||||
To mitigate breaking changes, please use tagged branches. New tagged branches will be created for breaking changes.
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
||||
|
||||
## Contributors
|
||||
|
||||
### Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
<a href="https://github.com/surdeus/goblin/src/tool/run/graphs/contributors"><img src="https://opencollective.com/mattn-anko/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
### Financial Contributors
|
||||
|
||||
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/mattn-anko/contribute)]
|
||||
|
||||
#### Individuals
|
||||
|
||||
<a href="https://opencollective.com/mattn-anko"><img src="https://opencollective.com/mattn-anko/individuals.svg?width=890"></a>
|
||||
|
||||
#### Organizations
|
||||
|
||||
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/mattn-anko/contribute)]
|
||||
|
||||
<a href="https://opencollective.com/mattn-anko/organization/0/website"><img src="https://opencollective.com/mattn-anko/organization/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/1/website"><img src="https://opencollective.com/mattn-anko/organization/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/2/website"><img src="https://opencollective.com/mattn-anko/organization/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/3/website"><img src="https://opencollective.com/mattn-anko/organization/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/4/website"><img src="https://opencollective.com/mattn-anko/organization/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/5/website"><img src="https://opencollective.com/mattn-anko/organization/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/6/website"><img src="https://opencollective.com/mattn-anko/organization/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/7/website"><img src="https://opencollective.com/mattn-anko/organization/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/8/website"><img src="https://opencollective.com/mattn-anko/organization/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mattn-anko/organization/9/website"><img src="https://opencollective.com/mattn-anko/organization/9/avatar.svg"></a>
|
9
src/tool/run/_example/scripts/anonymous-call.ank
Normal file
9
src/tool/run/_example/scripts/anonymous-call.ank
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!anko
|
||||
|
||||
func(x) {
|
||||
return func(y) {
|
||||
x(y)
|
||||
}
|
||||
}(func(z) {
|
||||
println("Yay!", z)
|
||||
})("hello world")
|
13
src/tool/run/_example/scripts/chan.ank
Normal file
13
src/tool/run/_example/scripts/chan.ank
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!anko
|
||||
|
||||
c = make(chan int64)
|
||||
|
||||
go func() {
|
||||
c <- 1
|
||||
c <- 2
|
||||
c <- 3
|
||||
}()
|
||||
|
||||
println(<-c)
|
||||
println(<-c)
|
||||
println(<-c)
|
9
src/tool/run/_example/scripts/env.ank
Normal file
9
src/tool/run/_example/scripts/env.ank
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!anko
|
||||
|
||||
var os, runtime = import("os"), import("runtime")
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
println(os.Getenv("USERPROFILE"))
|
||||
} else {
|
||||
println(os.Getenv("HOME"))
|
||||
}
|
70
src/tool/run/_example/scripts/example.ank
Normal file
70
src/tool/run/_example/scripts/example.ank
Normal file
|
@ -0,0 +1,70 @@
|
|||
#!anko
|
||||
|
||||
# declare function
|
||||
func foo(x){
|
||||
return x + 1
|
||||
}
|
||||
|
||||
func bar(x ...){
|
||||
return len(x)
|
||||
}
|
||||
|
||||
# declare variables
|
||||
x = 1
|
||||
y = x + 1
|
||||
|
||||
# print values
|
||||
println(x * (y + 2 * x + foo(x) / 2))
|
||||
|
||||
# if/else condition
|
||||
if foo(y) >= 1 {
|
||||
println("こんにちわ世界")
|
||||
} else {
|
||||
println("Hello, World")
|
||||
}
|
||||
|
||||
# array type
|
||||
a = [1,2,3]
|
||||
println(a)
|
||||
println(a[2])
|
||||
println(len(a))
|
||||
|
||||
# map type
|
||||
m = {"foo": "bar", "bar": "baz"}
|
||||
for k in keys(m) {
|
||||
println(m[k])
|
||||
}
|
||||
|
||||
f = func(a) {
|
||||
println(a)
|
||||
}
|
||||
|
||||
f("あんこ")
|
||||
|
||||
f = func(a ...) {
|
||||
println(a)
|
||||
}
|
||||
|
||||
f("あんこ", "だいすき")
|
||||
|
||||
println(1 && 2)
|
||||
|
||||
println(bar(1,2,3))
|
||||
println("foo")
|
||||
println(toByteSlice("あいう"))
|
||||
println(toRuneSlice("あいう"))
|
||||
|
||||
a = 1
|
||||
func foo() {
|
||||
a = 2
|
||||
}
|
||||
foo()
|
||||
println(a)
|
||||
|
||||
module Foo {
|
||||
func bar1() {
|
||||
println("Foo.bar1")
|
||||
}
|
||||
}
|
||||
|
||||
println(Foo.bar1())
|
7
src/tool/run/_example/scripts/exec.ank
Normal file
7
src/tool/run/_example/scripts/exec.ank
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!anko
|
||||
|
||||
var os, exec = import("os"), import("os/exec")
|
||||
|
||||
cmd = exec.Command("ls", "-la")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Run()
|
15
src/tool/run/_example/scripts/fib-for.ank
Normal file
15
src/tool/run/_example/scripts/fib-for.ank
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!anko
|
||||
|
||||
func fib(n) {
|
||||
a, b = 1, 1
|
||||
f = []
|
||||
for i in range(n) {
|
||||
f += a
|
||||
b += a
|
||||
a = b - a
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
||||
println(fib(20))
|
14
src/tool/run/_example/scripts/fib-recursion.ank
Normal file
14
src/tool/run/_example/scripts/fib-recursion.ank
Normal file
|
@ -0,0 +1,14 @@
|
|||
#!anko
|
||||
|
||||
func fib(n) {
|
||||
if n == 1 {
|
||||
return [1]
|
||||
} else if n == 2 {
|
||||
return [1,1]
|
||||
} else {
|
||||
t = fib(n-1)
|
||||
return t + (t[len(t)-1] + t[len(t)-2])
|
||||
}
|
||||
}
|
||||
|
||||
println(fib(20))
|
12
src/tool/run/_example/scripts/for-break-continue.ank
Normal file
12
src/tool/run/_example/scripts/for-break-continue.ank
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!anko
|
||||
|
||||
for i in [1,2,3,4,5] {
|
||||
if i == 2 {
|
||||
continue
|
||||
}
|
||||
println(i)
|
||||
if i > 3 {
|
||||
break
|
||||
}
|
||||
println("foo")
|
||||
}
|
8
src/tool/run/_example/scripts/http.ank
Normal file
8
src/tool/run/_example/scripts/http.ank
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!anko
|
||||
|
||||
var http, ioutil = import("net/http"), import("io/ioutil")
|
||||
|
||||
r = http.DefaultClient.Get("http://golang.org/")
|
||||
b, _ = ioutil.ReadAll(r[0].Body)
|
||||
printf("%s", toString(b))
|
||||
r[0].Body.Close()
|
10
src/tool/run/_example/scripts/module.ank
Normal file
10
src/tool/run/_example/scripts/module.ank
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!anko
|
||||
|
||||
module Foo {
|
||||
func bar1() {
|
||||
println("Foo.bar1")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
println(Foo.bar1())
|
8
src/tool/run/_example/scripts/regexp.ank
Normal file
8
src/tool/run/_example/scripts/regexp.ank
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!anko
|
||||
|
||||
var regexp = import("regexp")
|
||||
|
||||
for s in regexp.MustCompile(`[\s_]`).Split("foo_bar_baz", -1) {
|
||||
println(s)
|
||||
}
|
||||
|
8
src/tool/run/_example/scripts/server.ank
Normal file
8
src/tool/run/_example/scripts/server.ank
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!anko
|
||||
|
||||
var http = import("net/http")
|
||||
|
||||
http.HandleFunc("/", func(w, r) {
|
||||
w.Write(toByteSlice("hello world"))
|
||||
})
|
||||
http.ListenAndServe(":8080", nil)
|
14
src/tool/run/_example/scripts/signal.ank
Normal file
14
src/tool/run/_example/scripts/signal.ank
Normal file
|
@ -0,0 +1,14 @@
|
|||
#!anko
|
||||
|
||||
var os, signal, time = import("os"), import("os/signal"), import("time")
|
||||
|
||||
c = make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
<-c
|
||||
println("CTRL-C")
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
d, _ = time.ParseDuration("10s")
|
||||
time.Sleep(d)
|
10
src/tool/run/_example/scripts/slice.ank
Normal file
10
src/tool/run/_example/scripts/slice.ank
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!anko
|
||||
|
||||
a = make([]int64, 5)
|
||||
|
||||
for i = 0; i < len(a); i++ {
|
||||
a[i] = i
|
||||
}
|
||||
for i in a {
|
||||
println(i)
|
||||
}
|
26
src/tool/run/_example/scripts/socket.ank
Normal file
26
src/tool/run/_example/scripts/socket.ank
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!anko
|
||||
|
||||
var os, net, url, ioutil = import("os"), import("net"), import("net/url"), import("io/ioutil");
|
||||
|
||||
func connect(uri) {
|
||||
proxy = os.Getenv("http_proxy")
|
||||
if proxy != "" {
|
||||
u, e = url.Parse(proxy)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return net.Dial("tcp", u.Host)
|
||||
}
|
||||
return net.Dial("tcp", uri)
|
||||
}
|
||||
|
||||
c, e = connect("www.google.com:80")
|
||||
if e != nil {
|
||||
throw e
|
||||
}
|
||||
c.Write(toByteSlice("GET http://www.google.com/ HTTP/1.0\r\n\r\n"))
|
||||
b, e = ioutil.ReadAll(c)
|
||||
if e != nil {
|
||||
throw e
|
||||
}
|
||||
printf("%s", b)
|
123
src/tool/run/_example/scripts/toType.ank
Normal file
123
src/tool/run/_example/scripts/toType.ank
Normal file
|
@ -0,0 +1,123 @@
|
|||
#!anko
|
||||
|
||||
# toInt with ints, floats, strings, bools
|
||||
println("\ntoInt examples:\n===============")
|
||||
i = 1<<63 - 1
|
||||
println("int", i, "toInt:", toInt(i))
|
||||
|
||||
i = -1 << 63
|
||||
println("int", i, "toInt:", toInt(i))
|
||||
|
||||
f = 3.141592653589793
|
||||
println("float", f, "toInt:", toInt(f))
|
||||
|
||||
f = 1.797693134862315708145274237317043567981e18
|
||||
println("float", f, "toInt:", toInt(f))
|
||||
|
||||
f = -1.797693134862315708145274237317043567981e18
|
||||
println("float", f, "toInt:", toInt(f))
|
||||
|
||||
s = "4611686018427387904"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
s = "-9223372036854775808"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
s = "3.141592653589793"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
s = "1.797693134862315708145274237317043567981e18"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
s = "-1.797693134862315708145274237317043567981e18"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
s = "1.797693134862315708145274237317043567981e-18"
|
||||
println("string", s, "toInt:", toInt(s))
|
||||
|
||||
b = true
|
||||
println("bool", b, "toInt:", toInt(b))
|
||||
|
||||
b = false
|
||||
println("bool", b, "toInt:", toInt(b))
|
||||
|
||||
println("\ntoFloat examples:\n=================")
|
||||
i = 1<<63 - 1
|
||||
println("int", i, "toFloat:", toFloat(i))
|
||||
|
||||
i = -1 << 63
|
||||
println("int", i, "toFloat:", toFloat(i))
|
||||
|
||||
s = "4611686018427387904"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
s = "-9223372036854775808"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
s = "3.141592653589793"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
s = "1.797693134862315708145274237317043567981e18"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
s = "-1.797693134862315708145274237317043567981e18"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
s = "1.797693134862315708145274237317043567981e-18"
|
||||
println("string", s, "toFloat:", toFloat(s))
|
||||
|
||||
b = true
|
||||
println("bool", b, "toFloat:", toFloat(b))
|
||||
|
||||
b = false
|
||||
println("bool", b, "toFloat:", toFloat(b))
|
||||
|
||||
println("\ntoBool examples:\n================")
|
||||
i = 1
|
||||
println("int", i, "toBool:", toBool(i))
|
||||
|
||||
i = 0
|
||||
println("int", i, "toBool:", toBool(i))
|
||||
|
||||
i = -1
|
||||
println("int", i, "toBool:", toBool(i))
|
||||
|
||||
f = 1.0
|
||||
println("float", f, "toBool:", toBool(f))
|
||||
|
||||
f = 0.000000000001
|
||||
println("float", f, "toBool:", toBool(f))
|
||||
|
||||
f = 0.0
|
||||
println("float", f, "toBool:", toBool(f))
|
||||
|
||||
f = -0.0
|
||||
println("float", f, "toBool:", toBool(f))
|
||||
|
||||
s = "y"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "yEs"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "t"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "TrUe"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "1"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "0"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "f"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "FaLsE"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
||||
s = "foobar"
|
||||
println("string", s, "toBool:", toBool(s))
|
||||
|
19
src/tool/run/_example/scripts/try-catch.ank
Normal file
19
src/tool/run/_example/scripts/try-catch.ank
Normal file
|
@ -0,0 +1,19 @@
|
|||
#!anko
|
||||
|
||||
var http = import("net/http")
|
||||
|
||||
try {
|
||||
http.Do()
|
||||
} catch {
|
||||
println("catch!")
|
||||
} finally {
|
||||
println("finally!")
|
||||
}
|
||||
|
||||
try {
|
||||
http.Do()
|
||||
} catch e {
|
||||
println("catch!", e)
|
||||
} finally {
|
||||
println("finally!")
|
||||
}
|
7
src/tool/run/_example/scripts/url.ank
Normal file
7
src/tool/run/_example/scripts/url.ank
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!anko
|
||||
|
||||
var url = import("net/url")
|
||||
|
||||
u, _ = url.Parse("http://www.google.com/search?q=こんにちわ世界")
|
||||
println(u.Path)
|
||||
println(u.Host)
|
15
src/tool/run/_example/scripts/z-combinator.ank
Normal file
15
src/tool/run/_example/scripts/z-combinator.ank
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!anko
|
||||
|
||||
func Z(f) {
|
||||
return (func(x) {
|
||||
return f(func(y) {
|
||||
return x(x)(y)
|
||||
})
|
||||
})(func(x) {
|
||||
return f(func(y) {
|
||||
return x(x)(y)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
println(Z(func(f) { return func(n) { return n == 0 ? 1 : n * f(n - 1) } })(5) == 120)
|
172
src/tool/run/anko.go
Normal file
172
src/tool/run/anko.go
Normal file
|
@ -0,0 +1,172 @@
|
|||
// +build !appengine
|
||||
|
||||
package run
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
//"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/core"
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
_ "github.com/surdeus/goblin/src/tool/run/packages"
|
||||
"github.com/surdeus/goblin/src/tool/run/parser"
|
||||
"github.com/surdeus/goblin/src/tool/run/vm"
|
||||
"github.com/surdeus/gomtool/src/mtool"
|
||||
)
|
||||
|
||||
const version = "0.1.8"
|
||||
|
||||
var (
|
||||
flagExecute string
|
||||
file string
|
||||
args []string
|
||||
e *env.Env
|
||||
flag *mtool.Flags
|
||||
)
|
||||
|
||||
func Run(flagSet *mtool.Flags) {
|
||||
var exitCode int
|
||||
|
||||
flag = flagSet
|
||||
|
||||
parseFlags()
|
||||
setupEnv()
|
||||
if flagExecute != "" || flag.NArg() > 0 {
|
||||
exitCode = runNonInteractive()
|
||||
} else {
|
||||
exitCode = runInteractive()
|
||||
}
|
||||
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func parseFlags() {
|
||||
flagVersion := flag.Bool("v", false, "prints out the version and then exits")
|
||||
flag.StringVar(&flagExecute, "e", "", "execute the Anko code")
|
||||
flag.Parse()
|
||||
|
||||
if *flagVersion {
|
||||
fmt.Println(version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if flagExecute != "" || flag.NArg() < 1 {
|
||||
args = flag.Args()
|
||||
return
|
||||
}
|
||||
|
||||
file = flag.Arg(0)
|
||||
args = flag.Args()[1:]
|
||||
}
|
||||
|
||||
func setupEnv() {
|
||||
e = env.NewEnv()
|
||||
e.Define("args", args)
|
||||
core.Import(e)
|
||||
}
|
||||
|
||||
func runNonInteractive() int {
|
||||
var source string
|
||||
if flagExecute != "" {
|
||||
source = flagExecute
|
||||
} else {
|
||||
sourceBytes, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println("ReadFile error:", err)
|
||||
return 2
|
||||
}
|
||||
source = string(sourceBytes)
|
||||
}
|
||||
|
||||
_, err := vm.Execute(e, nil, source)
|
||||
if err != nil {
|
||||
fmt.Println("Execute error:", err)
|
||||
return 4
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func runInteractive() int {
|
||||
var following bool
|
||||
var source string
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
parser.EnableErrorVerbose()
|
||||
|
||||
for {
|
||||
if following {
|
||||
source += "\n"
|
||||
fmt.Print(" ")
|
||||
} else {
|
||||
fmt.Print("> ")
|
||||
}
|
||||
|
||||
if !scanner.Scan() {
|
||||
break
|
||||
}
|
||||
source += scanner.Text()
|
||||
if source == "" {
|
||||
continue
|
||||
}
|
||||
if source == "quit()" {
|
||||
break
|
||||
}
|
||||
|
||||
stmts, err := parser.ParseSrc(source)
|
||||
|
||||
if e, ok := err.(*parser.Error); ok {
|
||||
es := e.Error()
|
||||
if strings.HasPrefix(es, "syntax error: unexpected") {
|
||||
if strings.HasPrefix(es, "syntax error: unexpected $end,") {
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if e.Pos.Column == len(source) && !e.Fatal {
|
||||
fmt.Fprintln(os.Stderr, e)
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
if e.Error() == "unexpected EOF" {
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
following = false
|
||||
source = ""
|
||||
var v interface{}
|
||||
|
||||
if err == nil {
|
||||
v, err = vm.Run(e, nil, stmts)
|
||||
}
|
||||
if err != nil {
|
||||
if e, ok := err.(*vm.Error); ok {
|
||||
fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err)
|
||||
} else if e, ok := err.(*parser.Error); ok {
|
||||
fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%#v\n", v)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
if err != io.EOF {
|
||||
fmt.Fprintln(os.Stderr, "ReadString error:", err)
|
||||
return 12
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
BIN
src/tool/run/anko.png
Normal file
BIN
src/tool/run/anko.png
Normal file
Binary file not shown.
273
src/tool/run/anko_test.go
Normal file
273
src/tool/run/anko_test.go
Normal file
|
@ -0,0 +1,273 @@
|
|||
// +build !appengine
|
||||
|
||||
package run
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var logger *log.Logger
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
parseFlags()
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestRunNonInteractiveFile(t *testing.T) {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
testDir := filepath.Join(filepath.Dir(filename), "core", "testdata")
|
||||
setupEnv()
|
||||
|
||||
file = filepath.Join(testDir, "not-found.ank")
|
||||
exitCode := runNonInteractive()
|
||||
if exitCode != 2 {
|
||||
t.Fatalf("exitCode - received: %v - expected: %v", exitCode, 2)
|
||||
}
|
||||
|
||||
file = filepath.Join(testDir, "broken.ank")
|
||||
exitCode = runNonInteractive()
|
||||
os.Args = []string{os.Args[0]}
|
||||
if exitCode != 4 {
|
||||
t.Fatalf("exitCode - received: %v - expected: %v", exitCode, 4)
|
||||
}
|
||||
|
||||
file = filepath.Join(testDir, "test.ank")
|
||||
exitCode = runNonInteractive()
|
||||
os.Args = []string{os.Args[0]}
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("exitCode - received: %v - expected: %v", exitCode, 0)
|
||||
}
|
||||
|
||||
file = ""
|
||||
}
|
||||
|
||||
func TestRunNonInteractiveExecute(t *testing.T) {
|
||||
setupEnv()
|
||||
|
||||
flagExecute = "1 + 1"
|
||||
exitCode := runNonInteractive()
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("exitCode - received: %v - expected: %v", exitCode, 0)
|
||||
}
|
||||
|
||||
flagExecute = "1++"
|
||||
exitCode = runNonInteractive()
|
||||
if exitCode != 4 {
|
||||
t.Fatalf("exitCode - received: %v - expected: %v", exitCode, 4)
|
||||
}
|
||||
|
||||
flagExecute = ""
|
||||
}
|
||||
|
||||
type testInteractive struct {
|
||||
runLines []string
|
||||
runOutputs []string
|
||||
runError string
|
||||
}
|
||||
|
||||
func TestRunInteractive(t *testing.T) {
|
||||
// empty strings in runOutputs will ignore read timeouts
|
||||
tests := []testInteractive{
|
||||
{runLines: []string{".."}, runError: "1:1 syntax error on '.' at 1:1"},
|
||||
{runLines: []string{"1++"}, runError: "1:1 invalid operation"},
|
||||
{runLines: []string{"var , b = 1, 2"}, runError: "1:7 syntax error: unexpected ','"},
|
||||
|
||||
{runLines: []string{"", "1"}, runOutputs: []string{"", "1"}},
|
||||
{runLines: []string{"1 + 1"}, runOutputs: []string{"2"}},
|
||||
{runLines: []string{"a = 1", "b = 2", "a + b"}, runOutputs: []string{"1", "2", "3"}},
|
||||
{runLines: []string{"a = 1", "if a == 1 {", "b = 1", "b = 2", "}", "a"}, runOutputs: []string{"1", "", "", "", "2", "1"}},
|
||||
{runLines: []string{"a = 1", "for i = 0; i < 2; i++ {", "a++", "}", "a"}, runOutputs: []string{"1", "", "", "<nil>", "3"}},
|
||||
{runLines: []string{"1 + 1", "// comment 1", "2 + 2 // comment 2", "// 3 + 3"}, runOutputs: []string{"2", "<nil>", "4", "<nil>"}},
|
||||
}
|
||||
runInteractiveTests(t, tests)
|
||||
}
|
||||
|
||||
func runInteractiveTests(t *testing.T, tests []testInteractive) {
|
||||
// create logger
|
||||
// Note: logger is used for debugging since real stdout cannot be used
|
||||
logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.LUTC|log.Llongfile)
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
b, err := exec.Command("go", "env", "GOPATH").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gopath = strings.TrimSpace(string(b))
|
||||
}
|
||||
filehandle, err := os.OpenFile(filepath.Join(gopath, "bin", "anko_test.log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
t.Fatal("OpenFile error:", err)
|
||||
}
|
||||
defer filehandle.Close()
|
||||
logger.SetOutput(filehandle)
|
||||
logger.Print("logger file created")
|
||||
|
||||
// defer sending std back to real
|
||||
realStdin := os.Stdin
|
||||
realStderr := os.Stderr
|
||||
realStdout := os.Stdout
|
||||
defer setStd(realStdin, realStderr, realStdout)
|
||||
|
||||
// create pipes
|
||||
readFromIn, writeToIn, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal("Pipe error:", err)
|
||||
}
|
||||
os.Stdin = readFromIn
|
||||
logger.Print("pipe in created")
|
||||
readFromErr, writeToErr, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal("Pipe error:", err)
|
||||
}
|
||||
os.Stderr = writeToErr
|
||||
logger.Print("pipe err created")
|
||||
readFromOut, writeToOut, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal("Pipe error:", err)
|
||||
}
|
||||
os.Stdout = writeToOut
|
||||
logger.Print("pipe out created")
|
||||
|
||||
// setup reader
|
||||
readerErr := bufio.NewReaderSize(readFromErr, 256)
|
||||
readerOut := bufio.NewReaderSize(readFromOut, 256)
|
||||
chanQuit := make(chan struct{}, 1)
|
||||
chanErr := make(chan string, 3)
|
||||
chanOut := make(chan string, 3)
|
||||
readTimeout := 10 * time.Millisecond
|
||||
var dataErr string
|
||||
var dataOut string
|
||||
|
||||
go readerToChan(t, chanQuit, readerErr, chanErr)
|
||||
go readerToChan(t, chanQuit, readerOut, chanOut)
|
||||
|
||||
go runInteractive()
|
||||
|
||||
time.Sleep(readTimeout)
|
||||
|
||||
// basic read and write to make sure things are working
|
||||
_, err = writeToIn.WriteString("1\n")
|
||||
if err != nil {
|
||||
t.Fatal("Stdin WriteString error:", err)
|
||||
}
|
||||
select {
|
||||
case dataOut = <-chanOut:
|
||||
if len(dataOut) > 0 && dataOut[0] == '>' {
|
||||
dataOut = dataOut[1:]
|
||||
dataOut = strings.TrimSpace(dataOut)
|
||||
}
|
||||
if dataOut != "1" {
|
||||
t.Fatalf("Stdout - received: %v - expected: %v - basic test", dataOut, "1")
|
||||
}
|
||||
case dataErr = <-chanErr:
|
||||
dataErr = strings.TrimSpace(dataErr)
|
||||
if dataErr != "" {
|
||||
t.Fatalf("Stderr - received: %v - expected: %v - basic test", dataErr, "")
|
||||
}
|
||||
case <-time.After(readTimeout):
|
||||
t.Fatal("read timeout for basic test")
|
||||
}
|
||||
|
||||
// run tests
|
||||
logger.Print("running tests start")
|
||||
for _, test := range tests {
|
||||
|
||||
for i, runLine := range test.runLines {
|
||||
|
||||
_, err = writeToIn.WriteString(runLine + "\n")
|
||||
if err != nil {
|
||||
t.Fatal("Stdin WriteString error:", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(readTimeout):
|
||||
if test.runOutputs[i] != "" {
|
||||
t.Fatalf("read timeout for i: %v - runLines: %v", i, test.runLines)
|
||||
}
|
||||
case dataOut = <-chanOut:
|
||||
for len(dataOut) > 0 && dataOut[0] == '>' {
|
||||
dataOut = dataOut[1:]
|
||||
dataOut = strings.TrimSpace(dataOut)
|
||||
}
|
||||
if dataOut != test.runOutputs[i] {
|
||||
t.Fatalf("Stdout - received: %v - expected: %v - i: %v - runLines: %v", dataOut, test.runOutputs[i], i, test.runLines)
|
||||
}
|
||||
case dataErr = <-chanErr:
|
||||
dataErr = strings.TrimSpace(dataErr)
|
||||
if dataErr != test.runError {
|
||||
t.Fatalf("Stderr - received: %v - expected: %v - i: %v - runLines: %v", dataErr, test.runError, i, test.runLines)
|
||||
}
|
||||
|
||||
// to clean output from error
|
||||
_, err = writeToIn.WriteString("1\n")
|
||||
if err != nil {
|
||||
t.Fatal("Stdin WriteString error:", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case dataOut = <-chanOut:
|
||||
for len(dataOut) > 0 && dataOut[0] == '>' {
|
||||
dataOut = dataOut[1:]
|
||||
dataOut = strings.TrimSpace(dataOut)
|
||||
}
|
||||
if dataOut != "1" {
|
||||
t.Fatalf("Stdout - received: %v - expected: %v - i: %v - runLines: %v", dataOut, test.runOutputs[i], i, test.runLines)
|
||||
}
|
||||
case <-time.After(readTimeout):
|
||||
t.Fatalf("read timeout for i: %v - runLines: %v", i, test.runLines)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
logger.Print("running tests end")
|
||||
|
||||
// quit
|
||||
_, err = writeToIn.WriteString("quit()\n")
|
||||
if err != nil {
|
||||
t.Fatal("Stdin WriteString error:", err)
|
||||
}
|
||||
logger.Print("quit() sent")
|
||||
|
||||
close(chanQuit)
|
||||
logger.Print("chanQuit closed")
|
||||
|
||||
writeToErr.Close()
|
||||
writeToOut.Close()
|
||||
logger.Print("pipes closed")
|
||||
}
|
||||
|
||||
func readerToChan(t *testing.T, chanQuit chan struct{}, reader *bufio.Reader, chanOut chan string) {
|
||||
logger.Print("readerToChan start")
|
||||
for {
|
||||
data, err := reader.ReadString('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatal("readerToChan ReadString error:", err)
|
||||
}
|
||||
select {
|
||||
case <-chanQuit:
|
||||
logger.Print("readerToChan end")
|
||||
return
|
||||
default:
|
||||
}
|
||||
chanOut <- data
|
||||
}
|
||||
}
|
||||
|
||||
func setStd(stdin *os.File, stderr *os.File, stdout *os.File) {
|
||||
os.Stdin = stdin
|
||||
os.Stderr = stderr
|
||||
os.Stdout = stdout
|
||||
}
|
38
src/tool/run/ast/ast.go
Normal file
38
src/tool/run/ast/ast.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package ast
|
||||
|
||||
// Token is used in the lexer to split characters into a string called a token
|
||||
type Token struct {
|
||||
PosImpl
|
||||
Tok int
|
||||
Lit string
|
||||
}
|
||||
|
||||
// TypeKind is the kinds of types
|
||||
type TypeKind int
|
||||
|
||||
const (
|
||||
// TypeDefault default type
|
||||
TypeDefault TypeKind = iota
|
||||
// TypePtr ptr type
|
||||
TypePtr
|
||||
// TypeSlice slice type
|
||||
TypeSlice
|
||||
// TypeMap map type
|
||||
TypeMap
|
||||
// TypeChan chan type
|
||||
TypeChan
|
||||
// TypeStructType struct type
|
||||
TypeStructType
|
||||
)
|
||||
|
||||
// TypeStruct is the type and sub-types
|
||||
type TypeStruct struct {
|
||||
Kind TypeKind
|
||||
Env []string
|
||||
Name string
|
||||
Dimensions int
|
||||
SubType *TypeStruct
|
||||
Key *TypeStruct
|
||||
StructNames []string
|
||||
StructTypes []*TypeStruct
|
||||
}
|
281
src/tool/run/ast/astutil/walk.go
Normal file
281
src/tool/run/ast/astutil/walk.go
Normal file
|
@ -0,0 +1,281 @@
|
|||
// +build !appengine
|
||||
|
||||
package astutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/ast"
|
||||
)
|
||||
|
||||
// WalkFunc is used in Walk to walk the AST
|
||||
type WalkFunc func(interface{}) error
|
||||
|
||||
// Walk walks the ASTs associated with a statement list generated by parser.ParseSrc
|
||||
// each expression and/or statement is passed to the WalkFunc function.
|
||||
// If the WalkFunc returns an error the walk is aborted and the error is returned
|
||||
func Walk(stmt ast.Stmt, f WalkFunc) error {
|
||||
return walkStmt(stmt, f)
|
||||
}
|
||||
|
||||
func walkStmts(stmts []ast.Stmt, f WalkFunc) error {
|
||||
for _, stmt := range stmts {
|
||||
if err := walkStmt(stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkExprs(exprs []ast.Expr, f WalkFunc) error {
|
||||
for _, exp := range exprs {
|
||||
if err := walkExpr(exp, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkStmt(stmt ast.Stmt, f WalkFunc) error {
|
||||
//short circuit out if there are no functions
|
||||
if stmt == nil || f == nil {
|
||||
return nil
|
||||
}
|
||||
if err := callFunc(stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
switch stmt := stmt.(type) {
|
||||
case *ast.StmtsStmt:
|
||||
if err := walkStmts(stmt.Stmts, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.BreakStmt:
|
||||
case *ast.ContinueStmt:
|
||||
case *ast.LetMapItemStmt:
|
||||
if err := walkExpr(stmt.RHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExprs(stmt.LHSS, f)
|
||||
case *ast.ReturnStmt:
|
||||
return walkExprs(stmt.Exprs, f)
|
||||
case *ast.ExprStmt:
|
||||
return walkExpr(stmt.Expr, f)
|
||||
case *ast.VarStmt:
|
||||
return walkExprs(stmt.Exprs, f)
|
||||
case *ast.LetsStmt:
|
||||
if err := walkExprs(stmt.RHSS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExprs(stmt.LHSS, f)
|
||||
case *ast.IfStmt:
|
||||
if err := walkExpr(stmt.If, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Then, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmts(stmt.ElseIf, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Else, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.TryStmt:
|
||||
if err := walkStmt(stmt.Try, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Catch, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Finally, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.LoopStmt:
|
||||
if err := walkExpr(stmt.Expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.ForStmt:
|
||||
if err := walkExpr(stmt.Value, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.CForStmt:
|
||||
if err := walkStmt(stmt.Stmt1, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkExpr(stmt.Expr2, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkExpr(stmt.Expr3, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkStmt(stmt.Stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.ThrowStmt:
|
||||
if err := walkExpr(stmt.Expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.ModuleStmt:
|
||||
if err := walkStmt(stmt.Stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.SwitchStmt:
|
||||
if err := walkExpr(stmt.Expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, switchCaseStmt := range stmt.Cases {
|
||||
caseStmt := switchCaseStmt.(*ast.SwitchCaseStmt)
|
||||
if err := walkStmt(caseStmt.Stmt, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := walkStmt(stmt.Default, f); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ast.GoroutineStmt:
|
||||
return walkExpr(stmt.Expr, f)
|
||||
default:
|
||||
return fmt.Errorf("unknown statement %v", reflect.TypeOf(stmt))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkExpr(expr ast.Expr, f WalkFunc) error {
|
||||
//short circuit out if there are no functions
|
||||
if expr == nil || f == nil {
|
||||
return nil
|
||||
}
|
||||
if err := callFunc(expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
switch expr := expr.(type) {
|
||||
case *ast.OpExpr:
|
||||
return walkOperator(expr.Op, f)
|
||||
case *ast.LenExpr:
|
||||
case *ast.LiteralExpr:
|
||||
case *ast.IdentExpr:
|
||||
case *ast.MemberExpr:
|
||||
return walkExpr(expr.Expr, f)
|
||||
case *ast.ItemExpr:
|
||||
if err := walkExpr(expr.Item, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.Index, f)
|
||||
case *ast.SliceExpr:
|
||||
if err := walkExpr(expr.Item, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkExpr(expr.Begin, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.End, f)
|
||||
case *ast.ArrayExpr:
|
||||
return walkExprs(expr.Exprs, f)
|
||||
case *ast.MapExpr:
|
||||
for i := range expr.Keys {
|
||||
if err := walkExpr(expr.Keys[i], f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkExpr(expr.Values[i], f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case *ast.DerefExpr:
|
||||
return walkExpr(expr.Expr, f)
|
||||
case *ast.AddrExpr:
|
||||
return walkExpr(expr.Expr, f)
|
||||
case *ast.UnaryExpr:
|
||||
return walkExpr(expr.Expr, f)
|
||||
case *ast.ParenExpr:
|
||||
return walkExpr(expr.SubExpr, f)
|
||||
case *ast.FuncExpr:
|
||||
return walkStmt(expr.Stmt, f)
|
||||
case *ast.LetsExpr:
|
||||
if err := walkExprs(expr.LHSS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExprs(expr.RHSS, f)
|
||||
case *ast.AnonCallExpr:
|
||||
if err := walkExpr(expr.Expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(&ast.CallExpr{Func: reflect.Value{}, SubExprs: expr.SubExprs, VarArg: expr.VarArg, Go: expr.Go}, f)
|
||||
case *ast.CallExpr:
|
||||
return walkExprs(expr.SubExprs, f)
|
||||
case *ast.TernaryOpExpr:
|
||||
if err := walkExpr(expr.Expr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := walkExpr(expr.LHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.RHS, f)
|
||||
case *ast.ImportExpr:
|
||||
return walkExpr(expr.Name, f)
|
||||
case *ast.MakeExpr:
|
||||
if err := walkExpr(expr.LenExpr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.CapExpr, f)
|
||||
case *ast.ChanExpr:
|
||||
if err := walkExpr(expr.RHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.LHS, f)
|
||||
case *ast.IncludeExpr:
|
||||
if err := walkExpr(expr.ItemExpr, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(expr.ListExpr, f)
|
||||
default:
|
||||
return fmt.Errorf("unknown expression %v", reflect.TypeOf(expr))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkOperator(op ast.Operator, f WalkFunc) error {
|
||||
//short circuit out if there are no functions
|
||||
if op == nil || f == nil {
|
||||
return nil
|
||||
}
|
||||
if err := callFunc(op, f); err != nil {
|
||||
return err
|
||||
}
|
||||
switch op := op.(type) {
|
||||
case *ast.BinaryOperator:
|
||||
if err := walkExpr(op.LHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(op.RHS, f)
|
||||
case *ast.ComparisonOperator:
|
||||
if err := walkExpr(op.LHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(op.RHS, f)
|
||||
case *ast.AddOperator:
|
||||
if err := walkExpr(op.LHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(op.RHS, f)
|
||||
case *ast.MultiplyOperator:
|
||||
if err := walkExpr(op.LHS, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return walkExpr(op.RHS, f)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func callFunc(x interface{}, f WalkFunc) error {
|
||||
if x == nil || f == nil {
|
||||
return nil
|
||||
}
|
||||
return f(x)
|
||||
}
|
239
src/tool/run/ast/astutil/walk_test.go
Normal file
239
src/tool/run/ast/astutil/walk_test.go
Normal file
|
@ -0,0 +1,239 @@
|
|||
package astutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/ast"
|
||||
"github.com/surdeus/goblin/src/tool/run/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
goodSrc string = `
|
||||
var fmt = import("fmt")
|
||||
|
||||
a = "1"
|
||||
b = 2
|
||||
m = {}
|
||||
func testA(arg1, arg2, arg3) {
|
||||
v, ok = m["foo"]
|
||||
return "A" + arg1 + arg2 + arg3
|
||||
}
|
||||
|
||||
func Main(arg1) {
|
||||
fmt.Println("enter Main")
|
||||
b = testA(1, 2, 3) + Tester()
|
||||
|
||||
if b == 0 {
|
||||
fmt.Println("b is 0")
|
||||
} else if b == 1 {
|
||||
fmt.Println("b is 1")
|
||||
} else {
|
||||
fmt.Println("b is other")
|
||||
}
|
||||
|
||||
switch arg1 {
|
||||
case 0:
|
||||
fmt.Println("arg0 is 0")
|
||||
case 1:
|
||||
fmt.Println("arg0 is 1")
|
||||
default:
|
||||
fmt.Println("arg0 is other")
|
||||
}
|
||||
|
||||
try {
|
||||
throw "WTF!"
|
||||
} catch e {
|
||||
fmt.Println(e)
|
||||
}
|
||||
|
||||
for n = 0; n < 3; n++ {
|
||||
if n < 2 {
|
||||
continue
|
||||
}
|
||||
fmt.Println(n)
|
||||
}
|
||||
|
||||
for n in [1, 2, 3, 4, 5] {
|
||||
fmt.Println(n)
|
||||
if n > 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
n = 0
|
||||
for n < 3 {
|
||||
n++
|
||||
}
|
||||
|
||||
a = {"foo": "bar"}
|
||||
a.foo = "baz"
|
||||
if a["foo"] == "zoo" {
|
||||
fmt.Println("foo is zoo")
|
||||
}
|
||||
fmt.Println(a["foo"] == "zoo" ? "zoo" : "baz")
|
||||
|
||||
c = make(chan int64)
|
||||
|
||||
go func() {
|
||||
c <- 1
|
||||
c <- 2
|
||||
c <- 3
|
||||
}()
|
||||
|
||||
println(<-c)
|
||||
println(<-c)
|
||||
println(<-c)
|
||||
|
||||
v = make([]int, 3)
|
||||
fmt.Println("sizeof v is ", len(v))
|
||||
|
||||
x = 1
|
||||
y = (&x)
|
||||
*y = 2
|
||||
fmt.Println(x)
|
||||
|
||||
x, y = !x, 2
|
||||
fmt.Println(x, y)
|
||||
|
||||
x = new(string)
|
||||
fmt.Println(x)
|
||||
|
||||
var f = func() {
|
||||
return "foo"
|
||||
}
|
||||
x = f()[0:1]
|
||||
y = f()[0]
|
||||
fmt.Println(x == y ? true : false)
|
||||
}
|
||||
|
||||
func Tester() {
|
||||
return "YES"
|
||||
}
|
||||
|
||||
func testLen() {
|
||||
return len("test")
|
||||
}
|
||||
|
||||
fmt.Println(Main(1))
|
||||
`
|
||||
)
|
||||
|
||||
func TestWalk(t *testing.T) {
|
||||
stmts, err := parser.ParseSrc(goodSrc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var mainFound bool
|
||||
var lenFound bool
|
||||
err = Walk(stmts, func(e interface{}) error {
|
||||
switch exp := e.(type) {
|
||||
case *ast.CallExpr:
|
||||
switch exp.Name {
|
||||
case `testA`:
|
||||
if len(exp.SubExprs) != 3 {
|
||||
return errors.New("invalid parameter count")
|
||||
}
|
||||
case `Main`:
|
||||
if len(exp.SubExprs) != 1 {
|
||||
return errors.New("invalid parameter count")
|
||||
}
|
||||
case `Tester`:
|
||||
if len(exp.SubExprs) != 0 {
|
||||
return errors.New("invalid parameter count")
|
||||
}
|
||||
}
|
||||
case *ast.FuncExpr:
|
||||
if !mainFound && exp.Name == `Main` {
|
||||
mainFound = true
|
||||
} else if mainFound && exp.Name == `Main` {
|
||||
return errors.New("Main redefined")
|
||||
}
|
||||
case *ast.LenExpr:
|
||||
lenFound = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !mainFound {
|
||||
t.Fatal("Main not found")
|
||||
}
|
||||
if !lenFound {
|
||||
t.Fatal("len not found")
|
||||
}
|
||||
}
|
||||
|
||||
func Example_astWalk() {
|
||||
src := `
|
||||
var fmt = import("fmt")
|
||||
|
||||
func TestFunc(arg1, arg2, arg3) {
|
||||
return (arg1 + arg2) * arg3
|
||||
}
|
||||
|
||||
func Main() {
|
||||
return TestFunc(1, 2, 3) + BuiltinFuncX(1, 2, 3)
|
||||
}
|
||||
|
||||
fmt.Println(Main())
|
||||
`
|
||||
stmts, err := parser.ParseSrc(src)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
return
|
||||
}
|
||||
var mainFound bool
|
||||
err = Walk(stmts, func(e interface{}) error {
|
||||
switch e := e.(type) {
|
||||
case *ast.CallExpr:
|
||||
//check if the BuiltinFuncX is getting the right number of args
|
||||
if e.Name == `BuiltinFuncX` && len(e.SubExprs) != 3 {
|
||||
return errors.New("invalid number of arguments to BuiltinFuncX")
|
||||
}
|
||||
case *ast.FuncExpr:
|
||||
if !mainFound && e.Name == `Main` {
|
||||
if len(e.Params) != 0 {
|
||||
return errors.New("Too many args to main")
|
||||
}
|
||||
mainFound = true
|
||||
} else if mainFound && e.Name == `Main` {
|
||||
return errors.New("Main redefined")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
return
|
||||
}
|
||||
if !mainFound {
|
||||
fmt.Println("ERROR: Main not found")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadCode(t *testing.T) {
|
||||
var codes = []string{
|
||||
`const 1 = 2`,
|
||||
`a["foo"] = 2, 3`,
|
||||
`if a, 2 {}`,
|
||||
`if break {}`,
|
||||
`if a { else }`,
|
||||
`if a { } else foo { }`,
|
||||
`try a { } else { }`,
|
||||
`try { } catch 1, 2 { }`,
|
||||
`throw 1, 2`,
|
||||
`for.true`,
|
||||
`switch { var }`,
|
||||
`case { var }`,
|
||||
`v, ok = { "foo": "bar" }[const 1]`,
|
||||
}
|
||||
for _, code := range codes {
|
||||
_, err := parser.ParseSrc(code)
|
||||
if err == nil {
|
||||
t.Fatalf("code %q should fail", code)
|
||||
}
|
||||
}
|
||||
}
|
2
src/tool/run/ast/doc.go
Normal file
2
src/tool/run/ast/doc.go
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Package ast implements abstruct-syntax-tree for anko.
|
||||
package ast
|
187
src/tool/run/ast/expr.go
Normal file
187
src/tool/run/ast/expr.go
Normal file
|
@ -0,0 +1,187 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Expr provides all of interfaces for expression.
|
||||
type Expr interface {
|
||||
Pos
|
||||
}
|
||||
|
||||
// ExprImpl provide commonly implementations for Expr.
|
||||
type ExprImpl struct {
|
||||
PosImpl // PosImpl provide Pos() function.
|
||||
}
|
||||
|
||||
// OpExpr provide operator expression.
|
||||
type OpExpr struct {
|
||||
ExprImpl
|
||||
Op Operator
|
||||
}
|
||||
|
||||
// LiteralExpr provide literal expression.
|
||||
type LiteralExpr struct {
|
||||
ExprImpl
|
||||
Literal reflect.Value
|
||||
}
|
||||
|
||||
// ArrayExpr provide Array expression.
|
||||
type ArrayExpr struct {
|
||||
ExprImpl
|
||||
Exprs []Expr
|
||||
TypeData *TypeStruct
|
||||
}
|
||||
|
||||
// MapExpr provide Map expression.
|
||||
type MapExpr struct {
|
||||
ExprImpl
|
||||
Keys []Expr
|
||||
Values []Expr
|
||||
TypeData *TypeStruct
|
||||
}
|
||||
|
||||
// IdentExpr provide identity expression.
|
||||
type IdentExpr struct {
|
||||
ExprImpl
|
||||
Lit string
|
||||
}
|
||||
|
||||
// UnaryExpr provide unary minus expression. ex: -1, ^1, ~1.
|
||||
type UnaryExpr struct {
|
||||
ExprImpl
|
||||
Operator string
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// AddrExpr provide referencing address expression.
|
||||
type AddrExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// DerefExpr provide dereferencing address expression.
|
||||
type DerefExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// ParenExpr provide parent block expression.
|
||||
type ParenExpr struct {
|
||||
ExprImpl
|
||||
SubExpr Expr
|
||||
}
|
||||
|
||||
// NilCoalescingOpExpr provide if invalid operator expression.
|
||||
type NilCoalescingOpExpr struct {
|
||||
ExprImpl
|
||||
LHS Expr
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// TernaryOpExpr provide ternary operator expression.
|
||||
type TernaryOpExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
LHS Expr
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// CallExpr provide calling expression.
|
||||
type CallExpr struct {
|
||||
ExprImpl
|
||||
Func reflect.Value
|
||||
Name string
|
||||
SubExprs []Expr
|
||||
VarArg bool
|
||||
Go bool
|
||||
}
|
||||
|
||||
// AnonCallExpr provide anonymous calling expression. ex: func(){}().
|
||||
type AnonCallExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
SubExprs []Expr
|
||||
VarArg bool
|
||||
Go bool
|
||||
}
|
||||
|
||||
// MemberExpr provide expression to refer member.
|
||||
type MemberExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
Name string
|
||||
}
|
||||
|
||||
// ItemExpr provide expression to refer Map/Array item.
|
||||
type ItemExpr struct {
|
||||
ExprImpl
|
||||
Item Expr
|
||||
Index Expr
|
||||
}
|
||||
|
||||
// SliceExpr provide expression to refer slice of Array.
|
||||
type SliceExpr struct {
|
||||
ExprImpl
|
||||
Item Expr
|
||||
Begin Expr
|
||||
End Expr
|
||||
Cap Expr
|
||||
}
|
||||
|
||||
// FuncExpr provide function expression.
|
||||
type FuncExpr struct {
|
||||
ExprImpl
|
||||
Name string
|
||||
Stmt Stmt
|
||||
Params []string
|
||||
VarArg bool
|
||||
}
|
||||
|
||||
// LetsExpr provide multiple expression of let.
|
||||
type LetsExpr struct {
|
||||
ExprImpl
|
||||
LHSS []Expr
|
||||
RHSS []Expr
|
||||
}
|
||||
|
||||
// ChanExpr provide chan expression.
|
||||
type ChanExpr struct {
|
||||
ExprImpl
|
||||
LHS Expr
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// ImportExpr provide expression to import packages.
|
||||
type ImportExpr struct {
|
||||
ExprImpl
|
||||
Name Expr
|
||||
}
|
||||
|
||||
// MakeExpr provide expression to make instance.
|
||||
type MakeExpr struct {
|
||||
ExprImpl
|
||||
TypeData *TypeStruct
|
||||
LenExpr Expr
|
||||
CapExpr Expr
|
||||
}
|
||||
|
||||
// MakeTypeExpr provide expression to make type.
|
||||
type MakeTypeExpr struct {
|
||||
ExprImpl
|
||||
Name string
|
||||
Type Expr
|
||||
}
|
||||
|
||||
// LenExpr provide expression to get length of array, map, etc.
|
||||
type LenExpr struct {
|
||||
ExprImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// IncludeExpr provide in expression
|
||||
type IncludeExpr struct {
|
||||
ExprImpl
|
||||
ItemExpr Expr
|
||||
ListExpr Expr
|
||||
}
|
43
src/tool/run/ast/operator.go
Normal file
43
src/tool/run/ast/operator.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package ast
|
||||
|
||||
// Operator provides interfaces for operators.
|
||||
type Operator interface {
|
||||
Pos
|
||||
}
|
||||
|
||||
// OperatorImpl provides common implementations for Operator.
|
||||
type OperatorImpl struct {
|
||||
PosImpl // PosImpl provide Pos() function.
|
||||
}
|
||||
|
||||
// BinaryOperator provides binary operation.
|
||||
type BinaryOperator struct {
|
||||
OperatorImpl
|
||||
LHS Expr
|
||||
Operator string
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// ComparisonOperator provides comparison operation.
|
||||
type ComparisonOperator struct {
|
||||
OperatorImpl
|
||||
LHS Expr
|
||||
Operator string
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// AddOperator provides add operation.
|
||||
type AddOperator struct {
|
||||
OperatorImpl
|
||||
LHS Expr
|
||||
Operator string
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// MultiplyOperator provides multiply operation.
|
||||
type MultiplyOperator struct {
|
||||
OperatorImpl
|
||||
LHS Expr
|
||||
Operator string
|
||||
RHS Expr
|
||||
}
|
28
src/tool/run/ast/pos.go
Normal file
28
src/tool/run/ast/pos.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package ast
|
||||
|
||||
// Position provides interface to store code locations.
|
||||
type Position struct {
|
||||
Line int
|
||||
Column int
|
||||
}
|
||||
|
||||
// Pos interface provides two functions to get/set the position for expression or statement.
|
||||
type Pos interface {
|
||||
Position() Position
|
||||
SetPosition(Position)
|
||||
}
|
||||
|
||||
// PosImpl provides commonly implementations for Pos.
|
||||
type PosImpl struct {
|
||||
pos Position
|
||||
}
|
||||
|
||||
// Position return the position of the expression or statement.
|
||||
func (x *PosImpl) Position() Position {
|
||||
return x.pos
|
||||
}
|
||||
|
||||
// SetPosition is a function to specify position of the expression or statement.
|
||||
func (x *PosImpl) SetPosition(pos Position) {
|
||||
x.pos = pos
|
||||
}
|
157
src/tool/run/ast/stmt.go
Normal file
157
src/tool/run/ast/stmt.go
Normal file
|
@ -0,0 +1,157 @@
|
|||
package ast
|
||||
|
||||
// Stmt provides all of interfaces for statement.
|
||||
type Stmt interface {
|
||||
Pos
|
||||
}
|
||||
|
||||
// StmtImpl provide commonly implementations for Stmt..
|
||||
type StmtImpl struct {
|
||||
PosImpl // PosImpl provide Pos() function.
|
||||
}
|
||||
|
||||
// StmtsStmt provides statements.
|
||||
type StmtsStmt struct {
|
||||
StmtImpl
|
||||
Stmts []Stmt
|
||||
}
|
||||
|
||||
// ExprStmt provide expression statement.
|
||||
type ExprStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// IfStmt provide "if/else" statement.
|
||||
type IfStmt struct {
|
||||
StmtImpl
|
||||
If Expr
|
||||
Then Stmt
|
||||
ElseIf []Stmt // This is array of IfStmt
|
||||
Else Stmt
|
||||
}
|
||||
|
||||
// TryStmt provide "try/catch/finally" statement.
|
||||
type TryStmt struct {
|
||||
StmtImpl
|
||||
Try Stmt
|
||||
Var string
|
||||
Catch Stmt
|
||||
Finally Stmt
|
||||
}
|
||||
|
||||
// ForStmt provide "for in" expression statement.
|
||||
type ForStmt struct {
|
||||
StmtImpl
|
||||
Vars []string
|
||||
Value Expr
|
||||
Stmt Stmt
|
||||
}
|
||||
|
||||
// CForStmt provide C-style "for (;;)" expression statement.
|
||||
type CForStmt struct {
|
||||
StmtImpl
|
||||
Stmt1 Stmt
|
||||
Expr2 Expr
|
||||
Expr3 Expr
|
||||
Stmt Stmt
|
||||
}
|
||||
|
||||
// LoopStmt provide "for expr" expression statement.
|
||||
type LoopStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
Stmt Stmt
|
||||
}
|
||||
|
||||
// BreakStmt provide "break" expression statement.
|
||||
type BreakStmt struct {
|
||||
StmtImpl
|
||||
}
|
||||
|
||||
// ContinueStmt provide "continue" expression statement.
|
||||
type ContinueStmt struct {
|
||||
StmtImpl
|
||||
}
|
||||
|
||||
// ReturnStmt provide "return" expression statement.
|
||||
type ReturnStmt struct {
|
||||
StmtImpl
|
||||
Exprs []Expr
|
||||
}
|
||||
|
||||
// ThrowStmt provide "throw" expression statement.
|
||||
type ThrowStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// ModuleStmt provide "module" expression statement.
|
||||
type ModuleStmt struct {
|
||||
StmtImpl
|
||||
Name string
|
||||
Stmt Stmt
|
||||
}
|
||||
|
||||
// SwitchStmt provide switch statement.
|
||||
type SwitchStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
Cases []Stmt
|
||||
Default Stmt
|
||||
}
|
||||
|
||||
// SwitchCaseStmt provide switch case statement.
|
||||
type SwitchCaseStmt struct {
|
||||
StmtImpl
|
||||
Exprs []Expr
|
||||
Stmt Stmt
|
||||
}
|
||||
|
||||
// VarStmt provide statement to let variables in current scope.
|
||||
type VarStmt struct {
|
||||
StmtImpl
|
||||
Names []string
|
||||
Exprs []Expr
|
||||
}
|
||||
|
||||
// LetsStmt provide multiple statement of let.
|
||||
type LetsStmt struct {
|
||||
StmtImpl
|
||||
LHSS []Expr
|
||||
RHSS []Expr
|
||||
}
|
||||
|
||||
// LetMapItemStmt provide statement of let for map item.
|
||||
type LetMapItemStmt struct {
|
||||
StmtImpl
|
||||
LHSS []Expr
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
// GoroutineStmt provide statement of groutine.
|
||||
type GoroutineStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// DeleteStmt provides statement of delete.
|
||||
type DeleteStmt struct {
|
||||
ExprImpl
|
||||
Item Expr
|
||||
Key Expr
|
||||
}
|
||||
|
||||
// CloseStmt provides statement of close.
|
||||
type CloseStmt struct {
|
||||
StmtImpl
|
||||
Expr Expr
|
||||
}
|
||||
|
||||
// ChanStmt provide chan lets statement.
|
||||
type ChanStmt struct {
|
||||
ExprImpl
|
||||
LHS Expr
|
||||
OkExpr Expr
|
||||
RHS Expr
|
||||
}
|
122
src/tool/run/cmd/anko-package-gen/main.go
Normal file
122
src/tool/run/cmd/anko-package-gen/main.go
Normal file
|
@ -0,0 +1,122 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func pkgName(f string) string {
|
||||
file, err := parser.ParseFile(token.NewFileSet(), f, nil, parser.PackageClauseOnly)
|
||||
if err != nil || file == nil {
|
||||
return ""
|
||||
}
|
||||
return file.Name.Name
|
||||
}
|
||||
|
||||
func isGoFile(dir os.FileInfo) bool {
|
||||
return !dir.IsDir() &&
|
||||
!strings.HasPrefix(dir.Name(), ".") && // ignore .files
|
||||
filepath.Ext(dir.Name()) == ".go"
|
||||
}
|
||||
|
||||
func isPkgFile(dir os.FileInfo) bool {
|
||||
return isGoFile(dir) && !strings.HasSuffix(dir.Name(), "_test.go") // ignore test files
|
||||
}
|
||||
|
||||
func parseDir(p string) (map[string]*ast.Package, error) {
|
||||
isGoFile := func(d os.FileInfo) bool {
|
||||
return !d.IsDir() && !strings.HasSuffix(d.Name(), "_test.go") && !strings.HasPrefix(d.Name(), "example_")
|
||||
}
|
||||
|
||||
pkgs, err := parser.ParseDir(token.NewFileSet(), p, isGoFile, parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pkg := "flag"
|
||||
if len(os.Args) == 2 {
|
||||
pkg = os.Args[1]
|
||||
}
|
||||
b, err := exec.Command("go", "env", "GOROOT").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
paths := []string{filepath.Join(strings.TrimSpace(string(b)), "src")}
|
||||
b, err = exec.Command("go", "env", "GOPATH").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, p := range strings.Split(strings.TrimSpace(string(b)), string(filepath.ListSeparator)) {
|
||||
paths = append(paths, filepath.Join(p, "src"))
|
||||
}
|
||||
for _, p := range paths {
|
||||
pp := filepath.Join(p, pkg)
|
||||
pkgs, err := parseDir(pp)
|
||||
if err != nil || len(pkgs) == 0 {
|
||||
continue
|
||||
}
|
||||
names := map[string]bool{}
|
||||
pn := pkg
|
||||
for _, pp := range pkgs {
|
||||
pn = pp.Name
|
||||
for _, f := range pp.Files {
|
||||
for _, d := range f.Decls {
|
||||
switch decl := d.(type) {
|
||||
case *ast.GenDecl:
|
||||
for _, spec := range decl.Specs {
|
||||
if vspec, ok := spec.(*ast.ValueSpec); ok {
|
||||
for _, n := range vspec.Names {
|
||||
c := n.Name[0]
|
||||
if c < 'A' || c > 'Z' {
|
||||
continue
|
||||
}
|
||||
names[n.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
if decl.Recv != nil {
|
||||
continue
|
||||
}
|
||||
c := decl.Name.Name[0]
|
||||
if c < 'A' || c > 'Z' {
|
||||
continue
|
||||
}
|
||||
names[decl.Name.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
keys := []string{}
|
||||
for k := range names {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
fmt.Printf(`// Package %s implements %s interface for anko script.
|
||||
package %s
|
||||
|
||||
import (
|
||||
"%s"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Packages["%s"] = map[string]interface{}{
|
||||
`, pn, pkg, pn, pkg, pn)
|
||||
for _, k := range keys {
|
||||
fmt.Printf(` "%s": %s.%s,`+"\n", k, pn, k)
|
||||
}
|
||||
fmt.Println(` }
|
||||
}`)
|
||||
}
|
||||
}
|
105
src/tool/run/core/core.go
Normal file
105
src/tool/run/core/core.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Package core implements core interface for anko script.
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
"github.com/surdeus/goblin/src/tool/run/parser"
|
||||
"github.com/surdeus/goblin/src/tool/run/vm"
|
||||
)
|
||||
|
||||
// Import defines core language builtins - keys, range, println, etc.
|
||||
func Import(e *env.Env) *env.Env {
|
||||
e.Define("keys", func(v interface{}) []interface{} {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() == reflect.Interface {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
mapKeysValue := rv.MapKeys()
|
||||
mapKeys := make([]interface{}, len(mapKeysValue))
|
||||
for i := 0; i < len(mapKeysValue); i++ {
|
||||
mapKeys[i] = mapKeysValue[i].Interface()
|
||||
}
|
||||
return mapKeys
|
||||
})
|
||||
|
||||
e.Define("range", func(args ...int64) []int64 {
|
||||
var start, stop int64
|
||||
var step int64 = 1
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
panic("range expected at least 1 argument, got 0")
|
||||
case 1:
|
||||
stop = args[0]
|
||||
case 2:
|
||||
start = args[0]
|
||||
stop = args[1]
|
||||
case 3:
|
||||
start = args[0]
|
||||
stop = args[1]
|
||||
step = args[2]
|
||||
if step == 0 {
|
||||
panic("range argument 3 must not be zero")
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("range expected at most 3 arguments, got %d", len(args)))
|
||||
}
|
||||
|
||||
arr := []int64{}
|
||||
for i := start; (step > 0 && i < stop) || (step < 0 && i > stop); i += step {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
return arr
|
||||
})
|
||||
|
||||
e.Define("typeOf", func(v interface{}) string {
|
||||
return reflect.TypeOf(v).String()
|
||||
})
|
||||
|
||||
e.Define("kindOf", func(v interface{}) string {
|
||||
typeOf := reflect.TypeOf(v)
|
||||
if typeOf == nil {
|
||||
return "nil"
|
||||
}
|
||||
return typeOf.Kind().String()
|
||||
})
|
||||
|
||||
e.Define("defined", func(s string) bool {
|
||||
_, err := e.Get(s)
|
||||
return err == nil
|
||||
})
|
||||
|
||||
e.Define("load", func(s string) interface{} {
|
||||
body, err := ioutil.ReadFile(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
scanner := new(parser.Scanner)
|
||||
scanner.Init(string(body))
|
||||
stmts, err := parser.Parse(scanner)
|
||||
if err != nil {
|
||||
if pe, ok := err.(*parser.Error); ok {
|
||||
pe.Filename = s
|
||||
panic(pe)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
rv, err := vm.Run(e, nil, stmts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return rv
|
||||
})
|
||||
|
||||
e.Define("print", fmt.Print)
|
||||
e.Define("println", fmt.Println)
|
||||
e.Define("printf", fmt.Printf)
|
||||
|
||||
ImportToX(e)
|
||||
|
||||
return e
|
||||
}
|
6
src/tool/run/core/testdata/broken.ank
vendored
Normal file
6
src/tool/run/core/testdata/broken.ank
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
die "Hey! I'm anko";
|
17
src/tool/run/core/testdata/chan.ank
vendored
Normal file
17
src/tool/run/core/testdata/chan.ank
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
c = make(chan int64)
|
||||
r = []
|
||||
|
||||
go func() {
|
||||
c <- 1
|
||||
c <- 2
|
||||
c <- 3
|
||||
close(c)
|
||||
}()
|
||||
|
||||
for a in c {
|
||||
r += a
|
||||
}
|
||||
is([1,2,3], r, "chan")
|
||||
|
||||
nil
|
149
src/tool/run/core/testdata/core_test.go
vendored
Normal file
149
src/tool/run/core/testdata/core_test.go
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/packages"
|
||||
"github.com/surdeus/goblin/src/tool/run/vm"
|
||||
)
|
||||
|
||||
var testCoreEnvSetupFunc = func(t *testing.T, env corelib.Env) { Import(env.(*vm.Env)) }
|
||||
|
||||
func init() {
|
||||
corelib.NewEnv = func() corelib.Env {
|
||||
return vm.NewEnv()
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "1")
|
||||
tests := []testlib.Test{
|
||||
{Script: `a = {}; b = keys(a)`, RunOutput: []interface{}{}, Output: map[string]interface{}{"a": map[interface{}]interface{}{}}},
|
||||
{Script: `a = {"a": nil}; b = keys(a)`, RunOutput: []interface{}{"a"}, Output: map[string]interface{}{"a": map[interface{}]interface{}{"a": nil}}},
|
||||
{Script: `a = {"a": 1}; b = keys(a)`, RunOutput: []interface{}{"a"}, Output: map[string]interface{}{"a": map[interface{}]interface{}{"a": int64(1)}}},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
||||
|
||||
func TestKindOf(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "1")
|
||||
tests := []testlib.Test{
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": reflect.Value{}}, RunOutput: "struct", Output: map[string]interface{}{"a": reflect.Value{}}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": nil}, RunOutput: "nil", Output: map[string]interface{}{"a": nil}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": true}, RunOutput: "bool", Output: map[string]interface{}{"a": true}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: "int32", Output: map[string]interface{}{"a": int32(1)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: "int64", Output: map[string]interface{}{"a": int64(1)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": float32(1.1)}, RunOutput: "float32", Output: map[string]interface{}{"a": float32(1.1)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: "float64", Output: map[string]interface{}{"a": float64(1.1)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": "a"}, RunOutput: "string", Output: map[string]interface{}{"a": "a"}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": 'a'}, RunOutput: "int32", Output: map[string]interface{}{"a": 'a'}},
|
||||
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(nil)}, RunOutput: "nil", Output: map[string]interface{}{"a": interface{}(nil)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(true)}, RunOutput: "bool", Output: map[string]interface{}{"a": interface{}(true)}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(int32(1))}, RunOutput: "int32", Output: map[string]interface{}{"a": interface{}(int32(1))}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(int64(1))}, RunOutput: "int64", Output: map[string]interface{}{"a": interface{}(int64(1))}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(float32(1))}, RunOutput: "float32", Output: map[string]interface{}{"a": interface{}(float32(1))}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}(float64(1))}, RunOutput: "float64", Output: map[string]interface{}{"a": interface{}(float64(1))}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": interface{}("a")}, RunOutput: "string", Output: map[string]interface{}{"a": interface{}("a")}},
|
||||
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": []interface{}{}}, RunOutput: "slice", Output: map[string]interface{}{"a": []interface{}{}}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": []interface{}{nil}}, RunOutput: "slice", Output: map[string]interface{}{"a": []interface{}{nil}}},
|
||||
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": map[string]interface{}{}}, RunOutput: "map", Output: map[string]interface{}{"a": map[string]interface{}{}}},
|
||||
{Script: `kindOf(a)`, Input: map[string]interface{}{"a": map[string]interface{}{"b": "b"}}, RunOutput: "map", Output: map[string]interface{}{"a": map[string]interface{}{"b": "b"}}},
|
||||
|
||||
{Script: `a = make(interface); kindOf(a)`, RunOutput: "nil", Output: map[string]interface{}{"a": interface{}(nil)}},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "")
|
||||
tests := []testlib.Test{
|
||||
// 0 arguments
|
||||
{Script: `range()`, RunError: fmt.Errorf("range expected at least 1 argument, got 0")},
|
||||
// 1 arguments(step == 1, start == 0)
|
||||
{Script: `range(-1)`, RunOutput: []int64{}},
|
||||
{Script: `range(0)`, RunOutput: []int64{}},
|
||||
{Script: `range(1)`, RunOutput: []int64{0}},
|
||||
{Script: `range(2)`, RunOutput: []int64{0, 1}},
|
||||
{Script: `range(10)`, RunOutput: []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}},
|
||||
// 2 arguments(step == 1)
|
||||
{Script: `range(-5,-1)`, RunOutput: []int64{-5, -4, -3, -2}},
|
||||
{Script: `range(-1,1)`, RunOutput: []int64{-1, 0}},
|
||||
{Script: `range(1,5)`, RunOutput: []int64{1, 2, 3, 4}},
|
||||
// 3 arguments
|
||||
// step == 2
|
||||
{Script: `range(-5,-1,2)`, RunOutput: []int64{-5, -3}},
|
||||
{Script: `range(1,5,2)`, RunOutput: []int64{1, 3}},
|
||||
{Script: `range(-1,5,2)`, RunOutput: []int64{-1, 1, 3}},
|
||||
// step < 0 and from small to large
|
||||
{Script: `range(-5,-1,-1)`, RunOutput: []int64{}},
|
||||
{Script: `range(1,5,-1)`, RunOutput: []int64{}},
|
||||
{Script: `range(-1,5,-1)`, RunOutput: []int64{}},
|
||||
// step < 0 and from large to small
|
||||
{Script: `range(-1,-5,-1)`, RunOutput: []int64{-1, -2, -3, -4}},
|
||||
{Script: `range(5,1,-1)`, RunOutput: []int64{5, 4, 3, 2}},
|
||||
{Script: `range(5,-1,-1)`, RunOutput: []int64{5, 4, 3, 2, 1, 0}},
|
||||
// 4,5 arguments
|
||||
{Script: `range(1,5,1,1)`, RunError: fmt.Errorf("range expected at most 3 arguments, got 4")},
|
||||
{Script: `range(1,5,1,1,1)`, RunError: fmt.Errorf("range expected at most 3 arguments, got 5")},
|
||||
// more 0 test
|
||||
{Script: `range(0,1,2)`, RunOutput: []int64{0}},
|
||||
{Script: `range(1,0,2)`, RunOutput: []int64{}},
|
||||
{Script: `range(1,2,0)`, RunError: fmt.Errorf("range argument 3 must not be zero")},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "")
|
||||
notFoundRunErrorFunc := func(t *testing.T, err error) {
|
||||
if err == nil || !strings.HasPrefix(err.Error(), "open testdata/not-found.ank:") {
|
||||
t.Errorf("load not-found.ank failed - received: %v", err)
|
||||
}
|
||||
}
|
||||
tests := []testlib.Test{
|
||||
{Script: `load('testdata/test.ank'); X(1)`, RunOutput: int64(2)},
|
||||
{Script: `load('testdata/not-found.ank'); X(1)`, RunErrorFunc: ¬FoundRunErrorFunc},
|
||||
{Script: `load('testdata/broken.ank'); X(1)`, RunError: fmt.Errorf("syntax error")},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
||||
|
||||
func TestAnk(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "")
|
||||
var testEnvSetupFunc = func(t *testing.T, env corelib.Env) {
|
||||
e := env.(*vm.Env)
|
||||
Import(e)
|
||||
packages.DefineImport(e)
|
||||
}
|
||||
tests := []testlib.Test{
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/let.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/toString.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/op.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/func.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/len.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/for.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/switch.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/if.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/toBytes.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/toRunes.ank')`},
|
||||
{Script: `load('testdata/testing.ank'); load('testdata/chan.ank')`},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testEnvSetupFunc})
|
||||
}
|
||||
|
||||
func TestDefined(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "")
|
||||
tests := []testlib.Test{
|
||||
{Script: `var a = 1; defined("a")`, RunOutput: true},
|
||||
{Script: `defined("a")`, RunOutput: false},
|
||||
{Script: `func(){ var a = 1 }(); defined("a")`, RunOutput: false},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
3
src/tool/run/core/testdata/error.ank
vendored
Normal file
3
src/tool/run/core/testdata/error.ank
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
func X(a) {
|
||||
a.notfound = 1
|
||||
}
|
75
src/tool/run/core/testdata/for.ank
vendored
Normal file
75
src/tool/run/core/testdata/for.ank
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
|
||||
x = 0
|
||||
for a in [1,2,3] {
|
||||
x += 1
|
||||
}
|
||||
is(3, x, "for a in range [1,2,3]")
|
||||
|
||||
x = 0
|
||||
|
||||
for {
|
||||
x += 1
|
||||
if (x > 3) {
|
||||
break
|
||||
}
|
||||
}
|
||||
is(4, x, "for loop")
|
||||
|
||||
func loop_with_return_stmt() {
|
||||
y = 0
|
||||
for {
|
||||
if y == 5 {
|
||||
return y
|
||||
}
|
||||
y++
|
||||
}
|
||||
return 1
|
||||
}
|
||||
is(5, loop_with_return_stmt(), "loop with return stmt")
|
||||
|
||||
func for_with_return_stmt() {
|
||||
y = 0
|
||||
for k in range(0, 10) {
|
||||
if k == 5 {
|
||||
return y
|
||||
}
|
||||
y++
|
||||
}
|
||||
return 1
|
||||
}
|
||||
is(5, for_with_return_stmt(), "for loop with return stmt")
|
||||
|
||||
x = 0
|
||||
for a = 0; a < 10; a++ {
|
||||
x++
|
||||
}
|
||||
is(10, x, "C-style for loop")
|
||||
|
||||
func cstylefor_with_return_stmt() {
|
||||
y = 0
|
||||
for i = 0; i < 10; i++ {
|
||||
if i == 5 {
|
||||
return y
|
||||
}
|
||||
y++
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
is(5, cstylefor_with_return_stmt(), "C-style for loop with return statement")
|
||||
|
||||
resp = {
|
||||
"items": [{
|
||||
"someData": 2,
|
||||
}]
|
||||
}
|
||||
|
||||
x = 0
|
||||
for item in resp.items {
|
||||
x += item.someData
|
||||
}
|
||||
|
||||
is(2, x, "dereference slice element")
|
||||
|
||||
nil
|
24
src/tool/run/core/testdata/func.ank
vendored
Normal file
24
src/tool/run/core/testdata/func.ank
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
func a() { return 2 }
|
||||
is(2, a(), "func a() { return 2 }")
|
||||
|
||||
func b(x) { return x + 1 }
|
||||
is(3, b(2), "func b(x) { return x + 1 }")
|
||||
|
||||
func c(x) { return x, x + 1 }
|
||||
is([2,3], c(2), "func c(x) { return x, x + 1 }")
|
||||
|
||||
func d(x) { return func() { return x + 1 } }
|
||||
is(3, d(2)(), "func d(x) { return func() { return x + 1 } }")
|
||||
|
||||
var x = func(x) {
|
||||
return func(y) {
|
||||
x(y)
|
||||
}
|
||||
}(func(z) {
|
||||
return "Yay! " + z
|
||||
})("hello world")
|
||||
|
||||
is("Yay! hello world", x, "...")
|
||||
|
||||
nil
|
14
src/tool/run/core/testdata/if.ank
vendored
Normal file
14
src/tool/run/core/testdata/if.ank
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
r = -1
|
||||
if (false) {
|
||||
r = 1
|
||||
} else if (false) {
|
||||
r = 2
|
||||
} else if (false) {
|
||||
r = 3
|
||||
} else {
|
||||
r = 4
|
||||
}
|
||||
is(4, r, "if")
|
||||
|
||||
nil
|
6
src/tool/run/core/testdata/len.ank
vendored
Normal file
6
src/tool/run/core/testdata/len.ank
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
is(3, len("foo"), "len(\"foo\")")
|
||||
is(0, len(""), "len(\"\")")
|
||||
is(4, len([1,2,true,["foo"]]), "len([1,2,true,[\"foo\"]])")
|
||||
|
||||
nil
|
32
src/tool/run/core/testdata/let.ank
vendored
Normal file
32
src/tool/run/core/testdata/let.ank
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
a = nil
|
||||
is(nil, a, "let nil")
|
||||
|
||||
a = 1
|
||||
is(1, a, "let int")
|
||||
|
||||
a = 1.2
|
||||
is(1.2, a, "let float")
|
||||
|
||||
a = "foo"
|
||||
is("foo", a, "let string")
|
||||
|
||||
a = nil
|
||||
is(nil, a, "let nil")
|
||||
|
||||
a = true
|
||||
is(true, a, "let true")
|
||||
|
||||
a = false
|
||||
is(false, a, "let false")
|
||||
|
||||
a = [1,2,3]
|
||||
is([1,2,3], a, "let array")
|
||||
|
||||
a = {"foo": "bar", "bar": "baz"}
|
||||
is({"bar": "baz", "foo": "bar"}, a, "let map")
|
||||
|
||||
a = {"foo": "bar", "bar": {"blah": true, "blah!": [1.3e3, true]}}
|
||||
is({"foo": "bar", "bar": {"blah": true, "blah!": [1.3e3, true]}}, a, "let map deep")
|
||||
|
||||
nil
|
63
src/tool/run/core/testdata/op.ank
vendored
Normal file
63
src/tool/run/core/testdata/op.ank
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
ok(1 > 0, "1 > 0")
|
||||
ok(1 == 1.0, "1 == 1.0")
|
||||
is(1 != "1", false, "1 != \"1\"")
|
||||
ok(1 == 1, "1 == 1")
|
||||
ok(1.1 == 1.1, "1.1 == 1.1")
|
||||
ok("1" == "1", "\"1\" == \"1\"")
|
||||
|
||||
ok(false != "1", "false != \"1\"")
|
||||
ok(false != true, "false != true")
|
||||
ok(false == false, "false == false")
|
||||
ok(true == true, "true == true")
|
||||
ok(false == false, "false == false")
|
||||
ok(nil == nil, "nil == nil")
|
||||
|
||||
ok(1 <= 1, "1 <= 1")
|
||||
ok(1.0 <= 1.0, "1.0 <= 1.0")
|
||||
|
||||
is(true, 1 <= 2 ? true : false, "1 == 1 ? true : false")
|
||||
|
||||
a = 1; a += 1
|
||||
is(2, a, "+=")
|
||||
|
||||
a = 2; a -= 1
|
||||
is(1, a, "-=")
|
||||
|
||||
a = 2; a *= 2
|
||||
is(4, a, "*=")
|
||||
|
||||
a = 3; a /= 2
|
||||
is(1.5, a, "/=")
|
||||
|
||||
a = 2; a++
|
||||
is(3, a, "++")
|
||||
|
||||
a = 2; a--
|
||||
is(1, a, "--")
|
||||
|
||||
a = 1; a &= 2
|
||||
is(0, a, "&=")
|
||||
|
||||
a = 1; a |= 2
|
||||
is(3, a, "|=")
|
||||
|
||||
a = !3
|
||||
is(false, a, "!3")
|
||||
|
||||
a = !true
|
||||
is(false, a, "!true")
|
||||
|
||||
a = !false
|
||||
is(true, a, "!false")
|
||||
|
||||
a = ^3
|
||||
is(-4, a, "^3")
|
||||
|
||||
a = 3 << 2
|
||||
is(12, a, "3 << 2")
|
||||
|
||||
a = 11 >> 2
|
||||
is(2, a, "11 >> 2")
|
||||
|
||||
nil
|
32
src/tool/run/core/testdata/sort.ank
vendored
Normal file
32
src/tool/run/core/testdata/sort.ank
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
sort = import("sort")
|
||||
|
||||
a = make([]int)
|
||||
b = make([]int)
|
||||
a += [1, 2, 3]
|
||||
b += [3, 1, 2]
|
||||
sort.Ints(b)
|
||||
is(a, b, "sort.Ints")
|
||||
|
||||
a = make([]float64)
|
||||
b = make([]float64)
|
||||
a += [1.1, 2.2, 3.3]
|
||||
b += [3.3, 1.1, 2.2]
|
||||
sort.Float64s(b)
|
||||
is(a, b, "sort.Float64s")
|
||||
|
||||
a = make([]string)
|
||||
b = make([]string)
|
||||
a += ["a", "b", "c", "d"]
|
||||
b += ["b", "d", "a", "c"]
|
||||
sort.Strings(b)
|
||||
is(a, b, "sort.Strings")
|
||||
|
||||
if go18later() {
|
||||
a = [1, 3, 2]
|
||||
sort.Slice(a, func(i, j) {
|
||||
return a[i] < a[j]
|
||||
})
|
||||
is([1,2,3], a, "sort.Slice")
|
||||
}
|
||||
|
||||
nil
|
40
src/tool/run/core/testdata/switch.ank
vendored
Normal file
40
src/tool/run/core/testdata/switch.ank
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
x = 0
|
||||
r = -1
|
||||
switch x {
|
||||
case 0:
|
||||
r = 0
|
||||
case 1:
|
||||
r = 1
|
||||
case 2:
|
||||
r = 2
|
||||
}
|
||||
is(0, r, "switch/case")
|
||||
|
||||
x = 3
|
||||
r = -1
|
||||
switch x {
|
||||
case 0:
|
||||
r = 0
|
||||
case 1:
|
||||
r = 1
|
||||
case 2:
|
||||
r = 2
|
||||
}
|
||||
is(-1, r, "switch/case")
|
||||
|
||||
x = 3
|
||||
r = -1
|
||||
switch x {
|
||||
case 0:
|
||||
r = 0
|
||||
case 1:
|
||||
r = 1
|
||||
case 2:
|
||||
r = 2
|
||||
default:
|
||||
r = 3
|
||||
}
|
||||
is(3, r, "switch/default")
|
||||
|
||||
nil
|
3
src/tool/run/core/testdata/test.ank
vendored
Normal file
3
src/tool/run/core/testdata/test.ank
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
func X(a) {
|
||||
return a + 1
|
||||
}
|
19
src/tool/run/core/testdata/testing.ank
vendored
Normal file
19
src/tool/run/core/testdata/testing.ank
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
var runtime = import("runtime")
|
||||
var regexp = import("regexp")
|
||||
|
||||
func is(expect, got, name) {
|
||||
if expect != got {
|
||||
panic("is - received: " + toString(got) + " - expected: " + toString(expect) + " - for: " + toString(name))
|
||||
}
|
||||
}
|
||||
|
||||
func ok(expect, name) {
|
||||
if !expect {
|
||||
panic("ok - received: " + toString(expect) + " - for: " + toString(name))
|
||||
}
|
||||
}
|
||||
|
||||
func go18later() {
|
||||
return regexp.MustCompile("^go1\\.(1[0-9]|[8-9])\\.[0-9]$").MatchString(runtime.Version())
|
||||
}
|
12
src/tool/run/core/testdata/toBytes.ank
vendored
Normal file
12
src/tool/run/core/testdata/toBytes.ank
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
a = toByteSlice("あいうえお")
|
||||
b = [227, 129, 130, 227, 129, 132, 227, 129, 134, 227, 129, 136, 227, 129, 138]
|
||||
x = 0
|
||||
for i = 0; i < len(a); i++ {
|
||||
if (a[i] == b[i]) {
|
||||
x++
|
||||
}
|
||||
}
|
||||
is(x, len(a), "toByteSlice(str)")
|
||||
|
||||
nil
|
12
src/tool/run/core/testdata/toRunes.ank
vendored
Normal file
12
src/tool/run/core/testdata/toRunes.ank
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
a = toRuneSlice("あいうえお")
|
||||
b = [12354, 12356, 12358, 12360, 12362]
|
||||
x = 0
|
||||
for i = 0; i < len(a); i++ {
|
||||
if (a[i] == b[i]) {
|
||||
x++
|
||||
}
|
||||
}
|
||||
is(x, len(a), "toRuneSlice(str)")
|
||||
|
||||
nil
|
8
src/tool/run/core/testdata/toString.ank
vendored
Normal file
8
src/tool/run/core/testdata/toString.ank
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
is("1", toString(1), "toString(int)")
|
||||
is("1.2", toString(1.2), "toString(float)")
|
||||
is("true", toString(true), "toString(true)")
|
||||
is("false", toString(false), "toString(false)")
|
||||
is("foo", toString("foo"), "toString(\"foo\")")
|
||||
|
||||
nil
|
151
src/tool/run/core/testdata/toX_test.go
vendored
Normal file
151
src/tool/run/core/testdata/toX_test.go
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/internal/testlib"
|
||||
)
|
||||
|
||||
func TestToX(t *testing.T) {
|
||||
os.Setenv("ANKO_DEBUG", "1")
|
||||
tests := []testlib.Test{
|
||||
{Script: `toBool(-2)`, RunOutput: false},
|
||||
{Script: `toBool(-1.5)`, RunOutput: false},
|
||||
{Script: `toBool(-1)`, RunOutput: false},
|
||||
{Script: `toBool(-0.4)`, RunOutput: false},
|
||||
{Script: `toBool(0)`, RunOutput: false},
|
||||
{Script: `toBool(0.4)`, RunOutput: true},
|
||||
{Script: `toBool(1)`, RunOutput: true},
|
||||
{Script: `toBool(1.5)`, RunOutput: true},
|
||||
{Script: `toBool(2)`, RunOutput: true},
|
||||
{Script: `toBool(true)`, RunOutput: true},
|
||||
{Script: `toBool(false)`, RunOutput: false},
|
||||
{Script: `toBool("true")`, RunOutput: true},
|
||||
{Script: `toBool("false")`, RunOutput: false},
|
||||
{Script: `toBool("yes")`, RunOutput: true},
|
||||
{Script: `toBool("ye")`, RunOutput: false},
|
||||
{Script: `toBool("y")`, RunOutput: true},
|
||||
{Script: `toBool("false")`, RunOutput: false},
|
||||
{Script: `toBool("f")`, RunOutput: false},
|
||||
{Script: `toBool("")`, RunOutput: false},
|
||||
{Script: `toBool(nil)`, RunOutput: false},
|
||||
{Script: `toBool({})`, RunOutput: false},
|
||||
{Script: `toBool([])`, RunOutput: false},
|
||||
{Script: `toBool([true])`, RunOutput: false},
|
||||
{Script: `toBool({"true": "true"})`, RunOutput: false},
|
||||
{Script: `toString(nil)`, RunOutput: "<nil>"},
|
||||
{Script: `toString("")`, RunOutput: ""},
|
||||
{Script: `toString(1)`, RunOutput: "1"},
|
||||
{Script: `toString(1.2)`, RunOutput: "1.2"},
|
||||
{Script: `toString(1/3)`, RunOutput: "0.3333333333333333"},
|
||||
{Script: `toString(false)`, RunOutput: "false"},
|
||||
{Script: `toString(true)`, RunOutput: "true"},
|
||||
{Script: `toString({})`, RunOutput: "map[]"},
|
||||
{Script: `toString({"foo": "bar"})`, RunOutput: "map[foo:bar]"},
|
||||
{Script: `toString([true,nil])`, RunOutput: "[true <nil>]"},
|
||||
{Script: `toString(toByteSlice("foo"))`, RunOutput: "foo"},
|
||||
{Script: `toInt(nil)`, RunOutput: int64(0)},
|
||||
{Script: `toInt(-2)`, RunOutput: int64(-2)},
|
||||
{Script: `toInt(-1.4)`, RunOutput: int64(-1)},
|
||||
{Script: `toInt(-1)`, RunOutput: int64(-1)},
|
||||
{Script: `toInt(0)`, RunOutput: int64(0)},
|
||||
{Script: `toInt(1)`, RunOutput: int64(1)},
|
||||
{Script: `toInt(1.4)`, RunOutput: int64(1)},
|
||||
{Script: `toInt(1.5)`, RunOutput: int64(1)},
|
||||
{Script: `toInt(1.9)`, RunOutput: int64(1)},
|
||||
{Script: `toInt(2)`, RunOutput: int64(2)},
|
||||
{Script: `toInt(2.1)`, RunOutput: int64(2)},
|
||||
{Script: `toInt("2")`, RunOutput: int64(2)},
|
||||
{Script: `toInt("2.1")`, RunOutput: int64(2)},
|
||||
{Script: `toInt(true)`, RunOutput: int64(1)},
|
||||
{Script: `toInt(false)`, RunOutput: int64(0)},
|
||||
{Script: `toInt({})`, RunOutput: int64(0)},
|
||||
{Script: `toInt([])`, RunOutput: int64(0)},
|
||||
{Script: `toFloat(nil)`, RunOutput: float64(0.0)},
|
||||
{Script: `toFloat(-2)`, RunOutput: float64(-2.0)},
|
||||
{Script: `toFloat(-1.4)`, RunOutput: float64(-1.4)},
|
||||
{Script: `toFloat(-1)`, RunOutput: float64(-1.0)},
|
||||
{Script: `toFloat(0)`, RunOutput: float64(0.0)},
|
||||
{Script: `toFloat(1)`, RunOutput: float64(1.0)},
|
||||
{Script: `toFloat(1.4)`, RunOutput: float64(1.4)},
|
||||
{Script: `toFloat(1.5)`, RunOutput: float64(1.5)},
|
||||
{Script: `toFloat(1.9)`, RunOutput: float64(1.9)},
|
||||
{Script: `toFloat(2)`, RunOutput: float64(2.0)},
|
||||
{Script: `toFloat(2.1)`, RunOutput: float64(2.1)},
|
||||
{Script: `toFloat("2")`, RunOutput: float64(2.0)},
|
||||
{Script: `toFloat("2.1")`, RunOutput: float64(2.1)},
|
||||
{Script: `toFloat(true)`, RunOutput: float64(1.0)},
|
||||
{Script: `toFloat(false)`, RunOutput: float64(0.0)},
|
||||
{Script: `toFloat({})`, RunOutput: float64(0.0)},
|
||||
{Script: `toFloat([])`, RunOutput: float64(0.0)},
|
||||
{Script: `toChar(0x1F431)`, RunOutput: "🐱"},
|
||||
{Script: `toChar(0)`, RunOutput: "\x00"},
|
||||
{Script: `toRune("")`, RunOutput: rune(0)},
|
||||
{Script: `toRune("🐱")`, RunOutput: rune(0x1F431)},
|
||||
{Script: `toBoolSlice(nil)`, RunOutput: []bool{}},
|
||||
{Script: `toBoolSlice(1)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type int64")},
|
||||
{Script: `toBoolSlice(1.2)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type float64")},
|
||||
{Script: `toBoolSlice(false)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type bool")},
|
||||
{Script: `toBoolSlice({})`, RunError: fmt.Errorf("function wants argument type []interface {} but received type map[interface {}]interface {}")},
|
||||
{Script: `toBoolSlice([])`, RunOutput: []bool{}},
|
||||
{Script: `toBoolSlice([nil])`, RunOutput: []bool{false}},
|
||||
{Script: `toBoolSlice([1])`, RunOutput: []bool{false}},
|
||||
{Script: `toBoolSlice([1.1])`, RunOutput: []bool{false}},
|
||||
{Script: `toBoolSlice([true])`, RunOutput: []bool{true}},
|
||||
{Script: `toBoolSlice([[]])`, RunOutput: []bool{false}},
|
||||
{Script: `toBoolSlice([{}])`, RunOutput: []bool{false}},
|
||||
{Script: `toIntSlice(nil)`, RunOutput: []int64{}},
|
||||
{Script: `toIntSlice(1)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type int64")},
|
||||
{Script: `toIntSlice(1.2)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type float64")},
|
||||
{Script: `toIntSlice(false)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type bool")},
|
||||
{Script: `toIntSlice({})`, RunError: fmt.Errorf("function wants argument type []interface {} but received type map[interface {}]interface {}")},
|
||||
{Script: `toIntSlice([])`, RunOutput: []int64{}},
|
||||
{Script: `toIntSlice([nil])`, RunOutput: []int64{0}},
|
||||
{Script: `toIntSlice([1])`, RunOutput: []int64{1}},
|
||||
{Script: `toIntSlice([1.1])`, RunOutput: []int64{1}},
|
||||
{Script: `toIntSlice([true])`, RunOutput: []int64{0}},
|
||||
{Script: `toIntSlice([[]])`, RunOutput: []int64{0}},
|
||||
{Script: `toIntSlice([{}])`, RunOutput: []int64{0}},
|
||||
{Script: `toFloatSlice(nil)`, RunOutput: []float64{}},
|
||||
{Script: `toFloatSlice(1)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type int64")},
|
||||
{Script: `toFloatSlice(1.2)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type float64")},
|
||||
{Script: `toFloatSlice(false)`, RunError: fmt.Errorf("function wants argument type []interface {} but received type bool")},
|
||||
{Script: `toFloatSlice({})`, RunError: fmt.Errorf("function wants argument type []interface {} but received type map[interface {}]interface {}")},
|
||||
{Script: `toFloatSlice([])`, RunOutput: []float64{}},
|
||||
{Script: `toFloatSlice([nil])`, RunOutput: []float64{0.0}},
|
||||
{Script: `toFloatSlice([1])`, RunOutput: []float64{1.0}},
|
||||
{Script: `toFloatSlice([1.1])`, RunOutput: []float64{1.1}},
|
||||
{Script: `toFloatSlice([true])`, RunOutput: []float64{0.0}},
|
||||
{Script: `toFloatSlice([[]])`, RunOutput: []float64{0.0}},
|
||||
{Script: `toFloatSlice([{}])`, RunOutput: []float64{0.0}},
|
||||
{Script: `toByteSlice(nil)`, RunOutput: []byte{}},
|
||||
{Script: `toByteSlice([])`, RunError: fmt.Errorf("function wants argument type string but received type []interface {}")},
|
||||
{Script: `toByteSlice(1)`, RunOutput: []byte{0x01}}, // FIXME?
|
||||
{Script: `toByteSlice(1.1)`, RunError: fmt.Errorf("function wants argument type string but received type float64")},
|
||||
{Script: `toByteSlice(true)`, RunError: fmt.Errorf("function wants argument type string but received type bool")},
|
||||
{Script: `toByteSlice("foo")`, RunOutput: []byte{'f', 'o', 'o'}},
|
||||
{Script: `toByteSlice("世界")`, RunOutput: []byte{0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c}},
|
||||
{Script: `toRuneSlice(nil)`, RunOutput: []rune{}},
|
||||
{Script: `toRuneSlice([])`, RunError: fmt.Errorf("function wants argument type string but received type []interface {}")},
|
||||
{Script: `toRuneSlice(1)`, RunOutput: []rune{0x01}}, // FIXME?
|
||||
{Script: `toRuneSlice(1.1)`, RunError: fmt.Errorf("function wants argument type string but received type float64")},
|
||||
{Script: `toRuneSlice(true)`, RunError: fmt.Errorf("function wants argument type string but received type bool")},
|
||||
{Script: `toRuneSlice("foo")`, RunOutput: []rune{'f', 'o', 'o'}},
|
||||
{Script: `toRuneSlice("世界")`, RunOutput: []rune{'世', '界'}},
|
||||
{Script: `toStringSlice([true,false,1])`, RunOutput: []string{"", "", "\x01"}}, // FIXME?
|
||||
{Script: `toDuration(nil)`, RunOutput: time.Duration(0)},
|
||||
{Script: `toDuration(0)`, RunOutput: time.Duration(0)},
|
||||
{Script: `toDuration(true)`, RunError: fmt.Errorf("function wants argument type int64 but received type bool")},
|
||||
{Script: `toDuration([])`, RunError: fmt.Errorf("function wants argument type int64 but received type []interface {}")},
|
||||
{Script: `toDuration({})`, RunError: fmt.Errorf("function wants argument type int64 but received type map[interface {}]interface {}")},
|
||||
{Script: `toDuration("")`, RunError: fmt.Errorf("function wants argument type int64 but received type string")},
|
||||
{Script: `toDuration("1s")`, RunError: fmt.Errorf("function wants argument type int64 but received type string")}, // TODO
|
||||
{Script: `toDuration(a)`, Input: map[string]interface{}{"a": int64(time.Duration(123 * time.Minute))}, RunOutput: time.Duration(123 * time.Minute)},
|
||||
{Script: `toDuration(a)`, Input: map[string]interface{}{"a": float64(time.Duration(123 * time.Minute))}, RunOutput: time.Duration(123 * time.Minute)},
|
||||
{Script: `toDuration(a)`, Input: map[string]interface{}{"a": time.Duration(123 * time.Minute)}, RunOutput: time.Duration(123 * time.Minute)},
|
||||
}
|
||||
testlib.Run(t, tests, &testlib.Options{EnvSetupFunc: &testCoreEnvSetupFunc})
|
||||
}
|
171
src/tool/run/core/toX.go
Normal file
171
src/tool/run/core/toX.go
Normal file
|
@ -0,0 +1,171 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
// ImportToX adds all the toX to the env given
|
||||
func ImportToX(e *env.Env) {
|
||||
|
||||
e.Define("toBool", func(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return false
|
||||
}
|
||||
nt := reflect.TypeOf(true)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Bool()
|
||||
}
|
||||
if rv.Type().ConvertibleTo(reflect.TypeOf(1.0)) && rv.Convert(reflect.TypeOf(1.0)).Float() > 0.0 {
|
||||
return true
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
s := strings.ToLower(v.(string))
|
||||
if s == "y" || s == "yes" {
|
||||
return true
|
||||
}
|
||||
b, err := strconv.ParseBool(s)
|
||||
if err == nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
e.Define("toString", func(v interface{}) string {
|
||||
if b, ok := v.([]byte); ok {
|
||||
return string(b)
|
||||
}
|
||||
return fmt.Sprint(v)
|
||||
})
|
||||
|
||||
e.Define("toInt", func(v interface{}) int64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return 0
|
||||
}
|
||||
nt := reflect.TypeOf(1)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Int()
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
i, err := strconv.ParseInt(v.(string), 10, 64)
|
||||
if err == nil {
|
||||
return i
|
||||
}
|
||||
f, err := strconv.ParseFloat(v.(string), 64)
|
||||
if err == nil {
|
||||
return int64(f)
|
||||
}
|
||||
}
|
||||
if rv.Kind() == reflect.Bool {
|
||||
if v.(bool) {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
e.Define("toFloat", func(v interface{}) float64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return 0
|
||||
}
|
||||
nt := reflect.TypeOf(1.0)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Float()
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
f, err := strconv.ParseFloat(v.(string), 64)
|
||||
if err == nil {
|
||||
return f
|
||||
}
|
||||
}
|
||||
if rv.Kind() == reflect.Bool {
|
||||
if v.(bool) {
|
||||
return 1.0
|
||||
}
|
||||
}
|
||||
return 0.0
|
||||
})
|
||||
|
||||
e.Define("toChar", func(s rune) string {
|
||||
return string(s)
|
||||
})
|
||||
|
||||
e.Define("toRune", func(s string) rune {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
return []rune(s)[0]
|
||||
})
|
||||
|
||||
e.Define("toBoolSlice", func(v []interface{}) []bool {
|
||||
var result []bool
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("toStringSlice", func(v []interface{}) []string {
|
||||
var result []string
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("toIntSlice", func(v []interface{}) []int64 {
|
||||
var result []int64
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("toFloatSlice", func(v []interface{}) []float64 {
|
||||
var result []float64
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("toByteSlice", func(s string) []byte {
|
||||
return []byte(s)
|
||||
})
|
||||
|
||||
e.Define("toRuneSlice", func(s string) []rune {
|
||||
return []rune(s)
|
||||
})
|
||||
|
||||
e.Define("toDuration", func(v int64) time.Duration {
|
||||
return time.Duration(v)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// toSlice takes in a "generic" slice and converts and copies
|
||||
// it's elements into the typed slice pointed at by ptr.
|
||||
// Note that this is a costly operation.
|
||||
func toSlice(from []interface{}, ptr interface{}) {
|
||||
// Value of the pointer to the target
|
||||
obj := reflect.Indirect(reflect.ValueOf(ptr))
|
||||
// We can't just convert from interface{} to whatever the target is (diff memory layout),
|
||||
// so we need to create a New slice of the proper type and copy the values individually
|
||||
t := reflect.TypeOf(ptr).Elem()
|
||||
tt := t.Elem()
|
||||
slice := reflect.MakeSlice(t, len(from), len(from))
|
||||
// Copying the data, val is an addressable Pointer of the actual target type
|
||||
val := reflect.Indirect(reflect.New(tt))
|
||||
for i := 0; i < len(from); i++ {
|
||||
v := reflect.ValueOf(from[i])
|
||||
if v.IsValid() && v.Type().ConvertibleTo(tt) {
|
||||
val.Set(v.Convert(tt))
|
||||
} else {
|
||||
val.Set(reflect.Zero(tt))
|
||||
}
|
||||
slice.Index(i).Set(val)
|
||||
}
|
||||
// Ok now assign our slice to the target pointer
|
||||
obj.Set(slice)
|
||||
}
|
187
src/tool/run/env/env.go
vendored
Normal file
187
src/tool/run/env/env.go
vendored
Normal file
|
@ -0,0 +1,187 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
// ExternalLookup for Env external lookup of values and types.
|
||||
ExternalLookup interface {
|
||||
Get(string) (reflect.Value, error)
|
||||
Type(string) (reflect.Type, error)
|
||||
}
|
||||
|
||||
// Env is the environment needed for a VM to run in.
|
||||
Env struct {
|
||||
rwMutex *sync.RWMutex
|
||||
parent *Env
|
||||
values map[string]reflect.Value
|
||||
types map[string]reflect.Type
|
||||
externalLookup ExternalLookup
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// Packages is a where packages can be stored so VM import command can be used to import them.
|
||||
// reflect.Value must be valid or VM may crash.
|
||||
// For nil must use NilValue.
|
||||
Packages = make(map[string]map[string]reflect.Value)
|
||||
// PackageTypes is a where package types can be stored so VM import command can be used to import them
|
||||
// reflect.Type must be valid or VM may crash.
|
||||
// For nil type must use NilType.
|
||||
PackageTypes = make(map[string]map[string]reflect.Type)
|
||||
|
||||
// NilType is the reflect.type of nil
|
||||
NilType = reflect.TypeOf(nil)
|
||||
// NilValue is the reflect.value of nil
|
||||
NilValue = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem()
|
||||
|
||||
basicTypes = map[string]reflect.Type{
|
||||
"interface": reflect.ValueOf([]interface{}{int64(1)}).Index(0).Type(),
|
||||
"bool": reflect.TypeOf(true),
|
||||
"string": reflect.TypeOf("a"),
|
||||
"int": reflect.TypeOf(int(1)),
|
||||
"int32": reflect.TypeOf(int32(1)),
|
||||
"int64": reflect.TypeOf(int64(1)),
|
||||
"uint": reflect.TypeOf(uint(1)),
|
||||
"uint32": reflect.TypeOf(uint32(1)),
|
||||
"uint64": reflect.TypeOf(uint64(1)),
|
||||
"byte": reflect.TypeOf(byte(1)),
|
||||
"rune": reflect.TypeOf('a'),
|
||||
"float32": reflect.TypeOf(float32(1)),
|
||||
"float64": reflect.TypeOf(float64(1)),
|
||||
}
|
||||
|
||||
// ErrSymbolContainsDot symbol contains .
|
||||
ErrSymbolContainsDot = errors.New("symbol contains '.'")
|
||||
)
|
||||
|
||||
// NewEnv creates new global scope.
|
||||
func NewEnv() *Env {
|
||||
return &Env{
|
||||
rwMutex: &sync.RWMutex{},
|
||||
values: make(map[string]reflect.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// NewEnv creates new child scope.
|
||||
func (e *Env) NewEnv() *Env {
|
||||
return &Env{
|
||||
rwMutex: &sync.RWMutex{},
|
||||
parent: e,
|
||||
values: make(map[string]reflect.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// NewModule creates new child scope and define it as a symbol.
|
||||
// This is a shortcut for calling e.NewEnv then Define that new Env.
|
||||
func (e *Env) NewModule(symbol string) (*Env, error) {
|
||||
module := &Env{
|
||||
rwMutex: &sync.RWMutex{},
|
||||
parent: e,
|
||||
values: make(map[string]reflect.Value),
|
||||
}
|
||||
return module, e.Define(symbol, module)
|
||||
}
|
||||
|
||||
// SetExternalLookup sets an external lookup
|
||||
func (e *Env) SetExternalLookup(externalLookup ExternalLookup) {
|
||||
e.externalLookup = externalLookup
|
||||
}
|
||||
|
||||
// String returns string of values and types in current scope.
|
||||
func (e *Env) String() string {
|
||||
var buffer bytes.Buffer
|
||||
e.rwMutex.RLock()
|
||||
|
||||
if e.parent == nil {
|
||||
buffer.WriteString("No parent\n")
|
||||
} else {
|
||||
buffer.WriteString("Has parent\n")
|
||||
}
|
||||
|
||||
for symbol, value := range e.values {
|
||||
buffer.WriteString(fmt.Sprintf("%v = %#v\n", symbol, value))
|
||||
}
|
||||
|
||||
for symbol, aType := range e.types {
|
||||
buffer.WriteString(fmt.Sprintf("%v = %v\n", symbol, aType))
|
||||
}
|
||||
|
||||
e.rwMutex.RUnlock()
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// GetEnvFromPath returns Env from path
|
||||
func (e *Env) GetEnvFromPath(path []string) (*Env, error) {
|
||||
if len(path) < 1 {
|
||||
return e, nil
|
||||
}
|
||||
|
||||
var value reflect.Value
|
||||
var ok bool
|
||||
for {
|
||||
// find starting env
|
||||
value, ok = e.values[path[0]]
|
||||
if ok {
|
||||
e, ok = value.Interface().(*Env)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if e.parent == nil {
|
||||
return nil, fmt.Errorf("no namespace called: %v", path[0])
|
||||
}
|
||||
e = e.parent
|
||||
}
|
||||
|
||||
for i := 1; i < len(path); i++ {
|
||||
// find child env
|
||||
value, ok = e.values[path[i]]
|
||||
if ok {
|
||||
e, ok = value.Interface().(*Env)
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no namespace called: %v", path[i])
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// Copy the Env for current scope
|
||||
func (e *Env) Copy() *Env {
|
||||
e.rwMutex.RLock()
|
||||
copy := Env{
|
||||
rwMutex: &sync.RWMutex{},
|
||||
parent: e.parent,
|
||||
values: make(map[string]reflect.Value, len(e.values)),
|
||||
externalLookup: e.externalLookup,
|
||||
}
|
||||
for name, value := range e.values {
|
||||
copy.values[name] = value
|
||||
}
|
||||
if e.types != nil {
|
||||
copy.types = make(map[string]reflect.Type, len(e.types))
|
||||
for name, t := range e.types {
|
||||
copy.types[name] = t
|
||||
}
|
||||
}
|
||||
e.rwMutex.RUnlock()
|
||||
return ©
|
||||
}
|
||||
|
||||
// DeepCopy the Env for current scope and parent scopes.
|
||||
// Note that each scope is a consistent snapshot but not the whole.
|
||||
func (e *Env) DeepCopy() *Env {
|
||||
e = e.Copy()
|
||||
if e.parent != nil {
|
||||
e.parent = e.parent.DeepCopy()
|
||||
}
|
||||
return e
|
||||
}
|
235
src/tool/run/env/envExternalLookup_test.go
vendored
Normal file
235
src/tool/run/env/envExternalLookup_test.go
vendored
Normal file
|
@ -0,0 +1,235 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestExternalLookup struct {
|
||||
values map[string]reflect.Value
|
||||
types map[string]reflect.Type
|
||||
}
|
||||
|
||||
func NewTestExternalLookup() *TestExternalLookup {
|
||||
return &TestExternalLookup{
|
||||
values: make(map[string]reflect.Value),
|
||||
types: make(map[string]reflect.Type),
|
||||
}
|
||||
}
|
||||
|
||||
func (testExternalLookup *TestExternalLookup) SetValue(symbol string, value interface{}) error {
|
||||
if strings.Contains(symbol, ".") {
|
||||
return ErrSymbolContainsDot
|
||||
}
|
||||
|
||||
if value == nil {
|
||||
testExternalLookup.values[symbol] = NilValue
|
||||
} else {
|
||||
testExternalLookup.values[symbol] = reflect.ValueOf(value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (testExternalLookup *TestExternalLookup) Get(symbol string) (reflect.Value, error) {
|
||||
if value, ok := testExternalLookup.values[symbol]; ok {
|
||||
return value, nil
|
||||
}
|
||||
return NilValue, fmt.Errorf("undefined symbol '%s'", symbol)
|
||||
}
|
||||
|
||||
func (testExternalLookup *TestExternalLookup) DefineType(symbol string, aType interface{}) error {
|
||||
if strings.Contains(symbol, ".") {
|
||||
return ErrSymbolContainsDot
|
||||
}
|
||||
|
||||
var reflectType reflect.Type
|
||||
if aType == nil {
|
||||
reflectType = NilType
|
||||
} else {
|
||||
var ok bool
|
||||
reflectType, ok = reflectType.(reflect.Type)
|
||||
if !ok {
|
||||
reflectType = reflect.TypeOf(aType)
|
||||
}
|
||||
}
|
||||
|
||||
testExternalLookup.types[symbol] = reflectType
|
||||
return nil
|
||||
}
|
||||
|
||||
func (testExternalLookup *TestExternalLookup) Type(symbol string) (reflect.Type, error) {
|
||||
if value, ok := testExternalLookup.types[symbol]; ok {
|
||||
return value, nil
|
||||
}
|
||||
return NilType, fmt.Errorf("undefined symbol '%s'", symbol)
|
||||
}
|
||||
|
||||
func TestExternalLookupValueAndGet(t *testing.T) {
|
||||
var err error
|
||||
var value interface{}
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
varGetValue interface{}
|
||||
varKind reflect.Kind
|
||||
defineError error
|
||||
getError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, varGetValue: nil, varKind: reflect.Interface},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, varGetValue: true, varKind: reflect.Bool},
|
||||
{testInfo: "int16", varName: "a", varDefineValue: int16(1), varGetValue: int16(1), varKind: reflect.Int16},
|
||||
{testInfo: "int32", varName: "a", varDefineValue: int32(1), varGetValue: int32(1), varKind: reflect.Int32},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), varGetValue: int64(1), varKind: reflect.Int64},
|
||||
{testInfo: "uint32", varName: "a", varDefineValue: uint32(1), varGetValue: uint32(1), varKind: reflect.Uint32},
|
||||
{testInfo: "uint64", varName: "a", varDefineValue: uint64(1), varGetValue: uint64(1), varKind: reflect.Uint64},
|
||||
{testInfo: "float32", varName: "a", varDefineValue: float32(1), varGetValue: float32(1), varKind: reflect.Float32},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), varGetValue: float64(1), varKind: reflect.Float64},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", varGetValue: "a", varKind: reflect.String},
|
||||
|
||||
{testInfo: "string with dot", varName: "a.a", varDefineValue: "a", varGetValue: nil, varKind: reflect.String, defineError: ErrSymbolContainsDot, getError: fmt.Errorf("undefined symbol 'a.a'")},
|
||||
{testInfo: "string with quotes", varName: "a", varDefineValue: `"a"`, varGetValue: `"a"`, varKind: reflect.String},
|
||||
}
|
||||
|
||||
// ExternalLookup set And get
|
||||
for _, test := range tests {
|
||||
testExternalLookup := NewTestExternalLookup()
|
||||
env := NewEnv()
|
||||
env.SetExternalLookup(testExternalLookup)
|
||||
|
||||
err = testExternalLookup.SetValue(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("TestExternalLookupValueAndGet %v - SetValue error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("TestExternalLookupValueAndGet %v - SetValue error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
value, err = env.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("TestExternalLookupValueAndGet %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("TestExternalLookupValueAndGet %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("TestExternalLookupValueAndGet %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalLookupTypeAndGet(t *testing.T) {
|
||||
var err error
|
||||
var valueType reflect.Type
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
defineError error
|
||||
typeError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true},
|
||||
{testInfo: "int16", varName: "a", varDefineValue: int16(1)},
|
||||
{testInfo: "int32", varName: "a", varDefineValue: int32(1)},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1)},
|
||||
{testInfo: "uint32", varName: "a", varDefineValue: uint32(1)},
|
||||
{testInfo: "uint64", varName: "a", varDefineValue: uint64(1)},
|
||||
{testInfo: "float32", varName: "a", varDefineValue: float32(1)},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1)},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a"},
|
||||
|
||||
{testInfo: "string with dot", varName: "a.a", varDefineValue: nil, defineError: ErrSymbolContainsDot, typeError: fmt.Errorf("undefined type 'a.a'")},
|
||||
}
|
||||
|
||||
// DefineType
|
||||
for _, test := range tests {
|
||||
testExternalLookup := NewTestExternalLookup()
|
||||
env := NewEnv()
|
||||
env.SetExternalLookup(testExternalLookup)
|
||||
|
||||
err = testExternalLookup.DefineType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - DefineType error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - DefineType error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = env.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("TestExternalLookupTypeAndGet %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestExternalLookupAddr(t *testing.T) {
|
||||
var err error
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
defineError error
|
||||
addrError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, addrError: nil},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", addrError: fmt.Errorf("unaddressable")},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
testExternalLookup := NewTestExternalLookup()
|
||||
envParent.SetExternalLookup(testExternalLookup)
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = testExternalLookup.SetValue(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("TestExternalLookupAddr %v - SetValue error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("TestExternalLookupAddr %v - SetValue error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = envChild.Addr(test.varName)
|
||||
if err != nil && test.addrError != nil {
|
||||
if err.Error() != test.addrError.Error() {
|
||||
t.Errorf("TestExternalLookupAddr %v - Addr error - received: %v - expected: %v", test.testInfo, err, test.addrError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.addrError {
|
||||
t.Errorf("TestExternalLookupAddr %v - Addr error - received: %v - expected: %v", test.testInfo, err, test.addrError)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
83
src/tool/run/env/envTypes.go
vendored
Normal file
83
src/tool/run/env/envTypes.go
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DefineType defines type in current scope.
|
||||
func (e *Env) DefineType(symbol string, aType interface{}) error {
|
||||
var reflectType reflect.Type
|
||||
if aType == nil {
|
||||
reflectType = NilType
|
||||
} else {
|
||||
var ok bool
|
||||
reflectType, ok = aType.(reflect.Type)
|
||||
if !ok {
|
||||
reflectType = reflect.TypeOf(aType)
|
||||
}
|
||||
}
|
||||
|
||||
return e.DefineReflectType(symbol, reflectType)
|
||||
}
|
||||
|
||||
// DefineReflectType defines type in current scope.
|
||||
func (e *Env) DefineReflectType(symbol string, reflectType reflect.Type) error {
|
||||
if strings.Contains(symbol, ".") {
|
||||
return ErrSymbolContainsDot
|
||||
}
|
||||
|
||||
e.rwMutex.Lock()
|
||||
if e.types == nil {
|
||||
e.types = make(map[string]reflect.Type)
|
||||
}
|
||||
e.types[symbol] = reflectType
|
||||
e.rwMutex.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefineGlobalType defines type in global scope.
|
||||
func (e *Env) DefineGlobalType(symbol string, aType interface{}) error {
|
||||
for e.parent != nil {
|
||||
e = e.parent
|
||||
}
|
||||
return e.DefineType(symbol, aType)
|
||||
}
|
||||
|
||||
// DefineGlobalReflectType defines type in global scope.
|
||||
func (e *Env) DefineGlobalReflectType(symbol string, reflectType reflect.Type) error {
|
||||
for e.parent != nil {
|
||||
e = e.parent
|
||||
}
|
||||
return e.DefineReflectType(symbol, reflectType)
|
||||
}
|
||||
|
||||
// Type returns reflect type from the scope where symbol is frist found.
|
||||
func (e *Env) Type(symbol string) (reflect.Type, error) {
|
||||
e.rwMutex.RLock()
|
||||
reflectType, ok := e.types[symbol]
|
||||
e.rwMutex.RUnlock()
|
||||
if ok {
|
||||
return reflectType, nil
|
||||
}
|
||||
|
||||
if e.externalLookup != nil {
|
||||
var err error
|
||||
reflectType, err = e.externalLookup.Type(symbol)
|
||||
if err == nil {
|
||||
return reflectType, nil
|
||||
}
|
||||
}
|
||||
|
||||
if e.parent == nil {
|
||||
reflectType, ok = basicTypes[symbol]
|
||||
if ok {
|
||||
return reflectType, nil
|
||||
}
|
||||
return NilType, fmt.Errorf("undefined type '%s'", symbol)
|
||||
}
|
||||
|
||||
return e.parent.Type(symbol)
|
||||
}
|
313
src/tool/run/env/envTypes_test.go
vendored
Normal file
313
src/tool/run/env/envTypes_test.go
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBasicType(t *testing.T) {
|
||||
env := NewEnv()
|
||||
aType, err := env.Type("string")
|
||||
if err != nil {
|
||||
t.Fatalf("Type error - %v", err)
|
||||
}
|
||||
if aType != reflect.TypeOf("a") {
|
||||
t.Errorf("Type - received: %v - expected: %v", aType, reflect.TypeOf("a"))
|
||||
}
|
||||
|
||||
aType, err = env.Type("int64")
|
||||
if err != nil {
|
||||
t.Fatal("Type error:", err)
|
||||
}
|
||||
if aType != reflect.TypeOf(int64(1)) {
|
||||
t.Errorf("Type - received: %v - expected: %v", aType, reflect.TypeOf(int64(1)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefineType(t *testing.T) {
|
||||
var err error
|
||||
var valueType reflect.Type
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
defineError error
|
||||
typeError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true},
|
||||
{testInfo: "int16", varName: "a", varDefineValue: int16(1)},
|
||||
{testInfo: "int32", varName: "a", varDefineValue: int32(1)},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1)},
|
||||
{testInfo: "uint32", varName: "a", varDefineValue: uint32(1)},
|
||||
{testInfo: "uint64", varName: "a", varDefineValue: uint64(1)},
|
||||
{testInfo: "float32", varName: "a", varDefineValue: float32(1)},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1)},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a"},
|
||||
|
||||
{testInfo: "string with dot", varName: "a.a", varDefineValue: nil, defineError: ErrSymbolContainsDot, typeError: fmt.Errorf("undefined type 'a.a'")},
|
||||
}
|
||||
|
||||
// DefineType
|
||||
for _, test := range tests {
|
||||
env := NewEnv()
|
||||
|
||||
err = env.DefineType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = env.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
|
||||
// DefineType NewEnv
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envParent.DefineType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineType NewEnv %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineType NewEnv %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = envChild.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineType NewEnv %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineType NewEnv %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineType NewEnv %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineType NewEnv %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
|
||||
// DefineType NewModule
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild, err := envParent.NewModule("envChild")
|
||||
if err != nil {
|
||||
t.Fatalf("DefineType NewModule %v - NewModule error - received: %v - expected: %v", test.testInfo, err, nil)
|
||||
}
|
||||
|
||||
err = envParent.DefineType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineType NewModule %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineType NewModule %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = envChild.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineType NewModule %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineType NewModule %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineType NewModule %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineType NewModule %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
|
||||
// DefineGlobalType
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envChild.DefineGlobalType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineGlobalType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineGlobalType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = envParent.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineGlobalType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineGlobalType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineGlobalType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineGlobalType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
|
||||
valueType, err = envChild.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineGlobalType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineGlobalType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineGlobalType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineGlobalType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
|
||||
// DefineGlobalReflectType
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envChild.DefineGlobalReflectType(test.varName, reflect.TypeOf(test.varDefineValue))
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineGlobalReflectType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineGlobalReflectType %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType, err = envParent.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
|
||||
valueType, err = envChild.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
if valueType == nil || test.varDefineValue == nil {
|
||||
if valueType != reflect.TypeOf(test.varDefineValue) {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
} else if valueType.String() != reflect.TypeOf(test.varDefineValue).String() {
|
||||
t.Errorf("DefineGlobalReflectType %v - Type check - received: %v - expected: %v", test.testInfo, valueType, reflect.TypeOf(test.varDefineValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefineTypeFail(t *testing.T) {
|
||||
var err error
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
defineError error
|
||||
typeError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "int16", varName: "a", varDefineValue: int16(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "int32", varName: "a", varDefineValue: int32(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "uint32", varName: "a", varDefineValue: uint32(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "uint64", varName: "a", varDefineValue: uint64(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "float32", varName: "a", varDefineValue: float32(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), typeError: fmt.Errorf("undefined type 'a'")},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", typeError: fmt.Errorf("undefined type 'a'")},
|
||||
}
|
||||
|
||||
// DefineTypeFail
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envChild.DefineType(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("TestDefineTypeFail %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("TestDefineTypeFail %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = envParent.Type(test.varName)
|
||||
if err != nil && test.typeError != nil {
|
||||
if err.Error() != test.typeError.Error() {
|
||||
t.Errorf("TestDefineTypeFail %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.typeError {
|
||||
t.Errorf("TestDefineTypeFail %v - Type error - received: %v - expected: %v", test.testInfo, err, test.typeError)
|
||||
}
|
||||
}
|
||||
}
|
161
src/tool/run/env/envValues.go
vendored
Normal file
161
src/tool/run/env/envValues.go
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// define
|
||||
|
||||
// Define defines/sets interface value to symbol in current scope.
|
||||
func (e *Env) Define(symbol string, value interface{}) error {
|
||||
if value == nil {
|
||||
return e.DefineValue(symbol, NilValue)
|
||||
}
|
||||
return e.DefineValue(symbol, reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// DefineValue defines/sets reflect value to symbol in current scope.
|
||||
func (e *Env) DefineValue(symbol string, value reflect.Value) error {
|
||||
if strings.Contains(symbol, ".") {
|
||||
return ErrSymbolContainsDot
|
||||
}
|
||||
e.rwMutex.Lock()
|
||||
e.values[symbol] = value
|
||||
e.rwMutex.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefineGlobal defines/sets interface value to symbol in global scope.
|
||||
func (e *Env) DefineGlobal(symbol string, value interface{}) error {
|
||||
for e.parent != nil {
|
||||
e = e.parent
|
||||
}
|
||||
return e.Define(symbol, value)
|
||||
}
|
||||
|
||||
// DefineGlobalValue defines/sets reflect value to symbol in global scope.
|
||||
func (e *Env) DefineGlobalValue(symbol string, value reflect.Value) error {
|
||||
for e.parent != nil {
|
||||
e = e.parent
|
||||
}
|
||||
return e.DefineValue(symbol, value)
|
||||
}
|
||||
|
||||
// set
|
||||
|
||||
// Set interface value to the scope where symbol is frist found.
|
||||
func (e *Env) Set(symbol string, value interface{}) error {
|
||||
if value == nil {
|
||||
return e.SetValue(symbol, NilValue)
|
||||
}
|
||||
return e.SetValue(symbol, reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// SetValue reflect value to the scope where symbol is frist found.
|
||||
func (e *Env) SetValue(symbol string, value reflect.Value) error {
|
||||
e.rwMutex.RLock()
|
||||
_, ok := e.values[symbol]
|
||||
e.rwMutex.RUnlock()
|
||||
if ok {
|
||||
e.rwMutex.Lock()
|
||||
e.values[symbol] = value
|
||||
e.rwMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
if e.parent == nil {
|
||||
return fmt.Errorf("undefined symbol '%s'", symbol)
|
||||
}
|
||||
return e.parent.SetValue(symbol, value)
|
||||
}
|
||||
|
||||
// get
|
||||
|
||||
// Get returns interface value from the scope where symbol is frist found.
|
||||
func (e *Env) Get(symbol string) (interface{}, error) {
|
||||
rv, err := e.GetValue(symbol)
|
||||
return rv.Interface(), err
|
||||
}
|
||||
|
||||
// GetValue returns reflect value from the scope where symbol is frist found.
|
||||
func (e *Env) GetValue(symbol string) (reflect.Value, error) {
|
||||
e.rwMutex.RLock()
|
||||
value, ok := e.values[symbol]
|
||||
e.rwMutex.RUnlock()
|
||||
if ok {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
if e.externalLookup != nil {
|
||||
var err error
|
||||
value, err = e.externalLookup.Get(symbol)
|
||||
if err == nil {
|
||||
return value, nil
|
||||
}
|
||||
}
|
||||
|
||||
if e.parent == nil {
|
||||
return NilValue, fmt.Errorf("undefined symbol '%s'", symbol)
|
||||
}
|
||||
|
||||
return e.parent.GetValue(symbol)
|
||||
}
|
||||
|
||||
// delete
|
||||
|
||||
// Delete deletes symbol in current scope.
|
||||
func (e *Env) Delete(symbol string) {
|
||||
e.rwMutex.Lock()
|
||||
delete(e.values, symbol)
|
||||
e.rwMutex.Unlock()
|
||||
}
|
||||
|
||||
// DeleteGlobal deletes the first matching symbol found in current or parent scope.
|
||||
func (e *Env) DeleteGlobal(symbol string) {
|
||||
if e.parent == nil {
|
||||
e.Delete(symbol)
|
||||
return
|
||||
}
|
||||
|
||||
e.rwMutex.RLock()
|
||||
_, ok := e.values[symbol]
|
||||
e.rwMutex.RUnlock()
|
||||
|
||||
if ok {
|
||||
e.Delete(symbol)
|
||||
return
|
||||
}
|
||||
|
||||
e.parent.DeleteGlobal(symbol)
|
||||
}
|
||||
|
||||
// Addr
|
||||
|
||||
// Addr returns reflect.Addr of value for first matching symbol found in current or parent scope.
|
||||
func (e *Env) Addr(symbol string) (reflect.Value, error) {
|
||||
e.rwMutex.RLock()
|
||||
defer e.rwMutex.RUnlock()
|
||||
|
||||
if v, ok := e.values[symbol]; ok {
|
||||
if v.CanAddr() {
|
||||
return v.Addr(), nil
|
||||
}
|
||||
return NilValue, fmt.Errorf("unaddressable")
|
||||
}
|
||||
if e.externalLookup != nil {
|
||||
v, err := e.externalLookup.Get(symbol)
|
||||
if err == nil {
|
||||
if v.CanAddr() {
|
||||
return v.Addr(), nil
|
||||
}
|
||||
return NilValue, fmt.Errorf("unaddressable")
|
||||
}
|
||||
}
|
||||
if e.parent == nil {
|
||||
return NilValue, fmt.Errorf("undefined symbol '%s'", symbol)
|
||||
}
|
||||
return e.parent.Addr(symbol)
|
||||
}
|
787
src/tool/run/env/envValues_test.go
vendored
Normal file
787
src/tool/run/env/envValues_test.go
vendored
Normal file
|
@ -0,0 +1,787 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetError(t *testing.T) {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
err := envChild.Set("a", "a")
|
||||
if err == nil {
|
||||
t.Errorf("Set error - received: %v - expected: %v", err, fmt.Errorf("undefined symbol 'a'"))
|
||||
} else if err.Error() != "undefined symbol 'a'" {
|
||||
t.Errorf("Set error - received: %v - expected: %v", err, fmt.Errorf("undefined symbol 'a'"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddrError(t *testing.T) {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
_, err := envChild.Addr("a")
|
||||
if err == nil {
|
||||
t.Errorf("Addr error - received: %v - expected: %v", err, fmt.Errorf("undefined symbol 'a'"))
|
||||
} else if err.Error() != "undefined symbol 'a'" {
|
||||
t.Errorf("Addr error - received: %v - expected: %v", err, fmt.Errorf("undefined symbol 'a'"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefineGlobalValue(t *testing.T) {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
err := envChild.DefineGlobalValue("a", reflect.ValueOf("a"))
|
||||
if err != nil {
|
||||
t.Fatal("DefineGlobalValue error:", err)
|
||||
}
|
||||
|
||||
var value interface{}
|
||||
value, err = envParent.Get("a")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
t.Fatalf("value - received: %T - expected: %T", value, "a")
|
||||
}
|
||||
if v != "a" {
|
||||
t.Fatalf("value - received: %v - expected: %v", v, "a")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefineAndGet(t *testing.T) {
|
||||
var err error
|
||||
var value interface{}
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
varGetValue interface{}
|
||||
varKind reflect.Kind
|
||||
defineError error
|
||||
getError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: reflect.Value{}, varGetValue: reflect.Value{}, varKind: reflect.Invalid},
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, varGetValue: nil, varKind: reflect.Interface},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, varGetValue: true, varKind: reflect.Bool},
|
||||
{testInfo: "int16", varName: "a", varDefineValue: int16(1), varGetValue: int16(1), varKind: reflect.Int16},
|
||||
{testInfo: "int32", varName: "a", varDefineValue: int32(1), varGetValue: int32(1), varKind: reflect.Int32},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), varGetValue: int64(1), varKind: reflect.Int64},
|
||||
{testInfo: "uint32", varName: "a", varDefineValue: uint32(1), varGetValue: uint32(1), varKind: reflect.Uint32},
|
||||
{testInfo: "uint64", varName: "a", varDefineValue: uint64(1), varGetValue: uint64(1), varKind: reflect.Uint64},
|
||||
{testInfo: "float32", varName: "a", varDefineValue: float32(1), varGetValue: float32(1), varKind: reflect.Float32},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), varGetValue: float64(1), varKind: reflect.Float64},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", varGetValue: "a", varKind: reflect.String},
|
||||
|
||||
{testInfo: "string with dot", varName: "a.a", varDefineValue: "a", varGetValue: nil, varKind: reflect.Interface, defineError: ErrSymbolContainsDot, getError: fmt.Errorf("undefined symbol 'a.a'")},
|
||||
{testInfo: "string with quotes", varName: "a", varDefineValue: `"a"`, varGetValue: `"a"`, varKind: reflect.String},
|
||||
}
|
||||
|
||||
// DefineAndGet
|
||||
for _, test := range tests {
|
||||
env := NewEnv()
|
||||
|
||||
err = env.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineAndGet %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineAndGet %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = env.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineAndGet %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineAndGet %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineAndGet %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
}
|
||||
|
||||
// DefineAndGet NewEnv
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envParent.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineAndGet NewEnv %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineAndGet NewEnv %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envChild.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineAndGet NewEnv %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineAndGet NewEnv %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineAndGet NewEnv %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
}
|
||||
|
||||
// DefineAndGet DefineGlobal
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envChild.DefineGlobal(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineAndGet DefineGlobal %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineAndGet DefineGlobal %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envParent.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineAndGet DefineGlobal %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineAndGet DefineGlobal %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineAndGet DefineGlobal %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDefineModify(t *testing.T) {
|
||||
var err error
|
||||
var value interface{}
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
varGetValue interface{}
|
||||
varKind reflect.Kind
|
||||
defineError error
|
||||
getError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, varGetValue: nil, varKind: reflect.Interface},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, varGetValue: true, varKind: reflect.Bool},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), varGetValue: int64(1), varKind: reflect.Int64},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), varGetValue: float64(1), varKind: reflect.Float64},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", varGetValue: "a", varKind: reflect.String},
|
||||
}
|
||||
changeTests := []struct {
|
||||
varDefineValue interface{}
|
||||
varGetValue interface{}
|
||||
varKind reflect.Kind
|
||||
defineError error
|
||||
getError error
|
||||
}{
|
||||
{varDefineValue: nil, varGetValue: nil, varKind: reflect.Interface},
|
||||
{varDefineValue: "a", varGetValue: "a", varKind: reflect.String},
|
||||
{varDefineValue: int64(1), varGetValue: int64(1), varKind: reflect.Int64},
|
||||
{varDefineValue: float64(1), varGetValue: float64(1), varKind: reflect.Float64},
|
||||
{varDefineValue: true, varGetValue: true, varKind: reflect.Bool},
|
||||
}
|
||||
|
||||
// DefineModify
|
||||
for _, test := range tests {
|
||||
env := NewEnv()
|
||||
|
||||
err = env.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineModify %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineModify %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = env.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineModify %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineModify %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineModify %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
|
||||
// DefineModify changeTest
|
||||
for _, changeTest := range changeTests {
|
||||
err = env.Set(test.varName, changeTest.varDefineValue)
|
||||
if err != nil && changeTest.defineError != nil {
|
||||
if err.Error() != changeTest.defineError.Error() {
|
||||
t.Errorf("DefineModify changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.defineError {
|
||||
t.Errorf("DefineModify changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = env.Get(test.varName)
|
||||
if err != nil && changeTest.getError != nil {
|
||||
if err.Error() != changeTest.getError.Error() {
|
||||
t.Errorf("DefineModify changeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.getError {
|
||||
t.Errorf("DefineModify changeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
if value != changeTest.varGetValue {
|
||||
t.Errorf("DefineModify changeTest %v - value check - received %#v expected: %#v", test.testInfo, value, changeTest.varGetValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DefineModify envParent
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envParent.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineModify envParent %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineModify envParent %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envChild.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineModify envParent %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineModify envParent %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineModify envParent %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
|
||||
for _, changeTest := range changeTests {
|
||||
err = envParent.Set(test.varName, changeTest.varDefineValue)
|
||||
if err != nil && changeTest.defineError != nil {
|
||||
if err.Error() != changeTest.defineError.Error() {
|
||||
t.Errorf("DefineModify envParent changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.defineError {
|
||||
t.Errorf("DefineModify envParent changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envChild.Get(test.varName)
|
||||
if err != nil && changeTest.getError != nil {
|
||||
if err.Error() != changeTest.getError.Error() {
|
||||
t.Errorf("DefineModify envParent changeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.getError {
|
||||
t.Errorf("ChanDefineModify envParent changeTestgeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
if value != changeTest.varGetValue {
|
||||
t.Errorf("DefineModify envParent changeTest %v - value check - received %#v expected: %#v", test.testInfo, value, changeTest.varGetValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DefineModify envChild
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envParent.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("DefineModify envChild %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("DefineModify envChild %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envChild.Get(test.varName)
|
||||
if err != nil && test.getError != nil {
|
||||
if err.Error() != test.getError.Error() {
|
||||
t.Errorf("DefineModify envChild %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.getError {
|
||||
t.Errorf("DefineModify envChild %v - Get error - received: %v - expected: %v", test.testInfo, err, test.getError)
|
||||
continue
|
||||
}
|
||||
if value != test.varGetValue {
|
||||
t.Errorf("DefineModify envChild %v - value check - received %#v expected: %#v", test.testInfo, value, test.varGetValue)
|
||||
}
|
||||
|
||||
for _, changeTest := range changeTests {
|
||||
err = envChild.Set(test.varName, changeTest.varDefineValue)
|
||||
if err != nil && changeTest.defineError != nil {
|
||||
if err.Error() != changeTest.defineError.Error() {
|
||||
t.Errorf("DefineModify envChild changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.defineError {
|
||||
t.Errorf("DefineModify envChild changeTest %v - Set error - received: %v - expected: %v", test.testInfo, err, changeTest.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err = envChild.Get(test.varName)
|
||||
if err != nil && changeTest.getError != nil {
|
||||
if err.Error() != changeTest.getError.Error() {
|
||||
t.Errorf("DefineModify envChild changeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
} else if err != changeTest.getError {
|
||||
t.Errorf("ChanDefineModify envChild changeTestgeTest %v - Get error - received: %v - expected: %v", test.testInfo, err, changeTest.getError)
|
||||
continue
|
||||
}
|
||||
if value != changeTest.varGetValue {
|
||||
t.Errorf("DefineModify envChild changeTest %v - value check - received %#v expected: %#v", test.testInfo, value, changeTest.varGetValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddr(t *testing.T) {
|
||||
var err error
|
||||
tests := []struct {
|
||||
testInfo string
|
||||
varName string
|
||||
varDefineValue interface{}
|
||||
defineError error
|
||||
addrError error
|
||||
}{
|
||||
{testInfo: "nil", varName: "a", varDefineValue: nil, addrError: nil},
|
||||
{testInfo: "string", varName: "a", varDefineValue: "a", addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "int64", varName: "a", varDefineValue: int64(1), addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "float64", varName: "a", varDefineValue: float64(1), addrError: fmt.Errorf("unaddressable")},
|
||||
{testInfo: "bool", varName: "a", varDefineValue: true, addrError: fmt.Errorf("unaddressable")},
|
||||
}
|
||||
|
||||
// TestAddr
|
||||
for _, test := range tests {
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
err = envParent.Define(test.varName, test.varDefineValue)
|
||||
if err != nil && test.defineError != nil {
|
||||
if err.Error() != test.defineError.Error() {
|
||||
t.Errorf("TestAddr %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.defineError {
|
||||
t.Errorf("TestAddr %v - Define error - received: %v - expected: %v", test.testInfo, err, test.defineError)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = envChild.Addr(test.varName)
|
||||
if err != nil && test.addrError != nil {
|
||||
if err.Error() != test.addrError.Error() {
|
||||
t.Errorf("TestAddr %v - Addr error - received: %v - expected: %v", test.testInfo, err, test.addrError)
|
||||
continue
|
||||
}
|
||||
} else if err != test.addrError {
|
||||
t.Errorf("TestAddr %v - Addr error - received: %v - expected: %v", test.testInfo, err, test.addrError)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
// empty
|
||||
env := NewEnv()
|
||||
env.Delete("a")
|
||||
|
||||
// add & delete a
|
||||
env.Define("a", "a")
|
||||
env.Delete("a")
|
||||
|
||||
value, err := env.Get("a")
|
||||
expectedError := "undefined symbol 'a'"
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, expectedError)
|
||||
}
|
||||
if value != nil {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteGlobal(t *testing.T) {
|
||||
// empty
|
||||
env := NewEnv()
|
||||
env.DeleteGlobal("a")
|
||||
|
||||
// add & delete a
|
||||
env.Define("a", "a")
|
||||
env.DeleteGlobal("a")
|
||||
|
||||
value, err := env.Get("a")
|
||||
expectedError := "undefined symbol 'a'"
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, expectedError)
|
||||
}
|
||||
if value != nil {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, nil)
|
||||
}
|
||||
|
||||
// parent & child, var in child, delete in parent
|
||||
envChild := env.NewEnv()
|
||||
envChild.Define("a", "a")
|
||||
env.DeleteGlobal("a")
|
||||
|
||||
value, err = envChild.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, nil)
|
||||
}
|
||||
if value != "a" {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, "a")
|
||||
}
|
||||
|
||||
// parent & child, var in child, delete in child
|
||||
envChild.DeleteGlobal("a")
|
||||
|
||||
value, err = envChild.Get("a")
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, expectedError)
|
||||
}
|
||||
if value != nil {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, nil)
|
||||
}
|
||||
|
||||
// parent & child, var in parent, delete in child
|
||||
env.Define("a", "a")
|
||||
envChild.DeleteGlobal("a")
|
||||
|
||||
value, err = envChild.Get("a")
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, expectedError)
|
||||
}
|
||||
if value != nil {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, nil)
|
||||
}
|
||||
|
||||
// parent & child, var in parent, delete in parent
|
||||
env.Define("a", "a")
|
||||
env.DeleteGlobal("a")
|
||||
|
||||
value, err = envChild.Get("a")
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Errorf("Get error - received: %v - expected: %v", err, expectedError)
|
||||
}
|
||||
if value != nil {
|
||||
t.Errorf("Get value - received: %#v - expected: %#v", value, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaceCreateSameVariable(t *testing.T) {
|
||||
// Test creating same variable in parallel
|
||||
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
env := NewEnv()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func(i int) {
|
||||
<-waitChan
|
||||
err := env.Define("a", i)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}(i)
|
||||
}
|
||||
|
||||
close(waitChan)
|
||||
waitGroup.Wait()
|
||||
|
||||
_, err := env.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaceCreateDifferentVariables(t *testing.T) {
|
||||
// Test creating different variables in parallel
|
||||
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
env := NewEnv()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func(i int) {
|
||||
<-waitChan
|
||||
err := env.Define(fmt.Sprint(i), i)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
_, err = env.Get(fmt.Sprint(i))
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}(i)
|
||||
}
|
||||
|
||||
close(waitChan)
|
||||
waitGroup.Wait()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
_, err := env.Get(fmt.Sprint(i))
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaceReadDifferentVariables(t *testing.T) {
|
||||
// Test reading different variables in parallel
|
||||
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
env := NewEnv()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
err := env.Define(fmt.Sprint(i), i)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
_, err = env.Get(fmt.Sprint(i))
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func(i int) {
|
||||
<-waitChan
|
||||
_, err := env.Get(fmt.Sprint(i))
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}(i)
|
||||
}
|
||||
|
||||
close(waitChan)
|
||||
waitGroup.Wait()
|
||||
}
|
||||
|
||||
func TestRaceSetSameVariable(t *testing.T) {
|
||||
// Test setting same variable in parallel
|
||||
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
env := NewEnv()
|
||||
|
||||
err := env.Define("a", 0)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func(i int) {
|
||||
<-waitChan
|
||||
err := env.Set("a", i)
|
||||
if err != nil {
|
||||
t.Errorf("Set error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}(i)
|
||||
}
|
||||
|
||||
close(waitChan)
|
||||
waitGroup.Wait()
|
||||
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaceSetSameVariableNewEnv(t *testing.T) {
|
||||
// Test setting same variable in parallel with NewEnv
|
||||
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
env := NewEnv()
|
||||
|
||||
err := env.Define("a", 0)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func(i int) {
|
||||
<-waitChan
|
||||
env = env.NewEnv().NewEnv()
|
||||
err := env.Set("a", i)
|
||||
if err != nil {
|
||||
t.Errorf("Set error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}(i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaceDefineAndSetSameVariable(t *testing.T) {
|
||||
// Test defining and setting same variable in parallel
|
||||
for i := 0; i < 100; i++ {
|
||||
raceDefineAndSetSameVariable(t)
|
||||
}
|
||||
}
|
||||
|
||||
func raceDefineAndSetSameVariable(t *testing.T) {
|
||||
waitChan := make(chan struct{}, 1)
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
envParent := NewEnv()
|
||||
envChild := envParent.NewEnv()
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
waitGroup.Add(1)
|
||||
go func() {
|
||||
<-waitChan
|
||||
err := envParent.Set("a", 1)
|
||||
if err != nil && err.Error() != "undefined symbol 'a'" {
|
||||
t.Errorf("Set error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}()
|
||||
waitGroup.Add(1)
|
||||
go func() {
|
||||
<-waitChan
|
||||
err := envParent.Define("a", 2)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}()
|
||||
waitGroup.Add(1)
|
||||
go func() {
|
||||
<-waitChan
|
||||
err := envChild.Set("a", 3)
|
||||
if err != nil && err.Error() != "undefined symbol 'a'" {
|
||||
t.Errorf("Set error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}()
|
||||
waitGroup.Add(1)
|
||||
go func() {
|
||||
<-waitChan
|
||||
err := envChild.Define("a", 4)
|
||||
if err != nil {
|
||||
t.Errorf("Define error: %v", err)
|
||||
}
|
||||
waitGroup.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
close(waitChan)
|
||||
waitGroup.Wait()
|
||||
|
||||
_, err := envParent.Get("a") // value of a could be 1, 2, or 3
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
_, err = envChild.Get("a") // value of a could be 3 or 4
|
||||
if err != nil {
|
||||
t.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDefine(b *testing.B) {
|
||||
var err error
|
||||
env := NewEnv()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := env.Define("a", 1)
|
||||
if err != nil {
|
||||
b.Errorf("Set error: %v", err)
|
||||
}
|
||||
}
|
||||
b.StopTimer()
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
b.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSet(b *testing.B) {
|
||||
env := NewEnv()
|
||||
err := env.Define("a", 1)
|
||||
if err != nil {
|
||||
b.Errorf("Define error: %v", err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err = env.Set("a", 1)
|
||||
if err != nil {
|
||||
b.Errorf("Set error: %v", err)
|
||||
}
|
||||
}
|
||||
b.StopTimer()
|
||||
_, err = env.Get("a")
|
||||
if err != nil {
|
||||
b.Errorf("Get error: %v", err)
|
||||
}
|
||||
}
|
394
src/tool/run/env/env_test.go
vendored
Normal file
394
src/tool/run/env/env_test.go
vendored
Normal file
|
@ -0,0 +1,394 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := NewEnv()
|
||||
env.Define("a", "a")
|
||||
output := env.String()
|
||||
expected := `No parent
|
||||
a = "a"
|
||||
`
|
||||
if output != expected {
|
||||
t.Errorf("received: %v - expected: %v", output, expected)
|
||||
}
|
||||
|
||||
env = env.NewEnv()
|
||||
env.Define("b", "b")
|
||||
output = env.String()
|
||||
expected = `Has parent
|
||||
b = "b"
|
||||
`
|
||||
if output != expected {
|
||||
t.Errorf("received: %v - expected: %v", output, expected)
|
||||
}
|
||||
|
||||
env = NewEnv()
|
||||
env.Define("c", "c")
|
||||
env.DefineType("string", "a")
|
||||
output = env.String()
|
||||
expected = `No parent
|
||||
c = "c"
|
||||
string = string
|
||||
`
|
||||
if output != expected {
|
||||
t.Errorf("received: %v - expected: %v", output, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEnvFromPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := NewEnv()
|
||||
a, err := env.NewModule("a")
|
||||
if err != nil {
|
||||
t.Fatal("NewModule error:", err)
|
||||
}
|
||||
var b *Env
|
||||
b, err = a.NewModule("b")
|
||||
if err != nil {
|
||||
t.Fatal("NewModule error:", err)
|
||||
}
|
||||
var c *Env
|
||||
c, err = b.NewModule("c")
|
||||
if err != nil {
|
||||
t.Fatal("NewModule error:", err)
|
||||
}
|
||||
err = c.Define("d", "d")
|
||||
if err != nil {
|
||||
t.Fatal("Define error:", err)
|
||||
}
|
||||
|
||||
e, err := env.GetEnvFromPath(nil)
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
|
||||
e, err = env.GetEnvFromPath([]string{})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
|
||||
e, err = env.GetEnvFromPath([]string{"a", "c"})
|
||||
expected := "no namespace called: c"
|
||||
if err == nil || err.Error() != expected {
|
||||
t.Fatalf("GetEnvFromPath error - received: %v - expected: %v", err, expected)
|
||||
}
|
||||
if e != nil {
|
||||
t.Fatal("GetEnvFromPath e not nil")
|
||||
}
|
||||
|
||||
// a.b.c
|
||||
|
||||
e, err = env.GetEnvFromPath([]string{"a", "b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
var value interface{}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = a.GetEnvFromPath([]string{"a", "b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = b.GetEnvFromPath([]string{"a", "b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = c.GetEnvFromPath([]string{"a", "b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
// b.c
|
||||
|
||||
e, err = env.GetEnvFromPath([]string{"b", "c"})
|
||||
expected = "no namespace called: b"
|
||||
if err == nil || err.Error() != expected {
|
||||
t.Fatalf("GetEnvFromPath error - received: %v - expected: %v", err, expected)
|
||||
}
|
||||
if e != nil {
|
||||
t.Fatal("GetEnvFromPath e not nil")
|
||||
}
|
||||
|
||||
e, err = a.GetEnvFromPath([]string{"b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = b.GetEnvFromPath([]string{"b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = c.GetEnvFromPath([]string{"b", "c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
// c
|
||||
|
||||
e, err = env.GetEnvFromPath([]string{"c"})
|
||||
expected = "no namespace called: c"
|
||||
if err == nil || err.Error() != expected {
|
||||
t.Fatalf("GetEnvFromPath error - received: %v - expected: %v", err, expected)
|
||||
}
|
||||
if e != nil {
|
||||
t.Fatal("GetEnvFromPath e not nil")
|
||||
}
|
||||
|
||||
e, err = b.GetEnvFromPath([]string{"c"})
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
|
||||
e, err = c.GetEnvFromPath(nil)
|
||||
if err != nil {
|
||||
t.Fatal("GetEnvFromPath error:", err)
|
||||
}
|
||||
if e == nil {
|
||||
t.Fatal("GetEnvFromPath e nil")
|
||||
}
|
||||
value, err = e.Get("d")
|
||||
if err != nil {
|
||||
t.Fatal("Get error:", err)
|
||||
}
|
||||
v, ok = value.(string)
|
||||
if !ok {
|
||||
t.Fatal("value not string")
|
||||
}
|
||||
if v != "d" {
|
||||
t.Errorf("value - received: %v - expected: %v", v, "d")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
parent := NewEnv()
|
||||
parent.Define("a", "a")
|
||||
parent.DefineType("b", []bool{})
|
||||
child := parent.NewEnv()
|
||||
child.Define("c", "c")
|
||||
child.DefineType("d", []int64{})
|
||||
copy := child.Copy()
|
||||
|
||||
if v, e := copy.Get("a"); e != nil || v != "a" {
|
||||
t.Errorf("copy missing value")
|
||||
}
|
||||
if v, e := copy.Type("b"); e != nil || v != reflect.TypeOf([]bool{}) {
|
||||
t.Errorf("copy missing type")
|
||||
}
|
||||
if v, e := copy.Get("c"); e != nil || v != "c" {
|
||||
t.Errorf("copy missing value")
|
||||
}
|
||||
if v, e := copy.Type("d"); e != nil || v != reflect.TypeOf([]int64{}) {
|
||||
t.Errorf("copy missing type")
|
||||
}
|
||||
|
||||
// TODO: add more get type tests
|
||||
|
||||
copy.Set("a", "i")
|
||||
if v, e := child.Get("a"); e != nil || v != "i" {
|
||||
t.Errorf("parent was not modified")
|
||||
}
|
||||
if v, e := copy.Get("a"); e != nil || v != "i" {
|
||||
t.Errorf("copy did not get parent value")
|
||||
}
|
||||
|
||||
copy.Set("c", "j")
|
||||
if v, e := child.Get("c"); e != nil || v != "c" {
|
||||
t.Errorf("child was not modified")
|
||||
}
|
||||
if v, e := copy.Get("c"); e != nil || v != "j" {
|
||||
t.Errorf("copy child was not modified")
|
||||
}
|
||||
|
||||
child.Set("a", "x")
|
||||
if v, e := child.Get("a"); e != nil || v != "x" {
|
||||
t.Errorf("parent was not modified")
|
||||
}
|
||||
if v, e := copy.Get("a"); e != nil || v != "x" {
|
||||
t.Errorf("copy did not get parent value")
|
||||
}
|
||||
|
||||
child.Set("c", "z")
|
||||
if v, e := child.Get("c"); e != nil || v != "z" {
|
||||
t.Errorf("child was not modified")
|
||||
}
|
||||
if v, e := copy.Get("c"); e != nil || v != "j" {
|
||||
t.Errorf("copy child was modified")
|
||||
}
|
||||
|
||||
parent.Set("a", "m")
|
||||
if v, e := child.Get("a"); e != nil || v != "m" {
|
||||
t.Errorf("parent was not modified")
|
||||
}
|
||||
if v, e := copy.Get("a"); e != nil || v != "m" {
|
||||
t.Errorf("copy did not get parent value")
|
||||
}
|
||||
|
||||
parent.Define("x", "n")
|
||||
if v, e := child.Get("x"); e != nil || v != "n" {
|
||||
t.Errorf("child did not get parent value")
|
||||
}
|
||||
if v, e := copy.Get("x"); e != nil || v != "n" {
|
||||
t.Errorf("copy did not get parent value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeepCopy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
parent := NewEnv()
|
||||
parent.Define("a", "a")
|
||||
env := parent.NewEnv()
|
||||
copy := env.DeepCopy()
|
||||
|
||||
// TODO: add more/better tests, like above
|
||||
if v, e := copy.Get("a"); e != nil || v != "a" {
|
||||
t.Errorf("copy doesn't retain original values")
|
||||
}
|
||||
parent.Set("a", "b")
|
||||
if v, e := env.Get("a"); e != nil || v != "b" {
|
||||
t.Errorf("son was not modified")
|
||||
}
|
||||
if v, e := copy.Get("a"); e != nil || v != "a" {
|
||||
t.Errorf("copy got the new value")
|
||||
}
|
||||
parent.Set("a", "c")
|
||||
if v, e := env.Get("a"); e != nil || v != "c" {
|
||||
t.Errorf("original was not modified")
|
||||
}
|
||||
if v, e := copy.Get("a"); e != nil || v != "a" {
|
||||
t.Errorf("copy was modified")
|
||||
}
|
||||
parent.Define("b", "b")
|
||||
if _, e := copy.Get("b"); e == nil {
|
||||
t.Errorf("copy parent was modified")
|
||||
}
|
||||
}
|
1
src/tool/run/misc/vim/ftdetect/ank.vim
Normal file
1
src/tool/run/misc/vim/ftdetect/ank.vim
Normal file
|
@ -0,0 +1 @@
|
|||
au BufNewFile,BufRead *.ank setlocal filetype=anko
|
11
src/tool/run/misc/vim/ftplugin/anko/comment.vim
Normal file
11
src/tool/run/misc/vim/ftplugin/anko/comment.vim
Normal file
|
@ -0,0 +1,11 @@
|
|||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
setlocal comments=s1:#
|
||||
setlocal commentstring=#\ %s
|
||||
|
||||
let b:undo_ftplugin = "setl com< cms<"
|
||||
|
||||
" vim:ts=4:sw=4:et
|
15
src/tool/run/misc/vim/ftplugin/anko/play.vim
Normal file
15
src/tool/run/misc/vim/ftplugin/anko/play.vim
Normal file
|
@ -0,0 +1,15 @@
|
|||
scriptencoding utf-8
|
||||
|
||||
function! s:play()
|
||||
let code = join(getline(1, '$'), "\n")
|
||||
let res = webapi#http#post("http://play-anko.appspot.com/api/play", {"code": code})
|
||||
if res.status == "200"
|
||||
echo iconv(res.content, "utf-8", &encoding)
|
||||
else
|
||||
for line in split(res.content, "\n")
|
||||
echohl Error | echomsg iconv(line, "utf-8", &encoding) | echohl None
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
command! -buffer PlayAnko call s:play()
|
100
src/tool/run/misc/vim/syntax/anko.vim
Normal file
100
src/tool/run/misc/vim/syntax/anko.vim
Normal file
|
@ -0,0 +1,100 @@
|
|||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn case match
|
||||
|
||||
syn keyword ankoDirective module
|
||||
syn keyword ankoDeclaration var
|
||||
|
||||
hi def link ankoDirective Statement
|
||||
hi def link ankoDeclaration Type
|
||||
|
||||
syn keyword ankoStatement return break continue throw
|
||||
syn keyword ankoConditional if else switch try catch finally
|
||||
syn keyword ankoLabel case default
|
||||
syn keyword ankoRepeat for range
|
||||
|
||||
hi def link ankoStatement Statement
|
||||
hi def link ankoConditional Conditional
|
||||
hi def link ankoLabel Label
|
||||
hi def link ankoRepeat Repeat
|
||||
|
||||
syn match ankoDeclaration /\<func\>/
|
||||
syn match ankoDeclaration /^func\>/
|
||||
|
||||
syn keyword ankoCast bytes runes string
|
||||
|
||||
hi def link ankoCast Type
|
||||
|
||||
syn keyword ankoBuiltins keys len
|
||||
syn keyword ankoBuiltins println printf print
|
||||
syn keyword ankoConstants true false nil
|
||||
|
||||
hi def link ankoBuiltins Keyword
|
||||
hi def link ankoConstants Keyword
|
||||
|
||||
" Comments; their contents
|
||||
syn keyword ankoTodo contained TODO FIXME XXX BUG
|
||||
syn cluster ankoCommentGroup contains=ankoTodo
|
||||
syn region ankoComment start="#" end="$" contains=@ankoCommentGroup,@Spell
|
||||
|
||||
hi def link ankoComment Comment
|
||||
hi def link ankoTodo Todo
|
||||
|
||||
" anko escapes
|
||||
syn match ankoEscapeOctal display contained "\\[0-7]\{3}"
|
||||
syn match ankoEscapeC display contained +\\[abfnrtv\\'"]+
|
||||
syn match ankoEscapeX display contained "\\x\x\{2}"
|
||||
syn match ankoEscapeU display contained "\\u\x\{4}"
|
||||
syn match ankoEscapeBigU display contained "\\U\x\{8}"
|
||||
syn match ankoEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+
|
||||
|
||||
hi def link ankoEscapeOctal ankoSpecialString
|
||||
hi def link ankoEscapeC ankoSpecialString
|
||||
hi def link ankoEscapeX ankoSpecialString
|
||||
hi def link ankoEscapeU ankoSpecialString
|
||||
hi def link ankoEscapeBigU ankoSpecialString
|
||||
hi def link ankoSpecialString Special
|
||||
hi def link ankoEscapeError Error
|
||||
|
||||
" Strings and their contents
|
||||
syn cluster ankoStringGroup contains=ankoEscapeOctal,ankoEscapeC,ankoEscapeX,ankoEscapeU,ankoEscapeBigU,ankoEscapeError
|
||||
syn region ankoString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@ankoStringGroup
|
||||
syn region ankoRawString start=+`+ end=+`+
|
||||
|
||||
hi def link ankoString String
|
||||
hi def link ankoRawString String
|
||||
|
||||
" Characters; their contents
|
||||
syn cluster ankoCharacterGroup contains=ankoEscapeOctal,ankoEscapeC,ankoEscapeX,ankoEscapeU,ankoEscapeBigU
|
||||
syn region ankoCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@ankoCharacterGroup
|
||||
|
||||
hi def link ankoCharacter Character
|
||||
|
||||
" Regions
|
||||
syn region ankoBlock start="{" end="}" transparent fold
|
||||
syn region ankoParen start='(' end=')' transparent
|
||||
|
||||
" Integers
|
||||
syn match ankoDecimalInt "\<\d\+\([Ee]\d\+\)\?\>"
|
||||
syn match ankoHexadecimalInt "\<0x\x\+\>"
|
||||
syn match ankoOctalInt "\<0\o\+\>"
|
||||
syn match ankoOctalError "\<0\o*[89]\d*\>"
|
||||
|
||||
hi def link ankoDecimalInt Integer
|
||||
hi def link ankoHexadecimalInt Integer
|
||||
hi def link ankoOctalInt Integer
|
||||
hi def link Integer Number
|
||||
|
||||
" Floating point
|
||||
syn match ankoFloat "\<\d\+\.\d*\([Ee][-+]\d\+\)\?\>"
|
||||
syn match ankoFloat "\<\.\d\+\([Ee][-+]\d\+\)\?\>"
|
||||
syn match ankoFloat "\<\d\+[Ee][-+]\d\+\>"
|
||||
|
||||
hi def link ankoFloat Float
|
||||
hi def link ankoImaginary Number
|
||||
|
||||
syn sync minlines=500
|
||||
|
||||
let b:current_syntax = "anko"
|
129
src/tool/run/misc/wasm/anko.go
Normal file
129
src/tool/run/misc/wasm/anko.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
// +build js,wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"strings"
|
||||
"syscall/js"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/core"
|
||||
"github.com/surdeus/goblin/src/tool/run/packages"
|
||||
"github.com/surdeus/goblin/src/tool/run/parser"
|
||||
"github.com/surdeus/goblin/src/tool/run/vm"
|
||||
)
|
||||
|
||||
var (
|
||||
result = js.Global.Get("document").Call("getElementById", "result")
|
||||
input = js.Global.Get("document").Call("getElementById", "input")
|
||||
)
|
||||
|
||||
func writeCommand(s string) {
|
||||
result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='command'>"+html.EscapeString(s)+"</p>")
|
||||
result.Set("scrollTop", result.Get("scrollHeight").Int())
|
||||
}
|
||||
|
||||
func writeStdout(s string) {
|
||||
result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='stdout'>"+html.EscapeString(s)+"</p>")
|
||||
result.Set("scrollTop", result.Get("scrollHeight").Int())
|
||||
}
|
||||
|
||||
func writeStderr(s string) {
|
||||
result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='stderr'>"+html.EscapeString(s)+"</p>")
|
||||
result.Set("scrollTop", result.Get("scrollHeight").Int())
|
||||
}
|
||||
|
||||
func main() {
|
||||
env := vm.NewEnv()
|
||||
core.Import(env)
|
||||
packages.DefineImport(env)
|
||||
|
||||
env.Define("print", func(a ...interface{}) {
|
||||
writeStdout(fmt.Sprint(a...))
|
||||
})
|
||||
env.Define("printf", func(a string, b ...interface{}) {
|
||||
writeStdout(fmt.Sprintf(a, b...))
|
||||
})
|
||||
|
||||
var following bool
|
||||
var source string
|
||||
|
||||
parser.EnableErrorVerbose()
|
||||
|
||||
ch := make(chan string)
|
||||
|
||||
input.Call("addEventListener", "keypress", js.NewCallback(func(args []js.Value) {
|
||||
e := args[0]
|
||||
if e.Get("keyCode").Int() != 13 {
|
||||
return
|
||||
}
|
||||
s := e.Get("target").Get("value").String()
|
||||
e.Get("target").Set("value", "")
|
||||
writeCommand(s)
|
||||
ch <- s
|
||||
}))
|
||||
input.Set("disabled", false)
|
||||
result.Set("innerHTML", "")
|
||||
|
||||
go func() {
|
||||
for {
|
||||
text, ok := <-ch
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
source += text
|
||||
if source == "" {
|
||||
continue
|
||||
}
|
||||
if source == "quit()" {
|
||||
break
|
||||
}
|
||||
|
||||
stmts, err := parser.ParseSrc(source)
|
||||
|
||||
if e, ok := err.(*parser.Error); ok {
|
||||
es := e.Error()
|
||||
if strings.HasPrefix(es, "syntax error: unexpected") {
|
||||
if strings.HasPrefix(es, "syntax error: unexpected $end,") {
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if e.Pos.Column == len(source) && !e.Fatal {
|
||||
writeStderr(e.Error())
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
if e.Error() == "unexpected EOF" {
|
||||
following = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
following = false
|
||||
source = ""
|
||||
var v interface{}
|
||||
|
||||
if err == nil {
|
||||
v, err = vm.Run(stmts, env)
|
||||
}
|
||||
if err != nil {
|
||||
if e, ok := err.(*vm.Error); ok {
|
||||
writeStderr(fmt.Sprintf("%d:%d %s\n", e.Pos.Line, e.Pos.Column, err))
|
||||
} else if e, ok := err.(*parser.Error); ok {
|
||||
writeStderr(fmt.Sprintf("%d:%d %s\n", e.Pos.Line, e.Pos.Column, err))
|
||||
} else {
|
||||
writeStderr(err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
writeStdout(fmt.Sprintf("%#v\n", v))
|
||||
}
|
||||
}()
|
||||
|
||||
select {}
|
||||
|
||||
}
|
35
src/tool/run/misc/wasm/index.html
Normal file
35
src/tool/run/misc/wasm/index.html
Normal file
|
@ -0,0 +1,35 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Anko WebAssembly</title>
|
||||
<script src="wasm_exec.js"></script>
|
||||
<script type="text/javascript">
|
||||
function fetchAndInstantiate(url, importObject) {
|
||||
return fetch(url).then(response =>
|
||||
response.arrayBuffer()
|
||||
).then(bytes =>
|
||||
WebAssembly.instantiate(bytes, importObject)
|
||||
).then(results =>
|
||||
results.instance
|
||||
);
|
||||
}
|
||||
var go = new Go();
|
||||
var mod = fetchAndInstantiate("/anko.wasm", go.importObject);
|
||||
window.onload = function() {
|
||||
mod.then(function(instance) {
|
||||
go.run(instance);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
#result { width: 100%; height: 300px; overflow-y: scroll; }
|
||||
#input { width: 100%; }
|
||||
.stdout { margin: 0px; }
|
||||
.command { margin: 0px; color: gray; }
|
||||
.stderr { margin: 0px; color: red; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="result">loading...</div>
|
||||
<input id="input" type="text" value="" disabled=true /><br />
|
||||
</body>
|
||||
</html>
|
381
src/tool/run/misc/wasm/wasm_exec.js
Normal file
381
src/tool/run/misc/wasm/wasm_exec.js
Normal file
|
@ -0,0 +1,381 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
(() => {
|
||||
// Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
|
||||
const isNodeJS = typeof process !== "undefined";
|
||||
if (isNodeJS) {
|
||||
global.require = require;
|
||||
global.fs = require("fs");
|
||||
|
||||
const nodeCrypto = require("crypto");
|
||||
global.crypto = {
|
||||
getRandomValues(b) {
|
||||
nodeCrypto.randomFillSync(b);
|
||||
},
|
||||
};
|
||||
|
||||
global.performance = {
|
||||
now() {
|
||||
const [sec, nsec] = process.hrtime();
|
||||
return sec * 1000 + nsec / 1000000;
|
||||
},
|
||||
};
|
||||
|
||||
const util = require("util");
|
||||
global.TextEncoder = util.TextEncoder;
|
||||
global.TextDecoder = util.TextDecoder;
|
||||
} else {
|
||||
window.global = window;
|
||||
|
||||
let outputBuf = "";
|
||||
global.fs = {
|
||||
constants: {},
|
||||
writeSync(fd, buf) {
|
||||
outputBuf += decoder.decode(buf);
|
||||
const nl = outputBuf.lastIndexOf("\n");
|
||||
if (nl != -1) {
|
||||
console.log(outputBuf.substr(0, nl));
|
||||
outputBuf = outputBuf.substr(nl + 1);
|
||||
}
|
||||
return buf.length;
|
||||
},
|
||||
openSync(path, flags, mode) {
|
||||
const err = new Error("not implemented");
|
||||
err.code = "ENOSYS";
|
||||
throw err;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder("utf-8");
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
|
||||
global.Go = class {
|
||||
constructor() {
|
||||
this.argv = ["js"];
|
||||
this.env = {};
|
||||
this.exit = (code) => {
|
||||
if (code !== 0) {
|
||||
console.warn("exit code:", code);
|
||||
}
|
||||
};
|
||||
this._callbackTimeouts = new Map();
|
||||
this._nextCallbackTimeoutID = 1;
|
||||
|
||||
const mem = () => {
|
||||
// The buffer may change when requesting more memory.
|
||||
return new DataView(this._inst.exports.mem.buffer);
|
||||
}
|
||||
|
||||
const setInt64 = (addr, v) => {
|
||||
mem().setUint32(addr + 0, v, true);
|
||||
mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
|
||||
}
|
||||
|
||||
const getInt64 = (addr) => {
|
||||
const low = mem().getUint32(addr + 0, true);
|
||||
const high = mem().getInt32(addr + 4, true);
|
||||
return low + high * 4294967296;
|
||||
}
|
||||
|
||||
const loadValue = (addr) => {
|
||||
const id = mem().getUint32(addr, true);
|
||||
return this._values[id];
|
||||
}
|
||||
|
||||
const storeValue = (addr, v) => {
|
||||
if (v === undefined) {
|
||||
mem().setUint32(addr, 0, true);
|
||||
return;
|
||||
}
|
||||
if (v === null) {
|
||||
mem().setUint32(addr, 1, true);
|
||||
return;
|
||||
}
|
||||
this._values.push(v);
|
||||
mem().setUint32(addr, this._values.length - 1, true);
|
||||
}
|
||||
|
||||
const loadSlice = (addr) => {
|
||||
const array = getInt64(addr + 0);
|
||||
const len = getInt64(addr + 8);
|
||||
return new Uint8Array(this._inst.exports.mem.buffer, array, len);
|
||||
}
|
||||
|
||||
const loadSliceOfValues = (addr) => {
|
||||
const array = getInt64(addr + 0);
|
||||
const len = getInt64(addr + 8);
|
||||
const a = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const id = mem().getUint32(array + i * 4, true);
|
||||
a[i] = this._values[id];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
const loadString = (addr) => {
|
||||
const saddr = getInt64(addr + 0);
|
||||
const len = getInt64(addr + 8);
|
||||
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
|
||||
}
|
||||
|
||||
const timeOrigin = Date.now() - performance.now();
|
||||
this.importObject = {
|
||||
go: {
|
||||
// func wasmExit(code int32)
|
||||
"runtime.wasmExit": (sp) => {
|
||||
this.exited = true;
|
||||
this.exit(mem().getInt32(sp + 8, true));
|
||||
},
|
||||
|
||||
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
||||
"runtime.wasmWrite": (sp) => {
|
||||
const fd = getInt64(sp + 8);
|
||||
const p = getInt64(sp + 16);
|
||||
const n = mem().getInt32(sp + 24, true);
|
||||
fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
|
||||
},
|
||||
|
||||
// func nanotime() int64
|
||||
"runtime.nanotime": (sp) => {
|
||||
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
||||
},
|
||||
|
||||
// func walltime() (sec int64, nsec int32)
|
||||
"runtime.walltime": (sp) => {
|
||||
const msec = (new Date).getTime();
|
||||
setInt64(sp + 8, msec / 1000);
|
||||
mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
||||
},
|
||||
|
||||
// func scheduleCallback(delay int64) int32
|
||||
"runtime.scheduleCallback": (sp) => {
|
||||
const id = this._nextCallbackTimeoutID;
|
||||
this._nextCallbackTimeoutID++;
|
||||
this._callbackTimeouts.set(id, setTimeout(
|
||||
() => { this._resolveCallbackPromise(); },
|
||||
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
||||
));
|
||||
mem().setInt32(sp + 16, id, true);
|
||||
},
|
||||
|
||||
// func clearScheduledCallback(id int32)
|
||||
"runtime.clearScheduledCallback": (sp) => {
|
||||
const id = mem().getInt32(sp + 8, true);
|
||||
clearTimeout(this._callbackTimeouts.get(id));
|
||||
this._callbackTimeouts.delete(id);
|
||||
},
|
||||
|
||||
// func getRandomData(r []byte)
|
||||
"runtime.getRandomData": (sp) => {
|
||||
crypto.getRandomValues(loadSlice(sp + 8));
|
||||
},
|
||||
|
||||
// func boolVal(value bool) ref
|
||||
"syscall/js.boolVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getUint8(sp + 8) !== 0);
|
||||
},
|
||||
|
||||
// func intVal(value int) ref
|
||||
"syscall/js.intVal": (sp) => {
|
||||
storeValue(sp + 16, getInt64(sp + 8));
|
||||
},
|
||||
|
||||
// func floatVal(value float64) ref
|
||||
"syscall/js.floatVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getFloat64(sp + 8, true));
|
||||
},
|
||||
|
||||
// func stringVal(value string) ref
|
||||
"syscall/js.stringVal": (sp) => {
|
||||
storeValue(sp + 24, loadString(sp + 8));
|
||||
},
|
||||
|
||||
// func valueGet(v ref, p string) ref
|
||||
"syscall/js.valueGet": (sp) => {
|
||||
storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16)));
|
||||
},
|
||||
|
||||
// func valueSet(v ref, p string, x ref)
|
||||
"syscall/js.valueSet": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
||||
},
|
||||
|
||||
// func valueIndex(v ref, i int) ref
|
||||
"syscall/js.valueIndex": (sp) => {
|
||||
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
||||
},
|
||||
|
||||
// valueSetIndex(v ref, i int, x ref)
|
||||
"syscall/js.valueSetIndex": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
||||
},
|
||||
|
||||
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||
"syscall/js.valueCall": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const m = Reflect.get(v, loadString(sp + 16));
|
||||
const args = loadSliceOfValues(sp + 32);
|
||||
storeValue(sp + 56, Reflect.apply(m, v, args));
|
||||
mem().setUint8(sp + 60, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 56, err);
|
||||
mem().setUint8(sp + 60, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func valueInvoke(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueInvoke": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
storeValue(sp + 40, Reflect.apply(v, undefined, args));
|
||||
mem().setUint8(sp + 44, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
mem().setUint8(sp + 44, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func valueNew(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueNew": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
storeValue(sp + 40, Reflect.construct(v, args));
|
||||
mem().setUint8(sp + 44, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
mem().setUint8(sp + 44, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func valueFloat(v ref) float64
|
||||
"syscall/js.valueFloat": (sp) => {
|
||||
mem().setFloat64(sp + 16, parseFloat(loadValue(sp + 8)), true);
|
||||
},
|
||||
|
||||
// func valueInt(v ref) int
|
||||
"syscall/js.valueInt": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8)));
|
||||
},
|
||||
|
||||
// func valueBool(v ref) bool
|
||||
"syscall/js.valueBool": (sp) => {
|
||||
mem().setUint8(sp + 16, !!loadValue(sp + 8));
|
||||
},
|
||||
|
||||
// func valueLength(v ref) int
|
||||
"syscall/js.valueLength": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
||||
},
|
||||
|
||||
// valuePrepareString(v ref) (ref, int)
|
||||
"syscall/js.valuePrepareString": (sp) => {
|
||||
const str = encoder.encode(String(loadValue(sp + 8)));
|
||||
storeValue(sp + 16, str);
|
||||
setInt64(sp + 24, str.length);
|
||||
},
|
||||
|
||||
// valueLoadString(v ref, b []byte)
|
||||
"syscall/js.valueLoadString": (sp) => {
|
||||
const str = loadValue(sp + 8);
|
||||
loadSlice(sp + 16).set(str);
|
||||
},
|
||||
|
||||
"debug": (value) => {
|
||||
console.log(value);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async run(instance) {
|
||||
this._inst = instance;
|
||||
this._values = [ // TODO: garbage collection
|
||||
undefined,
|
||||
null,
|
||||
global,
|
||||
this._inst.exports.mem,
|
||||
() => { // resolveCallbackPromise
|
||||
if (this.exited) {
|
||||
throw new Error("bad callback: Go program has already exited");
|
||||
}
|
||||
setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
|
||||
},
|
||||
];
|
||||
this.exited = false;
|
||||
|
||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||
|
||||
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
|
||||
let offset = 4096;
|
||||
|
||||
const strPtr = (str) => {
|
||||
let ptr = offset;
|
||||
new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0"));
|
||||
offset += str.length + (8 - (str.length % 8));
|
||||
return ptr;
|
||||
};
|
||||
|
||||
const argc = this.argv.length;
|
||||
|
||||
const argvPtrs = [];
|
||||
this.argv.forEach((arg) => {
|
||||
argvPtrs.push(strPtr(arg));
|
||||
});
|
||||
|
||||
const keys = Object.keys(this.env).sort();
|
||||
argvPtrs.push(keys.length);
|
||||
keys.forEach((key) => {
|
||||
argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
|
||||
});
|
||||
|
||||
const argv = offset;
|
||||
argvPtrs.forEach((ptr) => {
|
||||
mem.setUint32(offset, ptr, true);
|
||||
mem.setUint32(offset + 4, 0, true);
|
||||
offset += 8;
|
||||
});
|
||||
|
||||
while (true) {
|
||||
const callbackPromise = new Promise((resolve) => {
|
||||
this._resolveCallbackPromise = resolve;
|
||||
});
|
||||
this._inst.exports.run(argc, argv);
|
||||
if (this.exited) {
|
||||
break;
|
||||
}
|
||||
await callbackPromise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNodeJS) {
|
||||
if (process.argv.length < 3) {
|
||||
process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const go = new Go();
|
||||
go.argv = process.argv.slice(2);
|
||||
go.env = process.env;
|
||||
go.exit = process.exit;
|
||||
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||
process.on("exit", () => { // Node.js exits if no callback is pending
|
||||
if (!go.exited) {
|
||||
console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!");
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
return go.run(result.instance);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
go.exited = true;
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
})();
|
64
src/tool/run/packages/bytes.go
Normal file
64
src/tool/run/packages/bytes.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["bytes"] = map[string]reflect.Value{
|
||||
"Compare": reflect.ValueOf(bytes.Compare),
|
||||
"Contains": reflect.ValueOf(bytes.Contains),
|
||||
"Count": reflect.ValueOf(bytes.Count),
|
||||
"Equal": reflect.ValueOf(bytes.Equal),
|
||||
"EqualFold": reflect.ValueOf(bytes.EqualFold),
|
||||
"Fields": reflect.ValueOf(bytes.Fields),
|
||||
"FieldsFunc": reflect.ValueOf(bytes.FieldsFunc),
|
||||
"HasPrefix": reflect.ValueOf(bytes.HasPrefix),
|
||||
"HasSuffix": reflect.ValueOf(bytes.HasSuffix),
|
||||
"Index": reflect.ValueOf(bytes.Index),
|
||||
"IndexAny": reflect.ValueOf(bytes.IndexAny),
|
||||
"IndexByte": reflect.ValueOf(bytes.IndexByte),
|
||||
"IndexFunc": reflect.ValueOf(bytes.IndexFunc),
|
||||
"IndexRune": reflect.ValueOf(bytes.IndexRune),
|
||||
"Join": reflect.ValueOf(bytes.Join),
|
||||
"LastIndex": reflect.ValueOf(bytes.LastIndex),
|
||||
"LastIndexAny": reflect.ValueOf(bytes.LastIndexAny),
|
||||
"LastIndexByte": reflect.ValueOf(bytes.LastIndexByte),
|
||||
"LastIndexFunc": reflect.ValueOf(bytes.LastIndexFunc),
|
||||
"Map": reflect.ValueOf(bytes.Map),
|
||||
"NewBuffer": reflect.ValueOf(bytes.NewBuffer),
|
||||
"NewBufferString": reflect.ValueOf(bytes.NewBufferString),
|
||||
"NewReader": reflect.ValueOf(bytes.NewReader),
|
||||
"Repeat": reflect.ValueOf(bytes.Repeat),
|
||||
"Replace": reflect.ValueOf(bytes.Replace),
|
||||
"Runes": reflect.ValueOf(bytes.Runes),
|
||||
"Split": reflect.ValueOf(bytes.Split),
|
||||
"SplitAfter": reflect.ValueOf(bytes.SplitAfter),
|
||||
"SplitAfterN": reflect.ValueOf(bytes.SplitAfterN),
|
||||
"SplitN": reflect.ValueOf(bytes.SplitN),
|
||||
"Title": reflect.ValueOf(bytes.Title),
|
||||
"ToLower": reflect.ValueOf(bytes.ToLower),
|
||||
"ToLowerSpecial": reflect.ValueOf(bytes.ToLowerSpecial),
|
||||
"ToTitle": reflect.ValueOf(bytes.ToTitle),
|
||||
"ToTitleSpecial": reflect.ValueOf(bytes.ToTitleSpecial),
|
||||
"ToUpper": reflect.ValueOf(bytes.ToUpper),
|
||||
"ToUpperSpecial": reflect.ValueOf(bytes.ToUpperSpecial),
|
||||
"Trim": reflect.ValueOf(bytes.Trim),
|
||||
"TrimFunc": reflect.ValueOf(bytes.TrimFunc),
|
||||
"TrimLeft": reflect.ValueOf(bytes.TrimLeft),
|
||||
"TrimLeftFunc": reflect.ValueOf(bytes.TrimLeftFunc),
|
||||
"TrimPrefix": reflect.ValueOf(bytes.TrimPrefix),
|
||||
"TrimRight": reflect.ValueOf(bytes.TrimRight),
|
||||
"TrimRightFunc": reflect.ValueOf(bytes.TrimRightFunc),
|
||||
"TrimSpace": reflect.ValueOf(bytes.TrimSpace),
|
||||
"TrimSuffix": reflect.ValueOf(bytes.TrimSuffix),
|
||||
}
|
||||
env.PackageTypes["bytes"] = map[string]reflect.Type{
|
||||
"Buffer": reflect.TypeOf(bytes.Buffer{}),
|
||||
"Reader": reflect.TypeOf(bytes.Reader{}),
|
||||
}
|
||||
bytesGo17()
|
||||
}
|
14
src/tool/run/packages/bytesGo17.go
Normal file
14
src/tool/run/packages/bytesGo17.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build go1.7
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func bytesGo17() {
|
||||
env.Packages["bytes"]["ContainsRune"] = reflect.ValueOf(bytes.ContainsRune)
|
||||
}
|
5
src/tool/run/packages/bytesNotGo17.go
Normal file
5
src/tool/run/packages/bytesNotGo17.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build !go1.7
|
||||
|
||||
package packages
|
||||
|
||||
func bytesGo17() {}
|
15
src/tool/run/packages/encoding.json.go
Normal file
15
src/tool/run/packages/encoding.json.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["encoding/json"] = map[string]reflect.Value{
|
||||
"Marshal": reflect.ValueOf(json.Marshal),
|
||||
"Unmarshal": reflect.ValueOf(json.Unmarshal),
|
||||
}
|
||||
}
|
14
src/tool/run/packages/errors.go
Normal file
14
src/tool/run/packages/errors.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["errors"] = map[string]reflect.Value{
|
||||
"New": reflect.ValueOf(errors.New),
|
||||
}
|
||||
}
|
48
src/tool/run/packages/flag.go
Normal file
48
src/tool/run/packages/flag.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["flag"] = map[string]reflect.Value{
|
||||
"Arg": reflect.ValueOf(flag.Arg),
|
||||
"Args": reflect.ValueOf(flag.Args),
|
||||
"Bool": reflect.ValueOf(flag.Bool),
|
||||
"BoolVar": reflect.ValueOf(flag.BoolVar),
|
||||
"CommandLine": reflect.ValueOf(flag.CommandLine),
|
||||
"ContinueOnError": reflect.ValueOf(flag.ContinueOnError),
|
||||
"Duration": reflect.ValueOf(flag.Duration),
|
||||
"DurationVar": reflect.ValueOf(flag.DurationVar),
|
||||
"ErrHelp": reflect.ValueOf(flag.ErrHelp),
|
||||
"ExitOnError": reflect.ValueOf(flag.ExitOnError),
|
||||
"Float64": reflect.ValueOf(flag.Float64),
|
||||
"Float64Var": reflect.ValueOf(flag.Float64Var),
|
||||
"Int": reflect.ValueOf(flag.Int),
|
||||
"Int64": reflect.ValueOf(flag.Int64),
|
||||
"Int64Var": reflect.ValueOf(flag.Int64Var),
|
||||
"IntVar": reflect.ValueOf(flag.IntVar),
|
||||
"Lookup": reflect.ValueOf(flag.Lookup),
|
||||
"NArg": reflect.ValueOf(flag.NArg),
|
||||
"NFlag": reflect.ValueOf(flag.NFlag),
|
||||
"NewFlagSet": reflect.ValueOf(flag.NewFlagSet),
|
||||
"PanicOnError": reflect.ValueOf(flag.PanicOnError),
|
||||
"Parse": reflect.ValueOf(flag.Parse),
|
||||
"Parsed": reflect.ValueOf(flag.Parsed),
|
||||
"PrintDefaults": reflect.ValueOf(flag.PrintDefaults),
|
||||
"Set": reflect.ValueOf(flag.Set),
|
||||
"String": reflect.ValueOf(flag.String),
|
||||
"StringVar": reflect.ValueOf(flag.StringVar),
|
||||
"Uint": reflect.ValueOf(flag.Uint),
|
||||
"Uint64": reflect.ValueOf(flag.Uint64),
|
||||
"Uint64Var": reflect.ValueOf(flag.Uint64Var),
|
||||
"UintVar": reflect.ValueOf(flag.UintVar),
|
||||
"Usage": reflect.ValueOf(flag.Usage),
|
||||
"Var": reflect.ValueOf(flag.Var),
|
||||
"Visit": reflect.ValueOf(flag.Visit),
|
||||
"VisitAll": reflect.ValueOf(flag.VisitAll),
|
||||
}
|
||||
}
|
32
src/tool/run/packages/fmt.go
Normal file
32
src/tool/run/packages/fmt.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["fmt"] = map[string]reflect.Value{
|
||||
"Errorf": reflect.ValueOf(fmt.Errorf),
|
||||
"Fprint": reflect.ValueOf(fmt.Fprint),
|
||||
"Fprintf": reflect.ValueOf(fmt.Fprintf),
|
||||
"Fprintln": reflect.ValueOf(fmt.Fprintln),
|
||||
"Fscan": reflect.ValueOf(fmt.Fscan),
|
||||
"Fscanf": reflect.ValueOf(fmt.Fscanf),
|
||||
"Fscanln": reflect.ValueOf(fmt.Fscanln),
|
||||
"Print": reflect.ValueOf(fmt.Print),
|
||||
"Printf": reflect.ValueOf(fmt.Printf),
|
||||
"Println": reflect.ValueOf(fmt.Println),
|
||||
"Scan": reflect.ValueOf(fmt.Scan),
|
||||
"Scanf": reflect.ValueOf(fmt.Scanf),
|
||||
"Scanln": reflect.ValueOf(fmt.Scanln),
|
||||
"Sprint": reflect.ValueOf(fmt.Sprint),
|
||||
"Sprintf": reflect.ValueOf(fmt.Sprintf),
|
||||
"Sprintln": reflect.ValueOf(fmt.Sprintln),
|
||||
"Sscan": reflect.ValueOf(fmt.Sscan),
|
||||
"Sscanf": reflect.ValueOf(fmt.Sscanf),
|
||||
"Sscanln": reflect.ValueOf(fmt.Sscanln),
|
||||
}
|
||||
}
|
30
src/tool/run/packages/io.go
Normal file
30
src/tool/run/packages/io.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["io"] = map[string]reflect.Value{
|
||||
"Copy": reflect.ValueOf(io.Copy),
|
||||
"CopyN": reflect.ValueOf(io.CopyN),
|
||||
"EOF": reflect.ValueOf(io.EOF),
|
||||
"ErrClosedPipe": reflect.ValueOf(io.ErrClosedPipe),
|
||||
"ErrNoProgress": reflect.ValueOf(io.ErrNoProgress),
|
||||
"ErrShortBuffer": reflect.ValueOf(io.ErrShortBuffer),
|
||||
"ErrShortWrite": reflect.ValueOf(io.ErrShortWrite),
|
||||
"ErrUnexpectedEOF": reflect.ValueOf(io.ErrUnexpectedEOF),
|
||||
"LimitReader": reflect.ValueOf(io.LimitReader),
|
||||
"MultiReader": reflect.ValueOf(io.MultiReader),
|
||||
"MultiWriter": reflect.ValueOf(io.MultiWriter),
|
||||
"NewSectionReader": reflect.ValueOf(io.NewSectionReader),
|
||||
"Pipe": reflect.ValueOf(io.Pipe),
|
||||
"ReadAtLeast": reflect.ValueOf(io.ReadAtLeast),
|
||||
"ReadFull": reflect.ValueOf(io.ReadFull),
|
||||
"TeeReader": reflect.ValueOf(io.TeeReader),
|
||||
"WriteString": reflect.ValueOf(io.WriteString),
|
||||
}
|
||||
}
|
17
src/tool/run/packages/io.ioutil.go
Normal file
17
src/tool/run/packages/io.ioutil.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["io/ioutil"] = map[string]reflect.Value{
|
||||
"ReadAll": reflect.ValueOf(ioutil.ReadAll),
|
||||
"ReadDir": reflect.ValueOf(ioutil.ReadDir),
|
||||
"ReadFile": reflect.ValueOf(ioutil.ReadFile),
|
||||
"WriteFile": reflect.ValueOf(ioutil.WriteFile),
|
||||
}
|
||||
}
|
29
src/tool/run/packages/log.go
Normal file
29
src/tool/run/packages/log.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["log"] = map[string]reflect.Value{
|
||||
"Fatal": reflect.ValueOf(log.Fatal),
|
||||
"Fatalf": reflect.ValueOf(log.Fatalf),
|
||||
"Fatalln": reflect.ValueOf(log.Fatalln),
|
||||
"Flags": reflect.ValueOf(log.Flags),
|
||||
"New": reflect.ValueOf(log.New),
|
||||
"Output": reflect.ValueOf(log.Output),
|
||||
"Panic": reflect.ValueOf(log.Panic),
|
||||
"Panicf": reflect.ValueOf(log.Panicf),
|
||||
"Panicln": reflect.ValueOf(log.Panicln),
|
||||
"Prefix": reflect.ValueOf(log.Prefix),
|
||||
"Print": reflect.ValueOf(log.Print),
|
||||
"Printf": reflect.ValueOf(log.Printf),
|
||||
"Println": reflect.ValueOf(log.Println),
|
||||
"SetFlags": reflect.ValueOf(log.SetFlags),
|
||||
"SetOutput": reflect.ValueOf(log.SetOutput),
|
||||
"SetPrefix": reflect.ValueOf(log.SetPrefix),
|
||||
}
|
||||
}
|
32
src/tool/run/packages/math.big.go
Normal file
32
src/tool/run/packages/math.big.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["math/big"] = map[string]reflect.Value{
|
||||
"Above": reflect.ValueOf(big.Above),
|
||||
"AwayFromZero": reflect.ValueOf(big.AwayFromZero),
|
||||
"Below": reflect.ValueOf(big.Below),
|
||||
"Exact": reflect.ValueOf(big.Exact),
|
||||
"Jacobi": reflect.ValueOf(big.Jacobi),
|
||||
"MaxBase": reflect.ValueOf(big.MaxBase),
|
||||
"MaxExp": reflect.ValueOf(big.MaxExp),
|
||||
// TODO: https://github.com/surdeus/goblin/src/tool/run/issues/49
|
||||
// "MaxPrec": reflect.ValueOf(big.MaxPrec),
|
||||
"MinExp": reflect.ValueOf(big.MinExp),
|
||||
"NewFloat": reflect.ValueOf(big.NewFloat),
|
||||
"NewInt": reflect.ValueOf(big.NewInt),
|
||||
"NewRat": reflect.ValueOf(big.NewRat),
|
||||
"ParseFloat": reflect.ValueOf(big.ParseFloat),
|
||||
"ToNearestAway": reflect.ValueOf(big.ToNearestAway),
|
||||
"ToNearestEven": reflect.ValueOf(big.ToNearestEven),
|
||||
"ToNegativeInf": reflect.ValueOf(big.ToNegativeInf),
|
||||
"ToPositiveInf": reflect.ValueOf(big.ToPositiveInf),
|
||||
"ToZero": reflect.ValueOf(big.ToZero),
|
||||
}
|
||||
}
|
74
src/tool/run/packages/math.go
Normal file
74
src/tool/run/packages/math.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["math"] = map[string]reflect.Value{
|
||||
"Abs": reflect.ValueOf(math.Abs),
|
||||
"Acos": reflect.ValueOf(math.Acos),
|
||||
"Acosh": reflect.ValueOf(math.Acosh),
|
||||
"Asin": reflect.ValueOf(math.Asin),
|
||||
"Asinh": reflect.ValueOf(math.Asinh),
|
||||
"Atan": reflect.ValueOf(math.Atan),
|
||||
"Atan2": reflect.ValueOf(math.Atan2),
|
||||
"Atanh": reflect.ValueOf(math.Atanh),
|
||||
"Cbrt": reflect.ValueOf(math.Cbrt),
|
||||
"Ceil": reflect.ValueOf(math.Ceil),
|
||||
"Copysign": reflect.ValueOf(math.Copysign),
|
||||
"Cos": reflect.ValueOf(math.Cos),
|
||||
"Cosh": reflect.ValueOf(math.Cosh),
|
||||
"Dim": reflect.ValueOf(math.Dim),
|
||||
"Erf": reflect.ValueOf(math.Erf),
|
||||
"Erfc": reflect.ValueOf(math.Erfc),
|
||||
"Exp": reflect.ValueOf(math.Exp),
|
||||
"Exp2": reflect.ValueOf(math.Exp2),
|
||||
"Expm1": reflect.ValueOf(math.Expm1),
|
||||
"Float32bits": reflect.ValueOf(math.Float32bits),
|
||||
"Float32frombits": reflect.ValueOf(math.Float32frombits),
|
||||
"Float64bits": reflect.ValueOf(math.Float64bits),
|
||||
"Float64frombits": reflect.ValueOf(math.Float64frombits),
|
||||
"Floor": reflect.ValueOf(math.Floor),
|
||||
"Frexp": reflect.ValueOf(math.Frexp),
|
||||
"Gamma": reflect.ValueOf(math.Gamma),
|
||||
"Hypot": reflect.ValueOf(math.Hypot),
|
||||
"Ilogb": reflect.ValueOf(math.Ilogb),
|
||||
"Inf": reflect.ValueOf(math.Inf),
|
||||
"IsInf": reflect.ValueOf(math.IsInf),
|
||||
"IsNaN": reflect.ValueOf(math.IsNaN),
|
||||
"J0": reflect.ValueOf(math.J0),
|
||||
"J1": reflect.ValueOf(math.J1),
|
||||
"Jn": reflect.ValueOf(math.Jn),
|
||||
"Ldexp": reflect.ValueOf(math.Ldexp),
|
||||
"Lgamma": reflect.ValueOf(math.Lgamma),
|
||||
"Log": reflect.ValueOf(math.Log),
|
||||
"Log10": reflect.ValueOf(math.Log10),
|
||||
"Log1p": reflect.ValueOf(math.Log1p),
|
||||
"Log2": reflect.ValueOf(math.Log2),
|
||||
"Logb": reflect.ValueOf(math.Logb),
|
||||
"Max": reflect.ValueOf(math.Max),
|
||||
"Min": reflect.ValueOf(math.Min),
|
||||
"Mod": reflect.ValueOf(math.Mod),
|
||||
"Modf": reflect.ValueOf(math.Modf),
|
||||
"NaN": reflect.ValueOf(math.NaN),
|
||||
"Nextafter": reflect.ValueOf(math.Nextafter),
|
||||
"Pow": reflect.ValueOf(math.Pow),
|
||||
"Pow10": reflect.ValueOf(math.Pow10),
|
||||
"Remainder": reflect.ValueOf(math.Remainder),
|
||||
"Signbit": reflect.ValueOf(math.Signbit),
|
||||
"Sin": reflect.ValueOf(math.Sin),
|
||||
"Sincos": reflect.ValueOf(math.Sincos),
|
||||
"Sinh": reflect.ValueOf(math.Sinh),
|
||||
"Sqrt": reflect.ValueOf(math.Sqrt),
|
||||
"Tan": reflect.ValueOf(math.Tan),
|
||||
"Tanh": reflect.ValueOf(math.Tanh),
|
||||
"Trunc": reflect.ValueOf(math.Trunc),
|
||||
"Y0": reflect.ValueOf(math.Y0),
|
||||
"Y1": reflect.ValueOf(math.Y1),
|
||||
"Yn": reflect.ValueOf(math.Yn),
|
||||
}
|
||||
}
|
26
src/tool/run/packages/math.rand.go
Normal file
26
src/tool/run/packages/math.rand.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["math/rand"] = map[string]reflect.Value{
|
||||
"ExpFloat64": reflect.ValueOf(rand.ExpFloat64),
|
||||
"Float32": reflect.ValueOf(rand.Float32),
|
||||
"Float64": reflect.ValueOf(rand.Float64),
|
||||
"Int": reflect.ValueOf(rand.Int),
|
||||
"Int31": reflect.ValueOf(rand.Int31),
|
||||
"Int31n": reflect.ValueOf(rand.Int31n),
|
||||
"Int63": reflect.ValueOf(rand.Int63),
|
||||
"Int63n": reflect.ValueOf(rand.Int63n),
|
||||
"Intn": reflect.ValueOf(rand.Intn),
|
||||
"NormFloat64": reflect.ValueOf(rand.NormFloat64),
|
||||
"Perm": reflect.ValueOf(rand.Perm),
|
||||
"Seed": reflect.ValueOf(rand.Seed),
|
||||
"Uint32": reflect.ValueOf(rand.Uint32),
|
||||
}
|
||||
}
|
76
src/tool/run/packages/net.go
Normal file
76
src/tool/run/packages/net.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
// +build !appengine
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["net"] = map[string]reflect.Value{
|
||||
"CIDRMask": reflect.ValueOf(net.CIDRMask),
|
||||
"Dial": reflect.ValueOf(net.Dial),
|
||||
"DialIP": reflect.ValueOf(net.DialIP),
|
||||
"DialTCP": reflect.ValueOf(net.DialTCP),
|
||||
"DialTimeout": reflect.ValueOf(net.DialTimeout),
|
||||
"DialUDP": reflect.ValueOf(net.DialUDP),
|
||||
"DialUnix": reflect.ValueOf(net.DialUnix),
|
||||
"ErrWriteToConnected": reflect.ValueOf(net.ErrWriteToConnected),
|
||||
"FileConn": reflect.ValueOf(net.FileConn),
|
||||
"FileListener": reflect.ValueOf(net.FileListener),
|
||||
"FilePacketConn": reflect.ValueOf(net.FilePacketConn),
|
||||
"FlagBroadcast": reflect.ValueOf(net.FlagBroadcast),
|
||||
"FlagLoopback": reflect.ValueOf(net.FlagLoopback),
|
||||
"FlagMulticast": reflect.ValueOf(net.FlagMulticast),
|
||||
"FlagPointToPoint": reflect.ValueOf(net.FlagPointToPoint),
|
||||
"FlagUp": reflect.ValueOf(net.FlagUp),
|
||||
"IPv4": reflect.ValueOf(net.IPv4),
|
||||
"IPv4Mask": reflect.ValueOf(net.IPv4Mask),
|
||||
"IPv4allrouter": reflect.ValueOf(net.IPv4allrouter),
|
||||
"IPv4allsys": reflect.ValueOf(net.IPv4allsys),
|
||||
"IPv4bcast": reflect.ValueOf(net.IPv4bcast),
|
||||
"IPv4len": reflect.ValueOf(net.IPv4len),
|
||||
"IPv4zero": reflect.ValueOf(net.IPv4zero),
|
||||
"IPv6interfacelocalallnodes": reflect.ValueOf(net.IPv6interfacelocalallnodes),
|
||||
"IPv6len": reflect.ValueOf(net.IPv6len),
|
||||
"IPv6linklocalallnodes": reflect.ValueOf(net.IPv6linklocalallnodes),
|
||||
"IPv6linklocalallrouters": reflect.ValueOf(net.IPv6linklocalallrouters),
|
||||
"IPv6loopback": reflect.ValueOf(net.IPv6loopback),
|
||||
"IPv6unspecified": reflect.ValueOf(net.IPv6unspecified),
|
||||
"IPv6zero": reflect.ValueOf(net.IPv6zero),
|
||||
"InterfaceAddrs": reflect.ValueOf(net.InterfaceAddrs),
|
||||
"InterfaceByIndex": reflect.ValueOf(net.InterfaceByIndex),
|
||||
"InterfaceByName": reflect.ValueOf(net.InterfaceByName),
|
||||
"Interfaces": reflect.ValueOf(net.Interfaces),
|
||||
"JoinHostPort": reflect.ValueOf(net.JoinHostPort),
|
||||
"Listen": reflect.ValueOf(net.Listen),
|
||||
"ListenIP": reflect.ValueOf(net.ListenIP),
|
||||
"ListenMulticastUDP": reflect.ValueOf(net.ListenMulticastUDP),
|
||||
"ListenPacket": reflect.ValueOf(net.ListenPacket),
|
||||
"ListenTCP": reflect.ValueOf(net.ListenTCP),
|
||||
"ListenUDP": reflect.ValueOf(net.ListenUDP),
|
||||
"ListenUnix": reflect.ValueOf(net.ListenUnix),
|
||||
"ListenUnixgram": reflect.ValueOf(net.ListenUnixgram),
|
||||
"LookupAddr": reflect.ValueOf(net.LookupAddr),
|
||||
"LookupCNAME": reflect.ValueOf(net.LookupCNAME),
|
||||
"LookupHost": reflect.ValueOf(net.LookupHost),
|
||||
"LookupIP": reflect.ValueOf(net.LookupIP),
|
||||
"LookupMX": reflect.ValueOf(net.LookupMX),
|
||||
"LookupNS": reflect.ValueOf(net.LookupNS),
|
||||
"LookupPort": reflect.ValueOf(net.LookupPort),
|
||||
"LookupSRV": reflect.ValueOf(net.LookupSRV),
|
||||
"LookupTXT": reflect.ValueOf(net.LookupTXT),
|
||||
"ParseCIDR": reflect.ValueOf(net.ParseCIDR),
|
||||
"ParseIP": reflect.ValueOf(net.ParseIP),
|
||||
"ParseMAC": reflect.ValueOf(net.ParseMAC),
|
||||
"Pipe": reflect.ValueOf(net.Pipe),
|
||||
"ResolveIPAddr": reflect.ValueOf(net.ResolveIPAddr),
|
||||
"ResolveTCPAddr": reflect.ValueOf(net.ResolveTCPAddr),
|
||||
"ResolveUDPAddr": reflect.ValueOf(net.ResolveUDPAddr),
|
||||
"ResolveUnixAddr": reflect.ValueOf(net.ResolveUnixAddr),
|
||||
"SplitHostPort": reflect.ValueOf(net.SplitHostPort),
|
||||
}
|
||||
}
|
17
src/tool/run/packages/net.http.cookiejar.go
Normal file
17
src/tool/run/packages/net.http.cookiejar.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"net/http/cookiejar"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["net/http/cookiejar"] = map[string]reflect.Value{
|
||||
"New": reflect.ValueOf(cookiejar.New),
|
||||
}
|
||||
env.PackageTypes["net/http/cookiejar"] = map[string]reflect.Type{
|
||||
"Options": reflect.TypeOf(cookiejar.Options{}),
|
||||
}
|
||||
}
|
32
src/tool/run/packages/net.http.go
Normal file
32
src/tool/run/packages/net.http.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// +build !appengine
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["net/http"] = map[string]reflect.Value{
|
||||
"DefaultClient": reflect.ValueOf(http.DefaultClient),
|
||||
"DefaultServeMux": reflect.ValueOf(http.DefaultServeMux),
|
||||
"DefaultTransport": reflect.ValueOf(http.DefaultTransport),
|
||||
"Handle": reflect.ValueOf(http.Handle),
|
||||
"HandleFunc": reflect.ValueOf(http.HandleFunc),
|
||||
"ListenAndServe": reflect.ValueOf(http.ListenAndServe),
|
||||
"ListenAndServeTLS": reflect.ValueOf(http.ListenAndServeTLS),
|
||||
"NewRequest": reflect.ValueOf(http.NewRequest),
|
||||
"NewServeMux": reflect.ValueOf(http.NewServeMux),
|
||||
"Serve": reflect.ValueOf(http.Serve),
|
||||
"SetCookie": reflect.ValueOf(http.SetCookie),
|
||||
}
|
||||
env.PackageTypes["net/http"] = map[string]reflect.Type{
|
||||
"Client": reflect.TypeOf(http.Client{}),
|
||||
"Cookie": reflect.TypeOf(http.Cookie{}),
|
||||
"Request": reflect.TypeOf(http.Request{}),
|
||||
"Response": reflect.TypeOf(http.Response{}),
|
||||
}
|
||||
}
|
27
src/tool/run/packages/net.url.go
Normal file
27
src/tool/run/packages/net.url.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
// +build !appengine
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["net/url"] = map[string]reflect.Value{
|
||||
"QueryEscape": reflect.ValueOf(url.QueryEscape),
|
||||
"QueryUnescape": reflect.ValueOf(url.QueryUnescape),
|
||||
"Parse": reflect.ValueOf(url.Parse),
|
||||
"ParseRequestURI": reflect.ValueOf(url.ParseRequestURI),
|
||||
"User": reflect.ValueOf(url.User),
|
||||
"UserPassword": reflect.ValueOf(url.UserPassword),
|
||||
"ParseQuery": reflect.ValueOf(url.ParseQuery),
|
||||
}
|
||||
env.PackageTypes["net/url"] = map[string]reflect.Type{
|
||||
"Error": reflect.TypeOf(url.Error{}),
|
||||
"URL": reflect.TypeOf(url.URL{}),
|
||||
"Values": reflect.TypeOf(url.Values{}),
|
||||
}
|
||||
}
|
16
src/tool/run/packages/os.exec.go
Normal file
16
src/tool/run/packages/os.exec.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["os/exec"] = map[string]reflect.Value{
|
||||
"ErrNotFound": reflect.ValueOf(exec.ErrNotFound),
|
||||
"LookPath": reflect.ValueOf(exec.LookPath),
|
||||
"Command": reflect.ValueOf(exec.Command),
|
||||
}
|
||||
}
|
102
src/tool/run/packages/os.go
Normal file
102
src/tool/run/packages/os.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["os"] = map[string]reflect.Value{
|
||||
"Args": reflect.ValueOf(os.Args),
|
||||
"Chdir": reflect.ValueOf(os.Chdir),
|
||||
"Chmod": reflect.ValueOf(os.Chmod),
|
||||
"Chown": reflect.ValueOf(os.Chown),
|
||||
"Chtimes": reflect.ValueOf(os.Chtimes),
|
||||
"Clearenv": reflect.ValueOf(os.Clearenv),
|
||||
"Create": reflect.ValueOf(os.Create),
|
||||
"DevNull": reflect.ValueOf(os.DevNull),
|
||||
"Environ": reflect.ValueOf(os.Environ),
|
||||
"ErrExist": reflect.ValueOf(os.ErrExist),
|
||||
"ErrInvalid": reflect.ValueOf(os.ErrInvalid),
|
||||
"ErrNotExist": reflect.ValueOf(os.ErrNotExist),
|
||||
"ErrPermission": reflect.ValueOf(os.ErrPermission),
|
||||
"Exit": reflect.ValueOf(os.Exit),
|
||||
"Expand": reflect.ValueOf(os.Expand),
|
||||
"ExpandEnv": reflect.ValueOf(os.ExpandEnv),
|
||||
"FindProcess": reflect.ValueOf(os.FindProcess),
|
||||
"Getegid": reflect.ValueOf(os.Getegid),
|
||||
"Getenv": reflect.ValueOf(os.Getenv),
|
||||
"Geteuid": reflect.ValueOf(os.Geteuid),
|
||||
"Getgid": reflect.ValueOf(os.Getgid),
|
||||
"Getgroups": reflect.ValueOf(os.Getgroups),
|
||||
"Getpagesize": reflect.ValueOf(os.Getpagesize),
|
||||
"Getpid": reflect.ValueOf(os.Getpid),
|
||||
"Getuid": reflect.ValueOf(os.Getuid),
|
||||
"Getwd": reflect.ValueOf(os.Getwd),
|
||||
"Hostname": reflect.ValueOf(os.Hostname),
|
||||
"Interrupt": reflect.ValueOf(os.Interrupt),
|
||||
"IsExist": reflect.ValueOf(os.IsExist),
|
||||
"IsNotExist": reflect.ValueOf(os.IsNotExist),
|
||||
"IsPathSeparator": reflect.ValueOf(os.IsPathSeparator),
|
||||
"IsPermission": reflect.ValueOf(os.IsPermission),
|
||||
"Kill": reflect.ValueOf(os.Kill),
|
||||
"Lchown": reflect.ValueOf(os.Lchown),
|
||||
"Link": reflect.ValueOf(os.Link),
|
||||
"Lstat": reflect.ValueOf(os.Lstat),
|
||||
"Mkdir": reflect.ValueOf(os.Mkdir),
|
||||
"MkdirAll": reflect.ValueOf(os.MkdirAll),
|
||||
"ModeAppend": reflect.ValueOf(os.ModeAppend),
|
||||
"ModeCharDevice": reflect.ValueOf(os.ModeCharDevice),
|
||||
"ModeDevice": reflect.ValueOf(os.ModeDevice),
|
||||
"ModeDir": reflect.ValueOf(os.ModeDir),
|
||||
"ModeExclusive": reflect.ValueOf(os.ModeExclusive),
|
||||
"ModeNamedPipe": reflect.ValueOf(os.ModeNamedPipe),
|
||||
"ModePerm": reflect.ValueOf(os.ModePerm),
|
||||
"ModeSetgid": reflect.ValueOf(os.ModeSetgid),
|
||||
"ModeSetuid": reflect.ValueOf(os.ModeSetuid),
|
||||
"ModeSocket": reflect.ValueOf(os.ModeSocket),
|
||||
"ModeSticky": reflect.ValueOf(os.ModeSticky),
|
||||
"ModeSymlink": reflect.ValueOf(os.ModeSymlink),
|
||||
"ModeTemporary": reflect.ValueOf(os.ModeTemporary),
|
||||
"ModeType": reflect.ValueOf(os.ModeType),
|
||||
"NewFile": reflect.ValueOf(os.NewFile),
|
||||
"NewSyscallError": reflect.ValueOf(os.NewSyscallError),
|
||||
"O_APPEND": reflect.ValueOf(os.O_APPEND),
|
||||
"O_CREATE": reflect.ValueOf(os.O_CREATE),
|
||||
"O_EXCL": reflect.ValueOf(os.O_EXCL),
|
||||
"O_RDONLY": reflect.ValueOf(os.O_RDONLY),
|
||||
"O_RDWR": reflect.ValueOf(os.O_RDWR),
|
||||
"O_SYNC": reflect.ValueOf(os.O_SYNC),
|
||||
"O_TRUNC": reflect.ValueOf(os.O_TRUNC),
|
||||
"O_WRONLY": reflect.ValueOf(os.O_WRONLY),
|
||||
"Open": reflect.ValueOf(os.Open),
|
||||
"OpenFile": reflect.ValueOf(os.OpenFile),
|
||||
"PathListSeparator": reflect.ValueOf(os.PathListSeparator),
|
||||
"PathSeparator": reflect.ValueOf(os.PathSeparator),
|
||||
"Pipe": reflect.ValueOf(os.Pipe),
|
||||
"Readlink": reflect.ValueOf(os.Readlink),
|
||||
"Remove": reflect.ValueOf(os.Remove),
|
||||
"RemoveAll": reflect.ValueOf(os.RemoveAll),
|
||||
"Rename": reflect.ValueOf(os.Rename),
|
||||
"SEEK_CUR": reflect.ValueOf(os.SEEK_CUR),
|
||||
"SEEK_END": reflect.ValueOf(os.SEEK_END),
|
||||
"SEEK_SET": reflect.ValueOf(os.SEEK_SET),
|
||||
"SameFile": reflect.ValueOf(os.SameFile),
|
||||
"Setenv": reflect.ValueOf(os.Setenv),
|
||||
"StartProcess": reflect.ValueOf(os.StartProcess),
|
||||
"Stat": reflect.ValueOf(os.Stat),
|
||||
"Stderr": reflect.ValueOf(os.Stderr),
|
||||
"Stdin": reflect.ValueOf(os.Stdin),
|
||||
"Stdout": reflect.ValueOf(os.Stdout),
|
||||
"Symlink": reflect.ValueOf(os.Symlink),
|
||||
"TempDir": reflect.ValueOf(os.TempDir),
|
||||
"Truncate": reflect.ValueOf(os.Truncate),
|
||||
}
|
||||
var signal os.Signal
|
||||
env.PackageTypes["os"] = map[string]reflect.Type{
|
||||
"Signal": reflect.TypeOf(&signal).Elem(),
|
||||
}
|
||||
osNotAppEngine()
|
||||
}
|
15
src/tool/run/packages/os.signal.go
Normal file
15
src/tool/run/packages/os.signal.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"os/signal"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["os/signal"] = map[string]reflect.Value{
|
||||
"Notify": reflect.ValueOf(signal.Notify),
|
||||
"Stop": reflect.ValueOf(signal.Stop),
|
||||
}
|
||||
}
|
5
src/tool/run/packages/osAppEngine.go
Normal file
5
src/tool/run/packages/osAppEngine.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build appengine
|
||||
|
||||
package packages
|
||||
|
||||
func osNotAppEngine() {}
|
14
src/tool/run/packages/osNotAppEngine.go
Normal file
14
src/tool/run/packages/osNotAppEngine.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build !appengine
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func osNotAppEngine() {
|
||||
env.Packages["os"]["Getppid"] = reflect.ValueOf(os.Getppid)
|
||||
}
|
30
src/tool/run/packages/path.filepath.go
Normal file
30
src/tool/run/packages/path.filepath.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["path/filepath"] = map[string]reflect.Value{
|
||||
"Abs": reflect.ValueOf(filepath.Abs),
|
||||
"Base": reflect.ValueOf(filepath.Base),
|
||||
"Clean": reflect.ValueOf(filepath.Clean),
|
||||
"Dir": reflect.ValueOf(filepath.Dir),
|
||||
"EvalSymlinks": reflect.ValueOf(filepath.EvalSymlinks),
|
||||
"Ext": reflect.ValueOf(filepath.Ext),
|
||||
"FromSlash": reflect.ValueOf(filepath.FromSlash),
|
||||
"Glob": reflect.ValueOf(filepath.Glob),
|
||||
"HasPrefix": reflect.ValueOf(filepath.HasPrefix),
|
||||
"IsAbs": reflect.ValueOf(filepath.IsAbs),
|
||||
"Join": reflect.ValueOf(filepath.Join),
|
||||
"Match": reflect.ValueOf(filepath.Match),
|
||||
"Rel": reflect.ValueOf(filepath.Rel),
|
||||
"Split": reflect.ValueOf(filepath.Split),
|
||||
"SplitList": reflect.ValueOf(filepath.SplitList),
|
||||
"ToSlash": reflect.ValueOf(filepath.ToSlash),
|
||||
"VolumeName": reflect.ValueOf(filepath.VolumeName),
|
||||
}
|
||||
}
|
22
src/tool/run/packages/path.go
Normal file
22
src/tool/run/packages/path.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"path"
|
||||
"reflect"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["path"] = map[string]reflect.Value{
|
||||
"Base": reflect.ValueOf(path.Base),
|
||||
"Clean": reflect.ValueOf(path.Clean),
|
||||
"Dir": reflect.ValueOf(path.Dir),
|
||||
"ErrBadPattern": reflect.ValueOf(path.ErrBadPattern),
|
||||
"Ext": reflect.ValueOf(path.Ext),
|
||||
"IsAbs": reflect.ValueOf(path.IsAbs),
|
||||
"Join": reflect.ValueOf(path.Join),
|
||||
"Match": reflect.ValueOf(path.Match),
|
||||
"Split": reflect.ValueOf(path.Split),
|
||||
}
|
||||
}
|
21
src/tool/run/packages/regexp.go
Normal file
21
src/tool/run/packages/regexp.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["regexp"] = map[string]reflect.Value{
|
||||
"Match": reflect.ValueOf(regexp.Match),
|
||||
"MatchReader": reflect.ValueOf(regexp.MatchReader),
|
||||
"MatchString": reflect.ValueOf(regexp.MatchString),
|
||||
"QuoteMeta": reflect.ValueOf(regexp.QuoteMeta),
|
||||
"Compile": reflect.ValueOf(regexp.Compile),
|
||||
"CompilePOSIX": reflect.ValueOf(regexp.CompilePOSIX),
|
||||
"MustCompile": reflect.ValueOf(regexp.MustCompile),
|
||||
"MustCompilePOSIX": reflect.ValueOf(regexp.MustCompilePOSIX),
|
||||
}
|
||||
}
|
19
src/tool/run/packages/runtime.go
Normal file
19
src/tool/run/packages/runtime.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["runtime"] = map[string]reflect.Value{
|
||||
"GC": reflect.ValueOf(runtime.GC),
|
||||
"GOARCH": reflect.ValueOf(runtime.GOARCH),
|
||||
"GOMAXPROCS": reflect.ValueOf(runtime.GOMAXPROCS),
|
||||
"GOOS": reflect.ValueOf(runtime.GOOS),
|
||||
"GOROOT": reflect.ValueOf(runtime.GOROOT),
|
||||
"Version": reflect.ValueOf(runtime.Version),
|
||||
}
|
||||
}
|
44
src/tool/run/packages/sort.go
Normal file
44
src/tool/run/packages/sort.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
// SortFuncsStruct provides functions to be used with Sort
|
||||
type SortFuncsStruct struct {
|
||||
LenFunc func() int
|
||||
LessFunc func(i, j int) bool
|
||||
SwapFunc func(i, j int)
|
||||
}
|
||||
|
||||
func (s SortFuncsStruct) Len() int { return s.LenFunc() }
|
||||
func (s SortFuncsStruct) Less(i, j int) bool { return s.LessFunc(i, j) }
|
||||
func (s SortFuncsStruct) Swap(i, j int) { s.SwapFunc(i, j) }
|
||||
|
||||
func init() {
|
||||
env.Packages["sort"] = map[string]reflect.Value{
|
||||
"Float64s": reflect.ValueOf(sort.Float64s),
|
||||
"Float64sAreSorted": reflect.ValueOf(sort.Float64sAreSorted),
|
||||
"Ints": reflect.ValueOf(sort.Ints),
|
||||
"IntsAreSorted": reflect.ValueOf(sort.IntsAreSorted),
|
||||
"IsSorted": reflect.ValueOf(sort.IsSorted),
|
||||
"Search": reflect.ValueOf(sort.Search),
|
||||
"SearchFloat64s": reflect.ValueOf(sort.SearchFloat64s),
|
||||
"SearchInts": reflect.ValueOf(sort.SearchInts),
|
||||
"SearchStrings": reflect.ValueOf(sort.SearchStrings),
|
||||
"Sort": reflect.ValueOf(sort.Sort),
|
||||
"Stable": reflect.ValueOf(sort.Stable),
|
||||
"Strings": reflect.ValueOf(sort.Strings),
|
||||
"StringsAreSorted": reflect.ValueOf(sort.StringsAreSorted),
|
||||
}
|
||||
env.PackageTypes["sort"] = map[string]reflect.Type{
|
||||
"Float64Slice": reflect.TypeOf(sort.Float64Slice{}),
|
||||
"IntSlice": reflect.TypeOf(sort.IntSlice{}),
|
||||
"StringSlice": reflect.TypeOf(sort.StringSlice{}),
|
||||
"SortFuncsStruct": reflect.TypeOf(&SortFuncsStruct{}),
|
||||
}
|
||||
sortGo18()
|
||||
}
|
16
src/tool/run/packages/sortGo18.go
Normal file
16
src/tool/run/packages/sortGo18.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build go1.8
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func sortGo18() {
|
||||
env.Packages["sort"]["Slice"] = reflect.ValueOf(sort.Slice)
|
||||
env.Packages["sort"]["SliceIsSorted"] = reflect.ValueOf(sort.SliceIsSorted)
|
||||
env.Packages["sort"]["SliceStable"] = reflect.ValueOf(sort.SliceStable)
|
||||
}
|
5
src/tool/run/packages/sortNotGo18.go
Normal file
5
src/tool/run/packages/sortNotGo18.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build !go1.8
|
||||
|
||||
package packages
|
||||
|
||||
func sortGo18() {}
|
23
src/tool/run/packages/strconv.go
Normal file
23
src/tool/run/packages/strconv.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package packages
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/surdeus/goblin/src/tool/run/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
env.Packages["strconv"] = map[string]reflect.Value{
|
||||
"FormatBool": reflect.ValueOf(strconv.FormatBool),
|
||||
"FormatFloat": reflect.ValueOf(strconv.FormatFloat),
|
||||
"FormatInt": reflect.ValueOf(strconv.FormatInt),
|
||||
"FormatUint": reflect.ValueOf(strconv.FormatUint),
|
||||
"ParseBool": reflect.ValueOf(strconv.ParseBool),
|
||||
"ParseFloat": reflect.ValueOf(strconv.ParseFloat),
|
||||
"ParseInt": reflect.ValueOf(strconv.ParseInt),
|
||||
"ParseUint": reflect.ValueOf(strconv.ParseUint),
|
||||
"Atoi": reflect.ValueOf(strconv.Atoi),
|
||||
"Itoa": reflect.ValueOf(strconv.Itoa),
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue