//makeEnv creates an environment to use in eval func makeEnv() *eval.SimpleEnv { env := eval.MakeSimpleEnv() env.Consts["constant1"] = reflect.ValueOf(constant1) var1 := 1 env.Vars["var1"] = reflect.ValueOf(&var1) env.Funcs["add"] = reflect.ValueOf(func(a, b int) int { return a + b }) fmtPkg := eval.MakeSimpleEnv() fmtPkg.Funcs["Sprintf"] = reflect.ValueOf(fmt.Sprintf) env.Pkgs["fmt"] = fmtPkg return env }
func writeImport(w io.Writer, pkg *ast.Package, pkgPath string) error { var files []*ast.File for _, f := range pkg.Files { if ast.FileExports(f) { files = append(files, f) } } env := eval.MakeSimpleEnv() env.Path = pkgPath for _, f := range files { for _, d := range f.Decls { if gen, ok := d.(*ast.GenDecl); ok { for _, s := range gen.Specs { if v, ok := s.(*ast.ValueSpec); ok { for _, i := range v.Names { if gen.Tok == token.VAR { env.Vars[i.Name] = reflect.Value{} } else { env.Consts[i.Name] = reflect.Value{} } } } else if t, ok := s.(*ast.TypeSpec); ok { env.Types[t.Name.Name] = nil } } } else if fun, ok := d.(*ast.FuncDecl); ok && fun.Recv == nil { env.Funcs[fun.Name.Name] = reflect.Value{} } } } return writePkg(w, env, pkg.Name) }
func main() { simpleEnv := eval.MakeSimpleEnv() v := 4 c := "CONSTANT" simpleEnv.Vars["v"] = reflect.ValueOf(&v) simpleEnv.Consts["c"] = reflect.ValueOf(c) env := &CustomEnv{simpleEnv} expectResult("v + 1", env, "6") expectResult("c + \" value\"", env, "constant value") }
// Create an eval.Env environment to use in evaluation. // This is a bit ugly here, because we are rolling everything by hand, but // we want some sort of environment to show off in demo'ing. // The artifical environment we create here consists of // fmt: // fns: fmt.Println, fmt.Printf // os: // types: MyInt // vars: Stdout, Args // main: // type Alice // var alice, aliceptr // // (REPL also adds var results to main) // // See make_env in github.com/rocky/go-fish for an automated way to // create more complete environment from a starting import. func makeBogusEnv() *eval.SimpleEnv { // A copule of things from the fmt package. var fmt_funcs map[string]reflect.Value = make(map[string]reflect.Value) fmt_funcs["Println"] = reflect.ValueOf(fmt.Println) fmt_funcs["Printf"] = reflect.ValueOf(fmt.Printf) // A simple type for demo type MyInt int // A stripped down package environment. See // http://github.com/rocky/go-fish and repl_imports.go for a more // complete environment. pkgs := map[string]eval.Env{ "fmt": &eval.SimpleEnv{ Vars: make(map[string]reflect.Value), Consts: make(map[string]reflect.Value), Funcs: fmt_funcs, Types: make(map[string]reflect.Type), Pkgs: nil, }, "os": &eval.SimpleEnv{ Vars: map[string]reflect.Value{ "Stdout": reflect.ValueOf(&os.Stdout), "Args": reflect.ValueOf(&os.Args)}, Consts: make(map[string]reflect.Value), Funcs: make(map[string]reflect.Value), Types: map[string]reflect.Type{ "MyInt": reflect.TypeOf(*new(MyInt))}, Pkgs: nil, }, } mainEnv := eval.MakeSimpleEnv() mainEnv.Pkgs = pkgs // Some "alice" things for testing type Alice struct { Bob int Secret string } type R rune alice := Alice{1, "shhh"} alicePtr := &alice foo := 10 ints := []int{1, 2, 3, 4} add := func(a, b int) int { return a + b } sum := func(as ...int) int { r := 0 for _, a := range as { r += a } return r } mainEnv.Vars["alice"] = reflect.ValueOf(&alice) mainEnv.Vars["alicePtr"] = reflect.ValueOf(&alicePtr) mainEnv.Vars["foo"] = reflect.ValueOf(&foo) mainEnv.Vars["ints"] = reflect.ValueOf(&ints) mainEnv.Consts["bar"] = reflect.ValueOf(eval.NewConstInt64(5)) mainEnv.Funcs["add"] = reflect.ValueOf(add) mainEnv.Funcs["sum"] = reflect.ValueOf(sum) mainEnv.Types["Alice"] = reflect.TypeOf(Alice{}) mainEnv.Types["R"] = reflect.TypeOf(R(0)) var xi *XI = new(XI) var yi *YI = new(YI) var zi *ZI = new(ZI) *xi = XI(X(0)) *yi = YI(Y(0)) *zi = ZI(Z(0)) mainEnv.Types["XI"] = reflect.TypeOf(xi).Elem() mainEnv.Types["YI"] = reflect.TypeOf(yi).Elem() mainEnv.Types["ZI"] = reflect.TypeOf(zi).Elem() mainEnv.Types["X"] = reflect.TypeOf(X(0)) mainEnv.Types["Y"] = reflect.TypeOf(Y(0)) mainEnv.Types["Z"] = reflect.TypeOf(Z(0)) return mainEnv }
func main() { gack.Repl(eval.MakeSimpleEnv(), nil) }