func NewRule(name string, r io.Reader) (*Rule, error) { data, err := ioutil.ReadAll(r) if err != nil { return nil, err } fset := twik.NewFileSet() scope := NewGlobalScope(fset) node, err := twik.Parse(fset, name, data) if err != nil { return nil, err } return &Rule{ Name: name, program: node, scope: scope, lock: &sync.Mutex{}, }, nil }
func run() error { fset := twik.NewFileSet() scope := twik.NewDefaultScope(fset) scope.Create("printf", printfFn) scope.Create("list", listFn) if len(os.Args) > 1 { if strings.HasPrefix(os.Args[1], "-") { return fmt.Errorf("usage: twik [<source file>]") } f, err := os.Open(os.Args[1]) if err != nil { return err } defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { return err } node, err := twik.Parse(fset, os.Args[1], data) if err != nil { return err } _, err = scope.Eval(node) return err } state, err := terminal.MakeRaw(1) if err != nil { return err } defer terminal.Restore(1, state) t := terminal.NewTerminal(os.Stdout, "> ") unclosed := "" for { line, err := t.ReadLine() if err == io.EOF { break } if err != nil { return err } if unclosed != "" { line = unclosed + "\n" + line } unclosed = "" t.SetPrompt("> ") node, err := twik.ParseString(fset, "", line) if err != nil { if strings.HasSuffix(err.Error(), "missing )") { unclosed = line t.SetPrompt(". ") continue } fmt.Println(err) continue } value, err := scope.Eval(node) if err != nil { fmt.Println(err) continue } if value != nil { if reflect.TypeOf(value).Kind() == reflect.Func { fmt.Println("#func") } else if v, ok := value.([]interface{}); ok { if len(v) == 0 { fmt.Println("()") } else { fmt.Print("(list") for _, e := range v { fmt.Printf(" %#v", e) } fmt.Println(")") } } else { fmt.Printf("%#v\n", value) } } } fmt.Println() return nil }