github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/eval/struct.go (about) 1 package eval 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/elves/elvish/parse" 8 ) 9 10 var ( 11 ErrIndexMustBeString = errors.New("index must be string") 12 ) 13 14 // Struct is like a Map with fixed keys. 15 type Struct struct { 16 FieldNames []string 17 Fields []Variable 18 } 19 20 var ( 21 _ Value = (*Struct)(nil) 22 _ MapLike = (*Struct)(nil) 23 ) 24 25 func (*Struct) Kind() string { 26 return "map" 27 } 28 29 func (s *Struct) Repr(indent int) string { 30 var builder MapReprBuilder 31 builder.Indent = indent 32 for i, name := range s.FieldNames { 33 builder.WritePair(parse.Quote(name), s.Fields[i].Get().Repr(indent+1)) 34 } 35 return builder.String() 36 } 37 38 func (s *Struct) Len() int { 39 return len(s.FieldNames) 40 } 41 42 func (s *Struct) IndexOne(idx Value) Value { 43 return s.index(idx).Get() 44 } 45 46 func (s *Struct) HasKey(k Value) bool { 47 index, ok := k.(String) 48 if !ok { 49 return false 50 } 51 for _, name := range s.FieldNames { 52 if string(index) == name { 53 return true 54 } 55 } 56 return false 57 } 58 59 func (s *Struct) IndexSet(idx Value, v Value) { 60 s.index(idx).Set(v) 61 } 62 63 func (s *Struct) index(idx Value) Variable { 64 index, ok := idx.(String) 65 if !ok { 66 throw(ErrIndexMustBeString) 67 } 68 for i, name := range s.FieldNames { 69 if string(index) == name { 70 return s.Fields[i] 71 } 72 } 73 throw(fmt.Errorf("no such field: %s", index.Repr(NoPretty))) 74 panic("unreachable") 75 }