Example #1
0
File: main.go Project: goist/anko
func main() {
	env := vm.NewEnv()
	env.Define("foo", reflect.ValueOf(1))

	scanner := new(parser.Scanner)
	scanner.Init(`foo + 1`)
	stmts, err := parser.Parse(scanner)
	if err != nil {
		log.Fatal(err)
	}
	v, err := vm.Run(stmts, env)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(v.Interface())
}
Example #2
0
File: anko.go Project: goist/anko
func main() {
	fs.Parse(os.Args[1:])
	if *v {
		fmt.Println(version)
		os.Exit(0)
	}

	env := vm.NewEnv()

	var code string
	var b []byte
	var reader *bufio.Reader
	var following bool
	var source string

	repl := fs.NArg() == 0 && *e == ""

	env.Define("args", reflect.ValueOf(fs.Args()))

	if repl {
		reader = bufio.NewReader(os.Stdin)
		source = "typein"
		os.Args = append([]string{os.Args[0]}, fs.Args()...)
	} else {
		if *e != "" {
			b = []byte(*e)
			source = "argument"
		} else {
			var err error
			b, err = ioutil.ReadFile(fs.Arg(0))
			if err != nil {
				colortext(ct.Red, false, func() {
					fmt.Fprintln(os.Stderr, err)
				})
				os.Exit(1)
			}
			env.Define("args", reflect.ValueOf(fs.Args()[1:]))
			source = filepath.Clean(fs.Arg(0))
		}
		os.Args = fs.Args()
	}

	anko_core.Import(env)

	tbl := map[string]func(env *vm.Env) *vm.Env{
		"encoding/json": anko_encoding_json.Import,
		"flag":          anko_flag.Import,
		"fmt":           anko_fmt.Import,
		"io":            anko_io.Import,
		"io/ioutil":     anko_io_ioutil.Import,
		"math":          anko_math.Import,
		"net":           anko_net.Import,
		"net/http":      anko_net_http.Import,
		"net/url":       anko_net_url.Import,
		"os":            anko_os.Import,
		"os/exec":       anko_os_exec.Import,
		"path":          anko_path.Import,
		"path/filepath": anko_path_filepath.Import,
		"regexp":        anko_regexp.Import,
		"sort":          anko_sort.Import,
		"strings":       anko_strings.Import,
		"github.com/daviddengcn/go-colortext": anko_colortext.Import,
	}

	env.Define("import", reflect.ValueOf(func(s string) interface{} {
		if loader, ok := tbl[s]; ok {
			return loader(env)
		}
		panic(fmt.Sprintf("package '%s' not found", s))
	}))

	for {
		if repl {
			colortext(ct.Green, true, func() {
				if following {
					fmt.Print("  ")
				} else {
					fmt.Print("> ")
				}
			})
			var err error
			b, _, err = reader.ReadLine()
			if err != nil {
				break
			}
			if len(b) == 0 {
				continue
			}
			if code != "" {
				code += "\n"
			}
			code += string(b)
		} else {
			code = string(b)
		}

		scanner := new(parser.Scanner)
		scanner.Init(code)
		stmts, err := parser.Parse(scanner)

		v := vm.NilValue

		if repl {
			if e, ok := err.(*parser.Error); ok {
				if e.Pos.Column == len(b) && !e.Fatal {
					following = true
					continue
				}
				if e.Error() == "unexpected EOF" {
					following = true
					continue
				}
			}
		}
		following = false
		code = ""
		if err == nil {
			v, err = vm.Run(stmts, env)
		}

		if err != nil {
			colortext(ct.Red, false, func() {
				if e, ok := err.(*vm.Error); ok {
					fmt.Fprintf(os.Stderr, "%s:%d: %s\n", source, e.Pos.Line, err)
				} else if e, ok := err.(*parser.Error); ok {
					if e.Filename != "" {
						source = e.Filename
					}
					fmt.Fprintf(os.Stderr, "%s:%d: %s\n", source, e.Pos.Line, err)
				} else {
					fmt.Fprintln(os.Stderr, err)
				}
			})

			if repl {
				continue
			} else {
				os.Exit(1)
			}
		} else {
			if repl {
				colortext(ct.Black, true, func() {
					if v == vm.NilValue || !v.IsValid() {
						fmt.Println("nil")
					} else {
						s, ok := v.Interface().(fmt.Stringer)
						if v.Kind() != reflect.String && ok {
							fmt.Println(s)
						} else {
							fmt.Printf("%#v\n", v.Interface())
						}
					}
				})
			} else {
				break
			}
		}
	}
}
Example #3
0
func runREPL() {
	fmt.Fprintf(os.Stderr, `# For more info about .ank scripts, see https://github.com/mattn/anko.
# In filtering script, DCPL defines variable 'event' which has following structure:
#
#     type Event struct {
#       Type  string
#       Key   string
#       Value []byte
#     }
#
# This REPL has preloaded event in 'event' variable, where Value is JSON encoded object. So that
# the simples filtering script might look like this:
#
#     json = import("json")
#     time = import("time")
#
#     func filter(event) {
#       if event.Type != "mutation" {
#         return false
#       }
#       releaseDate, err = time.Parse(time.RFC3339, "2015-08-15T01:01:42+08:00")
#       if err != nil {
#         return false
#       }
#       val, err = json.Unmarshal(event.Value)
#       if err != nil {
#         return false
#       }
#       documentDate, err = time.Parse(time.RFC3339, toString(val.LastViewDate))
#       if err != nil {
#         return false
#       }
#       return val.Type == "ad-view" && documentDate.After(releaseDate)
#     }
#
#     filter(event)

`)
	var (
		code      string
		following bool
	)

	event := Event{
		Type: "mutation",
		Key:  "foo",
		Value: []byte(`{
  "Type": "ad-view",
  "ObjectId": 43827,
  "ProfileId": 39524,
  "Count": 5,
  "Referrers": ["http://example.com", "http://google.com/search"],
  "LastViewDate": "2015-09-27T12:01:31+03:00"
}`),
	}

	env := NewAnkEnv()
	env.Define("event", reflect.ValueOf(event))
	reader := bufio.NewReader(os.Stdin)
	for {
		if following {
			fmt.Print("  ")
		} else {
			fmt.Print("> ")
		}
		b, _, err := reader.ReadLine()
		if err != nil {
			break
		}
		if len(b) == 0 {
			continue
		}
		if code != "" {
			code += "\n"
		}
		code += string(b)

		scanner := new(parser.Scanner)
		scanner.Init(code)
		stmts, err := parser.Parse(scanner)

		if e, ok := err.(*parser.Error); ok {
			if e.Pos.Column == len(b) && !e.Fatal {
				following = true
				continue
			}
			if e.Error() == "unexpected EOF" || strings.Contains(e.Error(), "unexpected $end") {
				following = true
				continue
			}
		}
		following = false
		code = ""
		v := vm.NilValue
		if err == nil {
			v, err = vm.Run(stmts, env)
		}
		if err != nil {
			if e, ok := err.(*vm.Error); ok {
				fmt.Fprintf(os.Stderr, "VM error at %d: %s\n", e.Pos.Line, err)
			} else if e, ok := err.(*parser.Error); ok {
				fmt.Fprintf(os.Stderr, "Parser error at %d: %s\n", e.Pos.Line, err)
			} else {
				fmt.Fprintln(os.Stderr, err)
			}
		} else {
			if v == vm.NilValue || !v.IsValid() {
				fmt.Println("nil")
			} else {
				s, ok := v.Interface().(fmt.Stringer)
				if v.Kind() != reflect.String && ok {
					fmt.Println(s)
				} else {
					fmt.Printf("%#v\n", v.Interface())
				}
			}
		}

	}
}
Example #4
0
func serveApiPlay(w http.ResponseWriter, r *http.Request) {
	code := r.FormValue("code")
	scanner := new(parser.Scanner)
	scanner.Init(code)
	stmts, err := parser.Parse(scanner)
	if e, ok := err.(*parser.Error); ok {
		w.WriteHeader(500)
		fmt.Fprintf(w, "%d: %s\n", e.Pos.Line, err)
		return
	}

	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	env := vm.NewEnv()

	anko_core.Import(env)

	tbl := map[string]func(env *vm.Env) *vm.Env{
		"encoding/json": anko_encoding_json.Import,
		"flag":          anko_flag.Import,
		"fmt":           anko_fmt.Import,
		"io":            anko_io.Import,
		"io/ioutil":     anko_io_ioutil.Import,
		"math":          anko_math.Import,
		"net":           anko_net.Import,
		"net/http":      anko_net_http.Import,
		"net/url":       anko_net_url.Import,
		"os":            anko_os.Import,
		"os/exec":       anko_os_exec.Import,
		"path":          anko_path.Import,
		"path/filepath": anko_path_filepath.Import,
		"regexp":        anko_regexp.Import,
		"sort":          anko_sort.Import,
		"strings":       anko_strings.Import,
		"github.com/daviddengcn/go-colortext": anko_colortext.Import,
	}

	env.Define("import", reflect.ValueOf(func(s string) interface{} {
		if loader, ok := tbl[s]; ok {
			return loader(env)
		}
		panic(fmt.Sprintf("package '%s' not found", s))
	}))

	env.Define("println", reflect.ValueOf(func(a ...interface{}) {
		fmt.Fprint(w, fmt.Sprintln(a...))
	}))
	env.Define("print", reflect.ValueOf(func(a ...interface{}) {
		fmt.Fprint(w, fmt.Sprint(a...))
	}))
	env.Define("panic", reflect.ValueOf(func(a ...interface{}) {
		w.WriteHeader(500)
		fmt.Fprintf(w, "Can't use panic()")
		return
	}))
	env.Define("load", reflect.ValueOf(func(a ...interface{}) {
		w.WriteHeader(500)
		fmt.Fprintf(w, "Can't use load()")
		return
	}))
	defer env.Destroy()
	_, err = vm.Run(stmts, env)
	if err != nil {
		w.WriteHeader(500)
		if e, ok := err.(*vm.Error); ok {
			fmt.Fprintf(w, "%d: %s\n", e.Pos.Line, err)
		} else if e, ok := err.(*parser.Error); ok {
			fmt.Fprintf(w, "%d: %s\n", e.Pos.Line, err)
		} else {
			fmt.Fprintln(w, e.Error())
		}
	}
}
Example #5
0
func ankoCmd(filename string) error {
	fmt.Println("ANKO " + filename)

	if len(filename) == 0 {
		err := errors.New("Please specify an Anko script file")
		printError(err)
		return err
	}

	file, err := os.Open(filename)
	if err != nil {
		printError(err)
		return err
	}

	env := vm.NewEnv()

	anko_core.Import(env)
	anko_flag.Import(env)
	anko_net.Import(env)
	anko_encoding.Import(env)
	anko_os.Import(env)
	anko_io.Import(env)
	anko_math.Import(env)
	anko_path.Import(env)
	anko_regexp.Import(env)
	anko_sort.Import(env)
	anko_strings.Import(env)
	anko_term.Import(env)

	var ln, code string

	lnScanner := bufio.NewScanner(file)
	for lnScanner.Scan() {

		ln = lnScanner.Text()

		code = code + ln + "\n"

		if err != nil {
			break
			printError(err)
			return err
		}
	}

	scanner := new(parser.Scanner)

	scanner.Init(code)

	stmts, err := parser.Parse(scanner)

	if err != nil {
		printError(err)
		return err
	}
	_, err = vm.Run(stmts, env)
	if err != nil {
		printError(err)
		return err
	}

	file.Close()

	return err
}
Example #6
0
func main() {
	flag.IntVar(&batchSize, "batch-size", 0, "the maximum size of websockets frame (0 - disable batching)")
	flag.StringVar(&clusterURI, "cluster-uri", "couchbase://localhost/", "URI of Couchbase cluster")
	flag.StringVar(&address, "address", "localhost:12345", "interface and port to bind the server")
	flag.StringVar(&filterScriptPath, "filter-script", "", ".ank script to filter values (bypass all event by default)")
	flag.BoolVar(&debug, "debug", false, "export pprof and expvars")
	flag.BoolVar(&repl, "repl", false, "run REPL to test and debug .ank scripts")
	flag.Parse()

	if repl {
		runREPL()
		return
	}

	log.Printf("GOMAXPROCS=%d\n", runtime.GOMAXPROCS(-1))

	if filterScriptPath != "" {
		filterScriptPath = path.Clean(filterScriptPath)
		file, err := os.Open(filterScriptPath)
		if err != nil {
			log.Fatal(err)
		}
		content, err := ioutil.ReadAll(file)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		scanner := new(parser.Scanner)
		scanner.Init(string(content))
		filterScript, err = parser.Parse(scanner)
		if err != nil {
			if e, ok := err.(*parser.Error); ok {
				log.Fatalf("%s:%d:%d: %s\n", filterScriptPath, e.Pos.Line, e.Pos.Column, err)
			} else {
				log.Fatal(err)
			}
		}
		log.Printf("filter script: %v\n", filterScriptPath)
	}

	log.Printf("cluster URI: %v\n", clusterURI)
	log.Printf("batch size: %v bytes\n", batchSize)
	server := websocket.Server{
		Handler:   onConnected,
		Handshake: checkAuth,
	}
	mux := http.NewServeMux()
	mux.Handle("/ws/", server)
	mux.HandleFunc("/http/", httpHandler)
	log.Printf("GET /ws/            # websockets endpoint")
	log.Printf("GET /http/          # HTTP endpoint with chunked encoding")
	if debug {
		initDebug(mux)
		log.Printf("GET /debug/pprof/   # pprof reports")
		log.Printf("GET /debug/vars/    # expvar metrics")
	}
	log.Printf("listening at %s", address)
	err := http.ListenAndServe(address, mux)
	if err != nil {
		log.Fatal(err)
	}
}
Example #7
0
File: core.go Project: goist/anko
func Import(env *vm.Env) *vm.Env {
	env.Define("len", reflect.ValueOf(func(v interface{}) int64 {
		rv := reflect.ValueOf(v)
		if rv.Kind() == reflect.Interface {
			rv = rv.Elem()
		}
		if rv.Kind() == reflect.String {
			return int64(len([]byte(rv.String())))
		}
		if rv.Kind() != reflect.Array && rv.Kind() != reflect.Slice {
			panic("Argument #1 should be array")
		}
		return int64(rv.Len())
	}))

	env.Define("keys", reflect.ValueOf(func(v interface{}) []string {
		rv := reflect.ValueOf(v)
		if rv.Kind() == reflect.Interface {
			rv = rv.Elem()
		}
		if rv.Kind() != reflect.Map {
			panic("Argument #1 should be map")
		}
		keys := []string{}
		mk := rv.MapKeys()
		for _, key := range mk {
			keys = append(keys, key.String())
		}
		return keys
	}))

	env.Define("range", reflect.ValueOf(func(args ...int64) []int64 {
		if len(args) < 1 {
			panic("Missing arguments")
		}
		if len(args) > 2 {
			panic("Too many arguments")
		}
		var min, max int64
		if len(args) == 1 {
			min = 0
			max = args[0] - 1
		} else {
			min = args[0]
			max = args[1]
		}
		arr := []int64{}
		for i := min; i <= max; i++ {
			arr = append(arr, i)
		}
		return arr
	}))

	env.Define("toBytes", reflect.ValueOf(func(s string) []byte {
		return []byte(s)
	}))

	env.Define("toRunes", reflect.ValueOf(func(s string) []rune {
		return []rune(s)
	}))

	env.Define("toString", reflect.ValueOf(func(v interface{}) string {
		return fmt.Sprint(v)
	}))

	env.Define("toInt", reflect.ValueOf(func(v interface{}) int64 {
		nt := reflect.TypeOf(1)
		rv := reflect.ValueOf(v)
		if rv.Type().ConvertibleTo(nt) {
			return 0
		}
		return rv.Convert(nt).Int()
	}))

	env.Define("toFloat", reflect.ValueOf(func(v interface{}) float64 {
		nt := reflect.TypeOf(1.0)
		rv := reflect.ValueOf(v)
		if rv.Type().ConvertibleTo(nt) {
			return 0.0
		}
		return rv.Convert(nt).Float()
	}))

	env.Define("toBool", reflect.ValueOf(func(v interface{}) bool {
		nt := reflect.TypeOf(true)
		rv := reflect.ValueOf(v)
		if rv.Type().ConvertibleTo(nt) {
			return false
		}
		return rv.Convert(nt).Bool()
	}))

	env.Define("toChar", reflect.ValueOf(func(s rune) string {
		return string(s)
	}))

	env.Define("toRune", reflect.ValueOf(func(s string) rune {
		if len(s) == 0 {
			return 0
		}
		return []rune(s)[0]
	}))

	env.Define("string", reflect.ValueOf(func(b []byte) string {
		return string(b)
	}))

	env.Define("typeof", reflect.ValueOf(func(v interface{}) string {
		return reflect.TypeOf(v).String()
	}))

	env.Define("defined", reflect.ValueOf(func(s string) bool {
		_, err := env.Get(s)
		return err == nil
	}))

	env.Define("load", reflect.ValueOf(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(stmts, env)
		if err != nil {
			panic(err)
		}
		if rv.IsValid() && rv.CanInterface() {
			return rv.Interface()
		}
		return nil
	}))

	env.Define("panic", reflect.ValueOf(func(e interface{}) {
		os.Setenv("ANKO_DEBUG", "1")
		panic(e)
	}))

	env.Define("print", reflect.ValueOf(fmt.Print))
	env.Define("println", reflect.ValueOf(fmt.Println))
	env.Define("printf", reflect.ValueOf(fmt.Printf))

	return env
}