package main import ( "fmt" "io/ioutil" "log" "os" "strings" "github.com/chzyer/readline" "github.com/hellerve/argos/eval" "github.com/hellerve/argos/macro" "github.com/hellerve/argos/parser" ) func runRepl() { rl, err := readline.New("argos> ") if err != nil { log.Fatal(err) } defer rl.Close() e := eval.RootEnv() m := macro.NewMacroEnv() for { input, err := rl.Readline() if err != nil { return } if len(input) == 0 { continue } parsed, err, unconsumed := parser.Parse(input) if err != nil { fmt.Println(err) continue } if len(unconsumed) != 0 { fmt.Println("Unconsumed input:", strings.Join(unconsumed, " ")) continue } expanded, err := macro.Expand(parsed, m) if err != nil { fmt.Println(err) continue } // TODO: how to avoid bindings on error? evald, err := eval.Eval(expanded, e) if err != nil { fmt.Println(err) continue } fmt.Println(evald.Pretty()) } } func runFile(path string) { e := eval.RootEnv() m := macro.NewMacroEnv() inp, err := ioutil.ReadFile(path) if err != nil { fmt.Println(err) return } input := string(inp) parsed, err := parser.ParseAll(input) if err != nil { fmt.Println(err) return } for _, statement := range parsed { expanded, err := macro.Expand(statement, m) if err != nil { fmt.Println(err) return } _, err = eval.Eval(expanded, e) if err != nil { fmt.Println(err) return } } } func main() { args := os.Args if len(args) == 1 { runRepl() } else { runFile(os.Args[1]) } }