Beispiel #1
0
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)
			}
		}
	}
}
Beispiel #2
0
// 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)
	}
}
Beispiel #3
0
func SimpleInspect(a ...interface{}) string {
	value := a[0].(reflect.Value)
	return eval.Inspect(value)
}