eval: Name functions related to variable references consistently.

This commit is contained in:
Qi Xiao 2018-01-29 17:29:38 +00:00
parent 78c4a4fb3a
commit 926ccdd13d
12 changed files with 58 additions and 55 deletions

View File

@ -72,13 +72,13 @@ func complFormHeadInner(head string, ev *eval.Evaler, rawCands chan<- rawCandida
for special := range eval.IsBuiltinSpecial {
got(special)
}
explode, ns, _ := eval.ParseVariable(head)
explode, ns, _ := eval.ParseVariableRef(head)
if !explode {
ev.EachVariableInTop(ns, func(varname string) {
if strings.HasSuffix(varname, eval.FnSuffix) {
got(eval.MakeVariableName(false, ns, varname[:len(varname)-len(eval.FnSuffix)]))
got(eval.MakeVariableRef(false, ns, varname[:len(varname)-len(eval.FnSuffix)]))
} else {
name := eval.MakeVariableName(false, ns, varname)
name := eval.MakeVariableRef(false, ns, varname)
rawCands <- &complexCandidate{name, " = ", " = ", ui.Styles{}}
}
})

View File

@ -17,7 +17,7 @@ func (*variableComplContext) name() string { return "variable" }
func findVariableComplContext(n parse.Node, _ pureEvaler) complContext {
primary := parse.GetPrimary(n)
if primary != nil && primary.Type == parse.Variable {
explode, nsPart, nameSeed := eval.SplitVariable(primary.Value)
explode, nsPart, nameSeed := eval.SplitVariableRef(primary.Value)
// Move past "$", "@" and "<ns>:".
begin := primary.Begin() + 1 + len(explode) + len(nsPart)
ns := nsPart

View File

@ -25,7 +25,7 @@ func goodFormHead(head string, ed *Editor) bool {
return util.IsExecutable(head) || isDir(head)
} else {
ev := ed.evaler
explode, ns, name := eval.ParseVariable(head)
explode, ns, name := eval.ParseVariableRef(head)
if !explode {
switch ns {
case "":

View File

@ -87,7 +87,7 @@ func compileDel(cp *compiler, fn *parse.Form) OpBody {
continue
}
explode, ns, name := ParseVariable(head.Value)
explode, ns, name := ParseVariableRef(head.Value)
if explode {
cp.errorf("arguments to del may be have a leading @")
continue

View File

@ -98,7 +98,7 @@ func (cp *compiler) lvaluesMulti(nodes []*parse.Compound) (LValuesOp, LValuesOp)
func (cp *compiler) lvalueBase(n *parse.Indexing, msg string) (bool, LValuesOpBody) {
qname := cp.literal(n.Head, msg)
explode, ns, name := ParseVariable(qname)
explode, ns, name := ParseVariableRef(qname)
if len(n.Indicies) == 0 {
cp.registerVariableSet(ns, name)
return explode, varOp{ns, name}

View File

@ -198,7 +198,7 @@ func (cp *compiler) form(n *parse.Form) OpBody {
specialOpFunc = compileForm(cp, n)
} else {
var headOpFunc ValuesOpBody
explode, ns, name := ParseVariable(headStr)
explode, ns, name := ParseVariableRef(headStr)
if !explode && cp.registerVariableGet(ns, name+FnSuffix) {
// $head~ resolves.
headOpFunc = variableOp{false, ns, name + FnSuffix}

View File

@ -252,7 +252,7 @@ func (cp *compiler) primary(n *parse.Primary) ValuesOpBody {
case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted:
return literalStr(n.Value)
case parse.Variable:
explode, ns, name := ParseVariable(n.Value)
explode, ns, name := ParseVariableRef(n.Value)
if !cp.registerVariableGet(ns, name) {
cp.errorf("variable $%s not found", n.Value)
}
@ -422,7 +422,7 @@ func (cp *compiler) lambda(n *parse.Primary) ValuesOpBody {
argNames = make([]string, len(n.Elements))
for i, arg := range n.Elements {
qname := mustString(cp, arg, "argument name must be literal string")
explode, ns, name := ParseVariable(qname)
explode, ns, name := ParseVariableRef(qname)
if ns != "" {
cp.errorpf(arg.Begin(), arg.End(), "argument name must be unqualified")
}
@ -445,7 +445,7 @@ func (cp *compiler) lambda(n *parse.Primary) ValuesOpBody {
optDefaultOps = make([]ValuesOp, len(n.MapPairs))
for i, opt := range n.MapPairs {
qname := mustString(cp, opt.Key, "option name must be literal string")
_, ns, name := ParseVariable(qname)
_, ns, name := ParseVariableRef(qname)
if ns != "" {
cp.errorpf(opt.Key.Begin(), opt.Key.End(), "option name must be unqualified")
}

View File

@ -60,7 +60,7 @@ func (cp *compiler) popScope() {
}
func (cp *compiler) registerVariableGetQname(qname string) bool {
_, ns, name := ParseVariable(qname)
_, ns, name := ParseVariableRef(qname)
return cp.registerVariableGet(ns, name)
}
@ -101,7 +101,7 @@ func (cp *compiler) registerVariableGet(ns, name string) bool {
}
func (cp *compiler) registerVariableSetQname(qname string) bool {
_, ns, name := ParseVariable(qname)
_, ns, name := ParseVariableRef(qname)
return cp.registerVariableSet(ns, name)
}

View File

@ -73,7 +73,7 @@ func (ev *Evaler) PurelyEvalPrimary(pn *parse.Primary) types.Value {
case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted:
return pn.Value
case parse.Variable:
explode, ns, name := ParseVariable(pn.Value)
explode, ns, name := ParseVariableRef(pn.Value)
if explode {
return nil
}

View File

@ -5,7 +5,7 @@ func resolve(s string, ec *Frame) Fn {
// (*compiler).form.
// Try variable
explode, ns, name := ParseVariable(s)
explode, ns, name := ParseVariableRef(s)
if !explode {
if v := ec.ResolveVar(ns, name+FnSuffix); v != nil {
if caller, ok := v.Get().(Fn); ok {

View File

@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"os"
"strings"
"github.com/elves/elvish/eval/types"
"github.com/elves/elvish/parse"
@ -33,45 +32,6 @@ func mustGetHome(uname string) string {
return dir
}
// ParseVariable parses a variable reference.
func ParseVariable(text string) (explode bool, ns string, name string) {
explodePart, nsPart, name := SplitVariable(text)
ns = nsPart
if len(ns) > 0 {
ns = ns[:len(ns)-1]
}
return explodePart != "", ns, name
}
// SplitVariable splits a variable reference into three parts: an optional
// explode operator (either "" or "@"), a namespace part, and a name part.
func SplitVariable(text string) (explodePart, nsPart, name string) {
if text == "" {
return "", "", ""
}
e, qname := "", text
if text[0] == '@' {
e = "@"
qname = text[1:]
}
if qname == "" {
return e, "", ""
}
i := strings.LastIndexByte(qname, ':')
return e, qname[:i+1], qname[i+1:]
}
func MakeVariableName(explode bool, ns string, name string) string {
prefix := ""
if explode {
prefix = "@"
}
if ns != "" {
prefix += ns + ":"
}
return prefix + name
}
func makeFlag(m parse.RedirMode) int {
switch m {
case parse.Read:

43
eval/variable_ref.go Normal file
View File

@ -0,0 +1,43 @@
package eval
import "strings"
// ParseVariableRef parses a variable reference.
func ParseVariableRef(text string) (explode bool, ns string, name string) {
explodePart, nsPart, name := SplitVariableRef(text)
ns = nsPart
if len(ns) > 0 {
ns = ns[:len(ns)-1]
}
return explodePart != "", ns, name
}
// SplitVariableRef splits a variable reference into three parts: an optional
// explode operator (either "" or "@"), a namespace part, and a name part.
func SplitVariableRef(text string) (explodePart, nsPart, name string) {
if text == "" {
return "", "", ""
}
e, qname := "", text
if text[0] == '@' {
e = "@"
qname = text[1:]
}
if qname == "" {
return e, "", ""
}
i := strings.LastIndexByte(qname, ':')
return e, qname[:i+1], qname[i+1:]
}
// MakeVariableRef builds a variable reference.
func MakeVariableRef(explode bool, ns string, name string) string {
prefix := ""
if explode {
prefix = "@"
}
if ns != "" {
prefix += ns + ":"
}
return prefix + name
}