func AbtabGrepMakeExpressionFilter(inp *AbtabURL, expr string) AbtabFilterFn { var fset = token.NewFileSet() w := eval.NewWorld() InstallStandardLibrary(w) var vars map[string]*eval.Variable = make(map[string]*eval.Variable, 1) var empty = "" var lnum int v, _ := w.DefineVar("__LINE__", eval.TypeOfNative(lnum), eval.ToValue(lnum)) vars["__LINE__"] = v for _, fname := range inp.Header { v, _ := w.DefineVar(ScrubFieldNameForEval(fname), eval.TypeOfNative(empty), eval.ToValue(empty)) vars[fname] = v } return func(rec *Rec) (bool, error) { // NB: this seems expensive, can we just re-assign to the internal var ref? for idx, fname := range inp.Header { var value = rec.Fields[idx] vars[fname].Init = eval.ToValue(value) } //fmt.Fprintf(os.Stderr, "setting __LINE__=%d\n", rec.LineNum) vars["__LINE__"].Init = eval.ToValue(int(rec.LineNum)) // NB: this seems expensive, can we compile once? code, err := w.Compile(fset, expr) if err != nil { return false, err } v, err := code.Run() if err != nil { return false, err } if v.String() == "true" { return true, nil } return false, nil } }
func main() { flag.Parse() w := eval.NewWorld() if *filename != "" { data, err := ioutil.ReadFile(*filename) if err != nil { fmt.Println(err.Error()) os.Exit(1) } file, err := parser.ParseFile(fset, *filename, data, 0) if err != nil { fmt.Println(err.Error()) os.Exit(1) } files := []*ast.File{file} code, err := w.CompilePackage(fset, files, "main") if err != nil { if list, ok := err.(scanner.ErrorList); ok { for _, e := range list { fmt.Println(e.Error()) } } else { fmt.Println(err.Error()) } os.Exit(1) } code, err = w.Compile(fset, "main()") if err != nil { fmt.Println(err.Error()) os.Exit(1) } _, err = code.Run() if err != nil { fmt.Println(err.Error()) os.Exit(1) } os.Exit(0) } fmt.Println(":: welcome to go-eval...") fd := int(os.Stdin.Fd()) oldState, err := terminal.MakeRaw(fd) if err != nil { panic(err) } defer terminal.Restore(fd, oldState) term := terminal.NewTerminal(&shell{r: os.Stdin, w: os.Stdout}, "> ") if term == nil { panic(errors.New("could not create terminal")) } //foo := 123 //w.DefineVar("foo", eval.TypeOfNative(foo), eval.ToValue(foo)) for { line, err := term.ReadLine() if err != nil { break } code, err := w.Compile(fset, line) if err != nil { term.Write([]byte(err.Error() + "\n")) continue } v, err := code.Run() if err != nil { term.Write([]byte(err.Error() + "\n")) continue } if v != nil { term.Write([]byte(v.String() + "\n")) } } }