Make the builtin namespace a fixed global.

This commit is contained in:
Qi Xiao 2016-02-27 23:43:54 +01:00
parent 892f327dc8
commit 3fb9602764
6 changed files with 31 additions and 30 deletions

View File

@ -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):])
}

View File

@ -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
}
}

15
eval/builtinNamespace.go Normal file
View File

@ -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{},
}

View File

@ -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 (

View File

@ -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):]})

View File

@ -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)
}
}