github.com/mattn/anko@v0.1.10/vm/vmLetExpr.go (about) 1 package vm 2 3 import ( 4 "reflect" 5 6 "github.com/mattn/anko/ast" 7 "github.com/mattn/anko/env" 8 ) 9 10 func (runInfo *runInfoStruct) invokeLetExpr() { 11 switch expr := runInfo.expr.(type) { 12 13 // IdentExpr 14 case *ast.IdentExpr: 15 if runInfo.env.SetValue(expr.Lit, runInfo.rv) != nil { 16 runInfo.err = nil 17 runInfo.env.DefineValue(expr.Lit, runInfo.rv) 18 } 19 20 // MemberExpr 21 case *ast.MemberExpr: 22 value := runInfo.rv 23 24 runInfo.expr = expr.Expr 25 runInfo.invokeExpr() 26 if runInfo.err != nil { 27 return 28 } 29 30 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 31 runInfo.rv = runInfo.rv.Elem() 32 } 33 34 if env, ok := runInfo.rv.Interface().(*env.Env); ok { 35 runInfo.err = env.SetValue(expr.Name, value) 36 if runInfo.err != nil { 37 runInfo.err = newError(expr, runInfo.err) 38 runInfo.rv = nilValue 39 } 40 return 41 } 42 43 if runInfo.rv.Kind() == reflect.Ptr { 44 runInfo.rv = runInfo.rv.Elem() 45 } 46 47 switch runInfo.rv.Kind() { 48 49 // Struct 50 case reflect.Struct: 51 field, found := runInfo.rv.Type().FieldByName(expr.Name) 52 if !found { 53 runInfo.err = newStringError(expr, "no member named '"+expr.Name+"' for struct") 54 runInfo.rv = nilValue 55 return 56 } 57 runInfo.rv = runInfo.rv.FieldByIndex(field.Index) 58 // From reflect CanSet: 59 // A Value can be changed only if it is addressable and was not obtained by the use of unexported struct fields. 60 // Often a struct has to be passed as a pointer to be set 61 if !runInfo.rv.CanSet() { 62 runInfo.err = newStringError(expr, "struct member '"+expr.Name+"' cannot be assigned") 63 runInfo.rv = nilValue 64 return 65 } 66 67 value, runInfo.err = convertReflectValueToType(value, runInfo.rv.Type()) 68 if runInfo.err != nil { 69 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+runInfo.rv.Type().String()+" for struct") 70 runInfo.rv = nilValue 71 return 72 } 73 74 runInfo.rv.Set(value) 75 return 76 77 // Map 78 case reflect.Map: 79 value, runInfo.err = convertReflectValueToType(value, runInfo.rv.Type().Elem()) 80 if runInfo.err != nil { 81 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+runInfo.rv.Type().Elem().String()+" for map") 82 runInfo.rv = nilValue 83 return 84 } 85 if runInfo.rv.IsNil() { 86 // make new map 87 item := reflect.MakeMap(runInfo.rv.Type()) 88 item.SetMapIndex(reflect.ValueOf(expr.Name), value) 89 // assign new map 90 runInfo.rv = item 91 runInfo.expr = expr.Expr 92 runInfo.invokeLetExpr() 93 runInfo.rv = item.MapIndex(reflect.ValueOf(expr.Name)) 94 return 95 } 96 runInfo.rv.SetMapIndex(reflect.ValueOf(expr.Name), value) 97 98 default: 99 runInfo.err = newStringError(expr, "type "+runInfo.rv.Kind().String()+" does not support member operation") 100 runInfo.rv = nilValue 101 } 102 103 // ItemExpr 104 case *ast.ItemExpr: 105 value := runInfo.rv 106 107 runInfo.expr = expr.Item 108 runInfo.invokeExpr() 109 if runInfo.err != nil { 110 return 111 } 112 item := runInfo.rv 113 114 runInfo.expr = expr.Index 115 runInfo.invokeExpr() 116 if runInfo.err != nil { 117 return 118 } 119 120 if item.Kind() == reflect.Interface && !item.IsNil() { 121 item = item.Elem() 122 } 123 124 switch item.Kind() { 125 126 // Slice && Array 127 case reflect.Slice, reflect.Array: 128 var index int 129 index, runInfo.err = tryToInt(runInfo.rv) 130 if runInfo.err != nil { 131 runInfo.err = newStringError(expr, "index must be a number") 132 runInfo.rv = nilValue 133 return 134 } 135 136 if index == item.Len() { 137 // try to do automatic append 138 value, runInfo.err = convertReflectValueToType(value, item.Type().Elem()) 139 if runInfo.err != nil { 140 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+item.Type().Elem().String()+" for slice index") 141 runInfo.rv = nilValue 142 return 143 } 144 item = reflect.Append(item, value) 145 runInfo.rv = item 146 runInfo.expr = expr.Item 147 runInfo.invokeLetExpr() 148 runInfo.rv = item.Index(index) 149 return 150 } 151 152 if index < 0 || index >= item.Len() { 153 runInfo.err = newStringError(expr, "index out of range") 154 runInfo.rv = nilValue 155 return 156 } 157 item = item.Index(index) 158 if !item.CanSet() { 159 runInfo.err = newStringError(expr, "index cannot be assigned") 160 runInfo.rv = nilValue 161 return 162 } 163 164 value, runInfo.err = convertReflectValueToType(value, item.Type()) 165 if runInfo.err != nil { 166 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+item.Type().String()+" for slice index") 167 runInfo.rv = nilValue 168 return 169 } 170 171 item.Set(value) 172 runInfo.rv = item 173 174 // Map 175 case reflect.Map: 176 runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, item.Type().Key()) 177 if runInfo.err != nil { 178 runInfo.err = newStringError(expr, "index type "+runInfo.rv.Type().String()+" cannot be used for map index type "+item.Type().Key().String()) 179 runInfo.rv = nilValue 180 return 181 } 182 183 value, runInfo.err = convertReflectValueToType(value, item.Type().Elem()) 184 if runInfo.err != nil { 185 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+item.Type().Elem().String()+" for map") 186 runInfo.rv = nilValue 187 return 188 } 189 190 if item.IsNil() { 191 // make new map 192 item = reflect.MakeMap(item.Type()) 193 item.SetMapIndex(runInfo.rv, value) 194 mapIndex := runInfo.rv 195 // assign new map 196 runInfo.rv = item 197 runInfo.expr = expr.Item 198 runInfo.invokeLetExpr() 199 runInfo.rv = item.MapIndex(mapIndex) 200 return 201 } 202 item.SetMapIndex(runInfo.rv, value) 203 204 // String 205 case reflect.String: 206 var index int 207 index, runInfo.err = tryToInt(runInfo.rv) 208 if runInfo.err != nil { 209 runInfo.err = newStringError(expr, "index must be a number") 210 runInfo.rv = nilValue 211 return 212 } 213 214 value, runInfo.err = convertReflectValueToType(value, item.Type()) 215 if runInfo.err != nil { 216 runInfo.err = newStringError(expr, "type "+value.Type().String()+" cannot be assigned to type "+item.Type().String()) 217 runInfo.rv = nilValue 218 return 219 } 220 221 if index == item.Len() { 222 // automatic append 223 if item.CanSet() { 224 item.SetString(item.String() + value.String()) 225 return 226 } 227 228 runInfo.rv = reflect.ValueOf(item.String() + value.String()) 229 runInfo.expr = expr.Item 230 runInfo.invokeLetExpr() 231 return 232 } 233 234 if index < 0 || index >= item.Len() { 235 runInfo.err = newStringError(expr, "index out of range") 236 runInfo.rv = nilValue 237 return 238 } 239 240 if item.CanSet() { 241 item.SetString(item.Slice(0, index).String() + value.String() + item.Slice(index+1, item.Len()).String()) 242 runInfo.rv = item 243 return 244 } 245 246 runInfo.rv = reflect.ValueOf(item.Slice(0, index).String() + value.String() + item.Slice(index+1, item.Len()).String()) 247 runInfo.expr = expr.Item 248 runInfo.invokeLetExpr() 249 250 default: 251 runInfo.err = newStringError(expr, "type "+item.Kind().String()+" does not support index operation") 252 runInfo.rv = nilValue 253 } 254 255 // SliceExpr 256 case *ast.SliceExpr: 257 value := runInfo.rv 258 259 runInfo.expr = expr.Item 260 runInfo.invokeExpr() 261 if runInfo.err != nil { 262 return 263 } 264 item := runInfo.rv 265 266 if item.Kind() == reflect.Interface && !item.IsNil() { 267 item = item.Elem() 268 } 269 270 switch item.Kind() { 271 272 // Slice && Array 273 case reflect.Slice, reflect.Array: 274 var beginIndex int 275 endIndex := item.Len() 276 277 if expr.Begin != nil { 278 runInfo.expr = expr.Begin 279 runInfo.invokeExpr() 280 if runInfo.err != nil { 281 return 282 } 283 beginIndex, runInfo.err = tryToInt(runInfo.rv) 284 if runInfo.err != nil { 285 runInfo.err = newStringError(expr, "index must be a number") 286 runInfo.rv = nilValue 287 return 288 } 289 // (0 <= low) <= high <= len(a) 290 if beginIndex < 0 { 291 runInfo.err = newStringError(expr, "index out of range") 292 runInfo.rv = nilValue 293 return 294 } 295 } 296 297 if expr.End != nil { 298 runInfo.expr = expr.End 299 runInfo.invokeExpr() 300 if runInfo.err != nil { 301 return 302 } 303 endIndex, runInfo.err = tryToInt(runInfo.rv) 304 if runInfo.err != nil { 305 runInfo.err = newStringError(expr, "index must be a number") 306 runInfo.rv = nilValue 307 return 308 } 309 // 0 <= low <= (high <= len(a)) 310 if endIndex > item.Len() { 311 runInfo.err = newStringError(expr, "index out of range") 312 runInfo.rv = nilValue 313 return 314 } 315 } 316 317 // 0 <= (low <= high) <= len(a) 318 if beginIndex > endIndex { 319 runInfo.err = newStringError(expr, "index out of range") 320 runInfo.rv = nilValue 321 return 322 } 323 324 sliceCap := item.Cap() 325 if expr.Cap != nil { 326 runInfo.expr = expr.Cap 327 runInfo.invokeExpr() 328 if runInfo.err != nil { 329 return 330 } 331 sliceCap, runInfo.err = tryToInt(runInfo.rv) 332 if runInfo.err != nil { 333 runInfo.err = newStringError(expr, "cap must be a number") 334 runInfo.rv = nilValue 335 return 336 } 337 // 0 <= low <= (high <= max <= cap(a)) 338 if sliceCap < endIndex || sliceCap > item.Cap() { 339 runInfo.err = newStringError(expr, "cap out of range") 340 runInfo.rv = nilValue 341 return 342 } 343 } 344 345 item = item.Slice3(beginIndex, endIndex, sliceCap) 346 347 if !item.CanSet() { 348 runInfo.err = newStringError(expr, "slice cannot be assigned") 349 runInfo.rv = nilValue 350 return 351 } 352 item.Set(value) 353 354 // String 355 case reflect.String: 356 runInfo.err = newStringError(expr, "type string does not support slice operation for assignment") 357 runInfo.rv = nilValue 358 359 default: 360 runInfo.err = newStringError(expr, "type "+item.Kind().String()+" does not support slice operation") 361 runInfo.rv = nilValue 362 } 363 364 // DerefExpr 365 case *ast.DerefExpr: 366 value := runInfo.rv 367 368 runInfo.expr = expr.Expr 369 runInfo.invokeExpr() 370 if runInfo.err != nil { 371 return 372 } 373 374 runInfo.rv.Elem().Set(value) 375 runInfo.rv = value 376 377 default: 378 runInfo.err = newStringError(expr, "invalid operation") 379 runInfo.rv = nilValue 380 } 381 382 }