github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/purely_eval.go (about) 1 package eval 2 3 import ( 4 "strings" 5 6 "src.elv.sh/pkg/fsutil" 7 "src.elv.sh/pkg/parse" 8 ) 9 10 func (ev *Evaler) PurelyEvalCompound(cn *parse.Compound) (string, bool) { 11 return ev.PurelyEvalPartialCompound(cn, -1) 12 } 13 14 func (ev *Evaler) PurelyEvalPartialCompound(cn *parse.Compound, upto int) (string, bool) { 15 tilde := false 16 head := "" 17 for _, in := range cn.Indexings { 18 if len(in.Indicies) > 0 { 19 return "", false 20 } 21 if upto >= 0 && in.To > upto { 22 break 23 } 24 switch in.Head.Type { 25 case parse.Tilde: 26 tilde = true 27 case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted: 28 head += in.Head.Value 29 case parse.Variable: 30 if ev == nil { 31 return "", false 32 } 33 v := ev.PurelyEvalPrimary(in.Head) 34 if s, ok := v.(string); ok { 35 head += s 36 } else { 37 return "", false 38 } 39 default: 40 return "", false 41 } 42 } 43 if tilde { 44 i := strings.Index(head, "/") 45 if i == -1 { 46 i = len(head) 47 } 48 uname := head[:i] 49 home, err := fsutil.GetHome(uname) 50 if err != nil { 51 return "", false 52 } 53 head = home + head[i:] 54 } 55 return head, true 56 } 57 58 // PurelyEvalPrimary evaluates a primary node without causing any side effects. 59 // If this cannot be done, it returns nil. 60 // 61 // Currently, only string literals and variables with no @ can be evaluated. 62 func (ev *Evaler) PurelyEvalPrimary(pn *parse.Primary) interface{} { 63 switch pn.Type { 64 case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted: 65 return pn.Value 66 case parse.Variable: 67 sigil, qname := SplitSigil(pn.Value) 68 if sigil != "" { 69 return nil 70 } 71 fm := &Frame{Evaler: ev, local: ev.Global(), up: new(Ns)} 72 ref := resolveVarRef(fm, qname, nil) 73 if ref != nil { 74 variable := deref(fm, ref) 75 if variable == nil { 76 return nil 77 } 78 return variable.Get() 79 } 80 } 81 return nil 82 }