func Repl(env *eval.SimpleEnv, history []string) { deleteMe := true if history == nil { introText() deleteMe = false } else { for _, h := range history { readline.AddHistory(h) } } // As a party piece. add the package contents as a map to the env. We can get away with this // because eval checks for packages before vars for EACH scope. Therefore, if a local variable // masks a pkg, it will still be found first. In other words, I'm cheating here, it's a hack. for name, pkg := range env.Pkgs { e := pkg.(*eval.SimpleEnv) // Don't overwrite existing vars if _, ok := e.Vars[name]; ok { continue } m := map[string]reflect.Type{} for n, v := range e.Vars { m[n] = v.Elem().Type() } for n, c := range e.Consts { m[n] = c.Type() } for n, f := range e.Funcs { m[n] = f.Type() } for n, t := range e.Types { m[n] = t } env.Vars[name] = reflect.ValueOf(&m) } complete := func(test string, start, end int) []string { return []string{""} } readline.SetAttemptedCompletionFunction(complete) prompt := "go> " line := "" for line != "quit" { result := readline.ReadLine(&prompt) if result == nil { fmt.Printf("\n") break } line := *result history = append(history, line) readline.AddHistory(line) if err := handleImport(env, line, history, deleteMe); err != nil { fmt.Println(err) // TODO[crc] move into generalised error position formatting code when written } else if stmt, err := eval.ParseStmt(line); err != nil { if pair := eval.FormatErrorPos(line, err.Error()); len(pair) == 2 { fmt.Println(pair[0]) fmt.Println(pair[1]) } fmt.Printf("%s\n", err) } else if expr, ok := stmt.(*ast.ExprStmt); ok { if cexpr, errs := eval.CheckExpr(expr.X, env); errs != nil { for _, cerr := range errs { fmt.Printf("%v\n", cerr) } } else if vals, err := eval.EvalExpr(cexpr, env); err != nil { fmt.Printf("panic: %s\n", err) } else if len(vals) == 0 { fmt.Printf("Kind=Slice\nvoid\n") } else { // Success if len(vals) == 1 { value := (vals)[0] if value.IsValid() { kind := value.Kind().String() typ := value.Type().String() if typ != kind { fmt.Printf("Kind = %v\n", kind) fmt.Printf("Type = %v\n", typ) } else { fmt.Printf("Kind = Type = %v\n", kind) } fmt.Printf("it = %s\n", eval.Inspect(value)) it := reflect.New(vals[0].Type()) it.Elem().Set(vals[0]) env.Vars["it"] = it } else { fmt.Printf("%s\n", value) } } else if len(vals) > 1 { fmt.Printf("Kind = Multi-Value\nit = ") size := len(vals) it := make([]interface{}, len(vals)) for i, v := range vals { fmt.Printf("%s", eval.Inspect(v)) if i < size-1 { fmt.Printf(", ") } it[i] = vals[i].Interface() } fmt.Printf("\n") env.Vars["it"] = reflect.ValueOf(&it) } } } else { if cstmt, errs := eval.CheckStmt(stmt, env); len(errs) != 0 { for _, cerr := range errs { fmt.Printf("%v\n", cerr) } } else if err = eval.InterpStmt(cstmt, env); err != nil { fmt.Printf("panic: %s\n", err) } } } }
// REPL is the a read, eval, and print loop. func REPL(env *eval.SimpleEnv) { var err error // A place to store result values of expressions entered // interactively results := make([]interface{}, 0, 10) env.Vars["results"] = reflect.ValueOf(&results) exprs := 0 in := bufio.NewReader(os.Stdin) line, err := readline("go> ", in) for line != "quit" { if err != nil { if err == io.EOF { break } panic(err) } if expr, err := parser.ParseExpr(line); err != nil { if pair := eval.FormatErrorPos(line, err.Error()); len(pair) == 2 { fmt.Println(pair[0]) fmt.Println(pair[1]) } fmt.Printf("parse error: %s\n", err) } else if cexpr, errs := eval.CheckExpr(expr, env); len(errs) != 0 { for _, cerr := range errs { fmt.Printf("check error: %v\n", cerr) } } else if vals, err := eval.EvalExpr(cexpr, env); err != nil { fmt.Printf("panic: %s\n", err) } else if len(vals) == 0 { fmt.Printf("Kind=Slice\nvoid\n") } else if len(vals) == 1 { value := (vals)[0] if value.IsValid() { kind := value.Kind().String() typ := value.Type().String() if typ != kind { fmt.Printf("Kind = %v\n", kind) fmt.Printf("Type = %v\n", typ) } else { fmt.Printf("Kind = Type = %v\n", kind) } fmt.Printf("results[%d] = %s\n", exprs, eval.Inspect(value)) exprs += 1 results = append(results, (vals)[0].Interface()) } else { fmt.Printf("%s\n", value) } } else { fmt.Printf("Kind = Multi-Value\n") size := len(vals) for i, v := range vals { fmt.Printf("%s", eval.Inspect(v)) if i < size-1 { fmt.Printf(", ") } } fmt.Printf("\n") exprs += 1 results = append(results, vals) } line, err = readline("go> ", in) } }
func SimpleInspect(a ...interface{}) string { value := a[0].(reflect.Value) return eval.Inspect(value) }