github.com/ladydascalie/elvish@v0.0.0-20170703214355-2964dd3ece7f/eval/value.go (about) 1 package eval 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "reflect" 8 9 "github.com/elves/elvish/util" 10 ) 11 12 // Definitions for Value interfaces, some simple Value types and some common 13 // Value helpers. 14 15 const ( 16 NoPretty = util.MinInt 17 ) 18 19 // Value is an elvish value. 20 type Value interface { 21 Kinder 22 Reprer 23 } 24 25 // Kinder is anything with kind string. 26 type Kinder interface { 27 Kind() string 28 } 29 30 // Reprer is anything with a Repr method. 31 type Reprer interface { 32 // Repr returns a string that represents a Value. The string either be a 33 // literal of that Value that is preferably deep-equal to it (like `[a b c]` 34 // for a list), or a string enclosed in "<>" containing the kind and 35 // identity of the Value(like `<fn 0xdeadcafe>`). 36 // 37 // If indent is at least 0, it should be pretty-printed with the current 38 // indentation level of indent; the indent of the first line has already 39 // been written and shall not be written in Repr. The returned string 40 // should never contain a trailing newline. 41 Repr(indent int) string 42 } 43 44 // Booler is anything that can be converted to a bool. 45 type Booler interface { 46 Bool() bool 47 } 48 49 // Stringer is anything that can be converted to a string. 50 type Stringer interface { 51 String() string 52 } 53 54 // Lener is anything with a length. 55 type Lener interface { 56 Len() int 57 } 58 59 // Iterable is anything that can be iterated. 60 type Iterable interface { 61 Iterate(func(Value) bool) 62 } 63 64 type IterableValue interface { 65 Iterable 66 Value 67 } 68 69 func collectFromIterable(it Iterable) []Value { 70 var vs []Value 71 if lener, ok := it.(Lener); ok { 72 vs = make([]Value, 0, lener.Len()) 73 } 74 it.Iterate(func(v Value) bool { 75 vs = append(vs, v) 76 return true 77 }) 78 return vs 79 } 80 81 // IterateKeyer is anything with keys that can be iterated. 82 type IterateKeyer interface { 83 IterateKey(func(Value) bool) 84 } 85 86 var ( 87 NoArgs = []Value{} 88 NoOpts = map[string]Value{} 89 ) 90 91 // Callable is anything may be called on an evalCtx with a list of Value's. 92 type Callable interface { 93 Call(ec *EvalCtx, args []Value, opts map[string]Value) 94 } 95 96 type CallableValue interface { 97 Value 98 Callable 99 } 100 101 func mustFn(v Value) Callable { 102 fn, ok := v.(Callable) 103 if !ok { 104 throw(fmt.Errorf("a %s is not callable", v.Kind())) 105 } 106 return fn 107 } 108 109 // Indexer is anything that can be indexed by Values and yields Values. 110 type Indexer interface { 111 Index(idx []Value) []Value 112 } 113 114 // IndexOneer is anything that can be indexed by one Value and yields one Value. 115 type IndexOneer interface { 116 IndexOne(idx Value) Value 117 } 118 119 // IndexSetter is a Value whose elements can be get as well as set. 120 type IndexSetter interface { 121 IndexOneer 122 IndexSet(idx Value, v Value) 123 } 124 125 func mustIndexer(v Value, ec *EvalCtx) Indexer { 126 indexer, ok := getIndexer(v, ec) 127 if !ok { 128 throw(fmt.Errorf("a %s is not indexable", v.Kind())) 129 } 130 return indexer 131 } 132 133 // getIndexer adapts a Value to an Indexer if there is an adapter. It adapts a 134 // Fn if ec is not nil. 135 func getIndexer(v Value, ec *EvalCtx) (Indexer, bool) { 136 if indexer, ok := v.(Indexer); ok { 137 return indexer, true 138 } 139 if indexOneer, ok := v.(IndexOneer); ok { 140 return IndexOneerIndexer{indexOneer}, true 141 } 142 return nil, false 143 } 144 145 // IndexOneerIndexer adapts an IndexOneer to an Indexer by calling all the 146 // indicies on the IndexOner and collect the results. 147 type IndexOneerIndexer struct { 148 IndexOneer 149 } 150 151 func (ioi IndexOneerIndexer) Index(vs []Value) []Value { 152 results := make([]Value, len(vs)) 153 for i, v := range vs { 154 results[i] = ioi.IndexOneer.IndexOne(v) 155 } 156 return results 157 } 158 159 // Error definitions. 160 var ( 161 ErrOnlyStrOrRat = errors.New("only str or rat may be converted to rat") 162 ) 163 164 // Bool represents truthness. 165 type Bool bool 166 167 func (Bool) Kind() string { 168 return "bool" 169 } 170 171 func (b Bool) Repr(int) string { 172 if b { 173 return "$true" 174 } 175 return "$false" 176 } 177 178 func (b Bool) Bool() bool { 179 return bool(b) 180 } 181 182 // ToBool converts a Value to bool. When the Value type implements Bool(), it 183 // is used. Otherwise it is considered true. 184 func ToBool(v Value) bool { 185 if b, ok := v.(Booler); ok { 186 return b.Bool() 187 } 188 return true 189 } 190 191 // Rat is a rational number. 192 type Rat struct { 193 b *big.Rat 194 } 195 196 func (Rat) Kind() string { 197 return "string" 198 } 199 200 func (r Rat) Repr(int) string { 201 return "(rat " + r.String() + ")" 202 } 203 204 func (r Rat) String() string { 205 if r.b.IsInt() { 206 return r.b.Num().String() 207 } 208 return r.b.String() 209 } 210 211 // ToRat converts a Value to rat. A str can be converted to a rat if it can be 212 // parsed. A rat is returned as-is. Other types of values cannot be converted. 213 func ToRat(v Value) (Rat, error) { 214 switch v := v.(type) { 215 case Rat: 216 return v, nil 217 case String: 218 r := big.Rat{} 219 _, err := fmt.Sscanln(string(v), &r) 220 if err != nil { 221 return Rat{}, fmt.Errorf("%s cannot be parsed as rat", v.Repr(NoPretty)) 222 } 223 return Rat{&r}, nil 224 default: 225 return Rat{}, ErrOnlyStrOrRat 226 } 227 } 228 229 // FromJSONInterface converts a interface{} that results from json.Unmarshal to 230 // a Value. 231 func FromJSONInterface(v interface{}) Value { 232 if v == nil { 233 // TODO Use a more appropriate type 234 return String("") 235 } 236 switch v.(type) { 237 case bool: 238 return Bool(v.(bool)) 239 case float64, string: 240 // TODO Use a numeric type for float64 241 return String(fmt.Sprint(v)) 242 case []interface{}: 243 a := v.([]interface{}) 244 vs := make([]Value, len(a)) 245 for i, v := range a { 246 vs[i] = FromJSONInterface(v) 247 } 248 return NewList(vs...) 249 case map[string]interface{}: 250 m := v.(map[string]interface{}) 251 mv := make(map[Value]Value) 252 for k, v := range m { 253 mv[String(k)] = FromJSONInterface(v) 254 } 255 return Map{&mv} 256 default: 257 throw(fmt.Errorf("unexpected json type: %T", v)) 258 return nil // not reached 259 } 260 } 261 262 // DeepEq compares two Value's deeply. 263 func DeepEq(a, b Value) bool { 264 return reflect.DeepEqual(a, b) 265 }