github.com/NeowayLabs/nash@v0.2.2-0.20200127205349-a227041ffd50/sh/obj.go (about) 1 package sh 2 3 import "fmt" 4 5 //go:generate stringer -type=objType 6 const ( 7 StringType objType = iota + 1 8 FnType 9 ListType 10 ) 11 12 type ( 13 objType int 14 15 Obj interface { 16 Type() objType 17 String() string 18 } 19 20 ListObj struct { 21 objType 22 list []Obj 23 } 24 25 FnObj struct { 26 objType 27 fn FnDef 28 } 29 30 StrObj struct { 31 objType 32 runes []rune 33 } 34 35 Collection interface { 36 Len() int 37 Get(index int) (Obj, error) 38 } 39 40 WriteableCollection interface { 41 Set(index int, val Obj) error 42 } 43 ) 44 45 func NewCollection(o Obj) (Collection, error) { 46 sizer, ok := o.(Collection) 47 if !ok { 48 return nil, fmt.Errorf( 49 "SizeError: trying to get size from type %s which is not a collection", 50 o.Type(), 51 ) 52 } 53 return sizer, nil 54 } 55 56 func NewWriteableCollection(o Obj) (WriteableCollection, error) { 57 indexer, ok := o.(WriteableCollection) 58 if !ok { 59 return nil, fmt.Errorf( 60 "IndexError: trying to use a non write/indexable type %s to write on index: ", 61 o.Type(), 62 ) 63 } 64 return indexer, nil 65 } 66 67 func (o objType) Type() objType { 68 return o 69 } 70 71 func NewStrObj(val string) *StrObj { 72 return &StrObj{ 73 runes: []rune(val), 74 objType: StringType, 75 } 76 } 77 78 func (o *StrObj) Str() string { return string(o.runes) } 79 80 func (o *StrObj) String() string { return o.Str() } 81 82 func (o *StrObj) Get(index int) (Obj, error) { 83 if index >= o.Len() { 84 return nil, fmt.Errorf( 85 "IndexError: Index[%d] out of range, string size[%d]", 86 index, 87 o.Len(), 88 ) 89 } 90 91 return NewStrObj(string(o.runes[index])), nil 92 } 93 94 func (o *StrObj) Len() int { 95 return len(o.runes) 96 } 97 98 func NewFnObj(val FnDef) *FnObj { 99 return &FnObj{ 100 fn: val, 101 objType: FnType, 102 } 103 } 104 105 func (o *FnObj) Fn() FnDef { return o.fn } 106 107 func (o *FnObj) String() string { return fmt.Sprintf("<fn %s>", o.fn.Name()) } 108 109 func NewListObj(val []Obj) *ListObj { 110 return &ListObj{ 111 list: val, 112 objType: ListType, 113 } 114 } 115 116 func (o *ListObj) Len() int { 117 return len(o.list) 118 } 119 120 func (o *ListObj) Set(index int, value Obj) error { 121 if index >= len(o.list) { 122 return fmt.Errorf( 123 "IndexError: Index[%d] out of range, list size[%d]", 124 index, 125 len(o.list), 126 ) 127 } 128 o.list[index] = value 129 return nil 130 } 131 132 func (o *ListObj) Get(index int) (Obj, error) { 133 if index >= len(o.list) { 134 return nil, fmt.Errorf( 135 "IndexError: Index out of bounds, index[%d] but list size[%d]", 136 index, 137 len(o.list), 138 ) 139 } 140 return o.list[index], nil 141 } 142 143 func (o *ListObj) List() []Obj { return o.list } 144 145 func (o *ListObj) String() string { 146 result := "" 147 list := o.List() 148 for i := 0; i < len(list); i++ { 149 l := list[i] 150 151 result += l.String() 152 153 if i < len(list)-1 { 154 result += " " 155 } 156 } 157 158 return result 159 }