func WhatisCommand(args []string) { if len(args) == 2 { arg := args[1] if _, ok := repl.Env.Pkg(arg).(*eval.SimpleEnv); ok { repl.Msg("`%s' is a package", arg) return } ids := strings.Split(arg, ".") if len(ids) == 1 { name := ids[0] if typ := repl.Env.Type(name); typ != nil { repl.Msg("%s is a type: %s", typ.String()) return } } if len(ids) == 2 { pkgName := ids[0] name := ids[1] if pkg, ok := repl.Env.Pkg(pkgName).(*eval.SimpleEnv); ok { if typ := pkg.Type(name); typ != nil { repl.Msg("%s is a kind: %s", arg, typ.Kind()) repl.Msg("%s is a type: %v", arg, typ) return } } } } line := repl.CmdLine[len(args[0]):len(repl.CmdLine)] if expr, err := parser.ParseExpr(line); err != nil { if pair := eval.FormatErrorPos(line, err.Error()); len(pair) == 2 { repl.Msg(pair[0]) repl.Msg(pair[1]) } repl.Errmsg("parse error: %s\n", err) } else if cexpr, errs := eval.CheckExpr(expr, repl.Env); len(errs) != 0 { for _, cerr := range errs { repl.Msg("%v", cerr) } } else { repl.Section(cexpr.String()) if cexpr.IsConst() { repl.Msg("constant:\t%s", cexpr.Const()) } knownTypes := cexpr.KnownType() if len(knownTypes) == 1 { repl.Msg("type:\t%s", knownTypes[0]) } else { for i, v := range knownTypes { repl.Msg("type[%d]:\t%s", i, v) } } } }
// REPL is the read, eval, and print loop. func REPL(env *eval.SimpleEnv, readLineFn ReadLineFnType, inspectFn InspectFnType) { var err error // A place to store result values of expressions entered // interactively results := make([]interface{}, 0, 10) env.Vars["results"] = reflect.ValueOf(&results) Env = env exprs := 0 line, err := readLineFn("gofish> ", true) for true { if err != nil { if err == io.EOF { break } panic(err) } if wasProcessed(line) { if LeaveREPL { break } line, err = readLineFn("gofish> ", true) continue } if stmt, err := eval.ParseStmt(line); err != nil { if pair := eval.FormatErrorPos(line, err.Error()); len(pair) == 2 { Msg(pair[0]) Msg(pair[1]) } Errmsg("parse error: %s", err) } else if expr, ok := stmt.(*ast.ExprStmt); ok { if cexpr, errs := eval.CheckExpr(expr.X, env); len(errs) != 0 { for _, cerr := range errs { Errmsg("%v", cerr) } } else if vals, err := eval.EvalExpr(cexpr, env); err != nil { Errmsg("panic: %s", 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 { Msg("Kind = %v", kind) Msg("Type = %v", typ) } else { Msg("Kind = Type = %v", kind) } Msg("results[%d] = %s", exprs, inspectFn(value)) exprs += 1 results = append(results, (vals)[0].Interface()) } else { Msg("%s", value) } } else { Msg("Kind = Multi-Value") size := len(vals) for i, v := range vals { fmt.Printf("%s", inspectFn(v)) if i < size-1 { fmt.Printf(", ") } } Msg("") exprs += 1 results = append(results, vals) } } else { if cstmt, errs := eval.CheckStmt(stmt, env); len(errs) != 0 { for _, cerr := range errs { Errmsg("%v", cerr) } } else if _, err := eval.InterpStmt(cstmt, env); err != nil { Errmsg("panic: %s", err) } } line, err = readLineFn("gofish> ", true) } }