From 3fb960276485c2ef6be50d8531e9c4882adc1ee8 Mon Sep 17 00:00:00 2001 From: Qi Xiao Date: Sat, 27 Feb 2016 23:43:54 +0100 Subject: [PATCH] Make the builtin namespace a fixed global. --- edit/completers.go | 4 ++-- edit/stylists.go | 2 +- eval/builtinNamespace.go | 15 +++++++++++++++ eval/builtin_func.go | 3 +++ eval/eval.go | 30 +++++++----------------------- eval/eval_test.go | 7 +++---- 6 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 eval/builtinNamespace.go diff --git a/edit/completers.go b/edit/completers.go index 7e013d4b..a614b49f 100644 --- a/edit/completers.go +++ b/edit/completers.go @@ -36,7 +36,7 @@ func complVariable(n parse.Node, ed *Editor) []*candidate { // Collect matching variables. var varnames []string - for varname := range ed.evaler.Builtin() { + for varname := range eval.Builtin() { if strings.HasPrefix(varname, head) { varnames = append(varnames, varname) } @@ -133,7 +133,7 @@ func complFormHeadInner(head string, ed *Editor) []*candidate { for special := range isBuiltinSpecial { foundCommand(special) } - for variable := range ed.evaler.Builtin() { + for variable := range eval.Builtin() { if strings.HasPrefix(variable, eval.FnPrefix) { foundCommand(variable[len(eval.FnPrefix):]) } diff --git a/edit/stylists.go b/edit/stylists.go index a1d9ae49..e1583ec1 100644 --- a/edit/stylists.go +++ b/edit/stylists.go @@ -37,7 +37,7 @@ func goodFormHead(head string, ed *Editor) bool { return util.IsExecutable(head) || isDir(head) } else { return ed.isExternal[head] || - ed.evaler.Builtin()[eval.FnPrefix+head] != nil || + eval.Builtin()[eval.FnPrefix+head] != nil || ed.evaler.Global()[eval.FnPrefix+head] != nil } } diff --git a/eval/builtinNamespace.go b/eval/builtinNamespace.go new file mode 100644 index 00000000..3844ac6a --- /dev/null +++ b/eval/builtinNamespace.go @@ -0,0 +1,15 @@ +package eval + +import ( + "strconv" + "syscall" +) + +var builtinNamespace = Namespace{ + "pid": NewRoVariable(String(strconv.Itoa(syscall.Getpid()))), + "ok": NewRoVariable(OK), + "true": NewRoVariable(Bool(true)), + "false": NewRoVariable(Bool(false)), + "paths": &EnvPathList{envName: "PATH"}, + "pwd": PwdVariable{}, +} diff --git a/eval/builtin_func.go b/eval/builtin_func.go index e1f10af1..09c21580 100644 --- a/eval/builtin_func.go +++ b/eval/builtin_func.go @@ -103,6 +103,9 @@ func init() { &BuiltinFn{"-log", wrapFn(_log)}, &BuiltinFn{"-exec", wrapFn(_exec)}, } + for _, b := range builtinFns { + builtinNamespace[FnPrefix+b.Name] = NewRoVariable(b) + } } var ( diff --git a/eval/eval.go b/eval/eval.go index dfdbe59d..a0affed1 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "os" "os/signal" - "strconv" "strings" "syscall" "unicode/utf8" @@ -33,7 +32,6 @@ type Namespace map[string]Variable // Evaler is used to evaluate elvish sources. It maintains runtime context // shared among all evalCtx instances. type Evaler struct { - builtin Namespace global Namespace modules map[string]Namespace store *store.Store @@ -59,31 +57,17 @@ func (ec *EvalCtx) evaling(n parse.Node) { // NewEvaler creates a new Evaler. func NewEvaler(st *store.Store) *Evaler { - // Construct initial global namespace - pid := String(strconv.Itoa(syscall.Getpid())) - builtin := Namespace{ - "pid": NewRoVariable(pid), - "ok": NewRoVariable(OK), - "true": NewRoVariable(Bool(true)), - "false": NewRoVariable(Bool(false)), - "paths": &EnvPathList{envName: "PATH"}, - "pwd": PwdVariable{}, - } - for _, b := range builtinFns { - builtin[FnPrefix+b.Name] = NewRoVariable(b) - } - // XXX Temporary fix for compiler not knowing builtin namespace. global := Namespace{} - for k, v := range builtin { + for k, v := range builtinNamespace { global[k] = v } - return &Evaler{builtin, global, map[string]Namespace{}, st, nil, nil} + return &Evaler{global, map[string]Namespace{}, st, nil, nil} } func (e *Evaler) searchPaths() []string { - return e.builtin["paths"].(*EnvPathList).get() + return builtinNamespace["paths"].(*EnvPathList).get() } func (e *Evaler) AddModule(name string, ns Namespace) { @@ -340,8 +324,8 @@ func (ev *Evaler) Source(fname string) error { } // Builtin returns the builtin namespace. -func (ev *Evaler) Builtin() Namespace { - return map[string]Variable(ev.builtin) +func Builtin() Namespace { + return map[string]Variable(builtinNamespace) } // Global returns the global namespace. @@ -360,7 +344,7 @@ func (ec *EvalCtx) ResolveVar(ns, name string) Variable { case "up": return ec.up[name] case "builtin": - return ec.builtin[name] + return builtinNamespace[name] case "": if v, ok := ec.local[name]; ok { return v @@ -368,7 +352,7 @@ func (ec *EvalCtx) ResolveVar(ns, name string) Variable { if v, ok := ec.up[name]; ok { return v } - return ec.builtin[name] + return builtinNamespace[name] case "env", "external", "e", "E": if strings.HasPrefix(name, FnPrefix) { return NewRoVariable(ExternalCmd{name[len(FnPrefix):]}) diff --git a/eval/eval_test.go b/eval/eval_test.go index 5021a734..c1de5f0c 100644 --- a/eval/eval_test.go +++ b/eval/eval_test.go @@ -12,11 +12,10 @@ import ( "github.com/elves/elvish/util" ) -func TestNewEvaler(t *testing.T) { - ev := NewEvaler(nil) +func TestBuiltinNamespace(t *testing.T) { pid := strconv.Itoa(syscall.Getpid()) - if ToString(ev.builtin["pid"].Get()) != pid { - t.Errorf(`ev.builtin["pid"] = %v, want %v`, ev.builtin["pid"], pid) + if ToString(builtinNamespace["pid"].Get()) != pid { + t.Errorf(`ev.builtin["pid"] = %v, want %v`, builtinNamespace["pid"], pid) } }