github.com/mattn/anko@v0.1.10/vm/vm.go (about) 1 package vm 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "reflect" 8 9 "github.com/mattn/anko/ast" 10 "github.com/mattn/anko/env" 11 ) 12 13 // Options provides options to run VM with 14 type Options struct { 15 Debug bool // run in Debug mode 16 } 17 18 type ( 19 // Error is a VM run error. 20 Error struct { 21 Message string 22 Pos ast.Position 23 } 24 25 // runInfo provides run incoming and outgoing information 26 runInfoStruct struct { 27 // incoming 28 ctx context.Context 29 env *env.Env 30 options *Options 31 stmt ast.Stmt 32 expr ast.Expr 33 operator ast.Operator 34 35 // outgoing 36 rv reflect.Value 37 err error 38 } 39 ) 40 41 var ( 42 nilType = reflect.TypeOf(nil) 43 stringType = reflect.TypeOf("a") 44 byteType = reflect.TypeOf(byte('a')) 45 runeType = reflect.TypeOf('a') 46 interfaceType = reflect.ValueOf([]interface{}{int64(1)}).Index(0).Type() 47 interfaceSliceType = reflect.TypeOf([]interface{}{}) 48 reflectValueType = reflect.TypeOf(reflect.Value{}) 49 errorType = reflect.ValueOf([]error{nil}).Index(0).Type() 50 vmErrorType = reflect.TypeOf(&Error{}) 51 contextType = reflect.TypeOf((*context.Context)(nil)).Elem() 52 53 nilValue = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem() 54 trueValue = reflect.ValueOf(true) 55 falseValue = reflect.ValueOf(false) 56 zeroValue = reflect.Value{} 57 reflectValueNilValue = reflect.ValueOf(nilValue) 58 reflectValueErrorNilValue = reflect.ValueOf(reflect.New(errorType).Elem()) 59 60 errInvalidTypeConversion = fmt.Errorf("invalid type conversion") 61 62 // ErrBreak when there is an unexpected break statement 63 ErrBreak = errors.New("unexpected break statement") 64 // ErrContinue when there is an unexpected continue statement 65 ErrContinue = errors.New("unexpected continue statement") 66 // ErrReturn when there is an unexpected return statement 67 ErrReturn = errors.New("unexpected return statement") 68 // ErrInterrupt when execution has been interrupted 69 ErrInterrupt = errors.New("execution interrupted") 70 ) 71 72 // Error returns the VM error message. 73 func (e *Error) Error() string { 74 return e.Message 75 } 76 77 // newError makes VM error from error 78 func newError(pos ast.Pos, err error) error { 79 if err == nil { 80 return nil 81 } 82 if pos == nil { 83 return &Error{Message: err.Error(), Pos: ast.Position{Line: 1, Column: 1}} 84 } 85 return &Error{Message: err.Error(), Pos: pos.Position()} 86 } 87 88 // newStringError makes VM error from string 89 func newStringError(pos ast.Pos, err string) error { 90 if err == "" { 91 return nil 92 } 93 if pos == nil { 94 return &Error{Message: err, Pos: ast.Position{Line: 1, Column: 1}} 95 } 96 return &Error{Message: err, Pos: pos.Position()} 97 } 98 99 // recoverFunc generic recover function 100 func recoverFunc(runInfo *runInfoStruct) { 101 recoverInterface := recover() 102 if recoverInterface == nil { 103 return 104 } 105 switch value := recoverInterface.(type) { 106 case *Error: 107 runInfo.err = value 108 case error: 109 runInfo.err = value 110 default: 111 runInfo.err = fmt.Errorf("%v", recoverInterface) 112 } 113 } 114 115 func isNil(v reflect.Value) bool { 116 switch v.Kind() { 117 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: 118 // from reflect IsNil: 119 // Note that IsNil is not always equivalent to a regular comparison with nil in Go. 120 // For example, if v was created by calling ValueOf with an uninitialized interface variable i, 121 // i==nil will be true but v.IsNil will panic as v will be the zero Value. 122 return v.IsNil() 123 default: 124 return false 125 } 126 } 127 128 func isNum(v reflect.Value) bool { 129 switch v.Kind() { 130 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 131 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, 132 reflect.Float32, reflect.Float64: 133 return true 134 } 135 return false 136 } 137 138 // equal returns true when lhsV and rhsV is same value. 139 func equal(lhsV, rhsV reflect.Value) bool { 140 lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV) 141 if lhsIsNil && rhsIsNil { 142 return true 143 } 144 if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) { 145 return false 146 } 147 if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr { 148 lhsV = lhsV.Elem() 149 } 150 if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr { 151 rhsV = rhsV.Elem() 152 } 153 154 // Compare a string and a number. 155 // This will attempt to convert the string to a number, 156 // while leaving the other side alone. Code further 157 // down takes care of converting ints and floats as needed. 158 if isNum(lhsV) && rhsV.Kind() == reflect.String { 159 rhsF, err := tryToFloat64(rhsV) 160 if err != nil { 161 // Couldn't convert RHS to a float, they can't be compared. 162 return false 163 } 164 rhsV = reflect.ValueOf(rhsF) 165 } else if lhsV.Kind() == reflect.String && isNum(rhsV) { 166 // If the LHS is a string formatted as an int, try that before trying float 167 lhsI, err := tryToInt64(lhsV) 168 if err != nil { 169 // if LHS is a float, e.g. "1.2", we need to set lhsV to a float64 170 lhsF, err := tryToFloat64(lhsV) 171 if err != nil { 172 return false 173 } 174 lhsV = reflect.ValueOf(lhsF) 175 } else { 176 lhsV = reflect.ValueOf(lhsI) 177 } 178 } 179 180 if isNum(lhsV) && isNum(rhsV) { 181 return fmt.Sprintf("%v", lhsV) == fmt.Sprintf("%v", rhsV) 182 } 183 184 // Try to compare bools to strings and numbers 185 if lhsV.Kind() == reflect.Bool || rhsV.Kind() == reflect.Bool { 186 lhsB, err := tryToBool(lhsV) 187 if err != nil { 188 return false 189 } 190 rhsB, err := tryToBool(rhsV) 191 if err != nil { 192 return false 193 } 194 return lhsB == rhsB 195 } 196 197 return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface()) 198 } 199 200 func getMapIndex(key reflect.Value, aMap reflect.Value) reflect.Value { 201 if aMap.IsNil() { 202 return nilValue 203 } 204 205 var err error 206 key, err = convertReflectValueToType(key, aMap.Type().Key()) 207 if err != nil { 208 return nilValue 209 } 210 211 // From reflect MapIndex: 212 // It returns the zero Value if key is not found in the map or if v represents a nil map. 213 value := aMap.MapIndex(key) 214 if !value.IsValid() { 215 return nilValue 216 } 217 218 if aMap.Type().Elem() == interfaceType && !value.IsNil() { 219 value = reflect.ValueOf(value.Interface()) 220 } 221 222 return value 223 } 224 225 // appendSlice appends rhs to lhs 226 // function assumes lhsV and rhsV are slice or array 227 func appendSlice(expr ast.Expr, lhsV reflect.Value, rhsV reflect.Value) (reflect.Value, error) { 228 lhsT := lhsV.Type().Elem() 229 rhsT := rhsV.Type().Elem() 230 231 if lhsT == rhsT { 232 return reflect.AppendSlice(lhsV, rhsV), nil 233 } 234 235 if rhsT.ConvertibleTo(lhsT) { 236 for i := 0; i < rhsV.Len(); i++ { 237 lhsV = reflect.Append(lhsV, rhsV.Index(i).Convert(lhsT)) 238 } 239 return lhsV, nil 240 } 241 242 leftHasSubArray := lhsT.Kind() == reflect.Slice || lhsT.Kind() == reflect.Array 243 rightHasSubArray := rhsT.Kind() == reflect.Slice || rhsT.Kind() == reflect.Array 244 245 if leftHasSubArray != rightHasSubArray && lhsT != interfaceType && rhsT != interfaceType { 246 return nilValue, newStringError(expr, "invalid type conversion") 247 } 248 249 if !leftHasSubArray && !rightHasSubArray { 250 for i := 0; i < rhsV.Len(); i++ { 251 value := rhsV.Index(i) 252 if rhsT == interfaceType { 253 value = value.Elem() 254 } 255 if lhsT == value.Type() { 256 lhsV = reflect.Append(lhsV, value) 257 } else if value.Type().ConvertibleTo(lhsT) { 258 lhsV = reflect.Append(lhsV, value.Convert(lhsT)) 259 } else { 260 return nilValue, newStringError(expr, "invalid type conversion") 261 } 262 } 263 return lhsV, nil 264 } 265 266 if (leftHasSubArray || lhsT == interfaceType) && (rightHasSubArray || rhsT == interfaceType) { 267 for i := 0; i < rhsV.Len(); i++ { 268 value := rhsV.Index(i) 269 if rhsT == interfaceType { 270 value = value.Elem() 271 if value.Kind() != reflect.Slice && value.Kind() != reflect.Array { 272 return nilValue, newStringError(expr, "invalid type conversion") 273 } 274 } 275 newSlice, err := appendSlice(expr, reflect.MakeSlice(lhsT, 0, value.Len()), value) 276 if err != nil { 277 return nilValue, err 278 } 279 lhsV = reflect.Append(lhsV, newSlice) 280 } 281 return lhsV, nil 282 } 283 284 return nilValue, newStringError(expr, "invalid type conversion") 285 } 286 287 func makeType(runInfo *runInfoStruct, typeStruct *ast.TypeStruct) reflect.Type { 288 switch typeStruct.Kind { 289 case ast.TypeDefault: 290 return getTypeFromEnv(runInfo, typeStruct) 291 case ast.TypePtr: 292 var t reflect.Type 293 if typeStruct.SubType != nil { 294 t = makeType(runInfo, typeStruct.SubType) 295 } else { 296 t = getTypeFromEnv(runInfo, typeStruct) 297 } 298 if runInfo.err != nil { 299 return nil 300 } 301 if t == nil { 302 return nil 303 } 304 return reflect.PtrTo(t) 305 case ast.TypeSlice: 306 var t reflect.Type 307 if typeStruct.SubType != nil { 308 t = makeType(runInfo, typeStruct.SubType) 309 } else { 310 t = getTypeFromEnv(runInfo, typeStruct) 311 } 312 if runInfo.err != nil { 313 return nil 314 } 315 if t == nil { 316 return nil 317 } 318 for i := 1; i < typeStruct.Dimensions; i++ { 319 t = reflect.SliceOf(t) 320 } 321 return reflect.SliceOf(t) 322 case ast.TypeMap: 323 key := makeType(runInfo, typeStruct.Key) 324 if runInfo.err != nil { 325 return nil 326 } 327 if key == nil { 328 return nil 329 } 330 t := makeType(runInfo, typeStruct.SubType) 331 if runInfo.err != nil { 332 return nil 333 } 334 if t == nil { 335 return nil 336 } 337 if !runInfo.options.Debug { 338 // captures panic 339 defer recoverFunc(runInfo) 340 } 341 t = reflect.MapOf(key, t) 342 return t 343 case ast.TypeChan: 344 var t reflect.Type 345 if typeStruct.SubType != nil { 346 t = makeType(runInfo, typeStruct.SubType) 347 } else { 348 t = getTypeFromEnv(runInfo, typeStruct) 349 } 350 if runInfo.err != nil { 351 return nil 352 } 353 if t == nil { 354 return nil 355 } 356 return reflect.ChanOf(reflect.BothDir, t) 357 case ast.TypeStructType: 358 var t reflect.Type 359 fields := make([]reflect.StructField, 0, len(typeStruct.StructNames)) 360 for i := 0; i < len(typeStruct.StructNames); i++ { 361 t = makeType(runInfo, typeStruct.StructTypes[i]) 362 if runInfo.err != nil { 363 return nil 364 } 365 if t == nil { 366 return nil 367 } 368 fields = append(fields, reflect.StructField{Name: typeStruct.StructNames[i], Type: t}) 369 } 370 if !runInfo.options.Debug { 371 // captures panic 372 defer recoverFunc(runInfo) 373 } 374 t = reflect.StructOf(fields) 375 return t 376 default: 377 runInfo.err = fmt.Errorf("unknown kind") 378 return nil 379 } 380 } 381 382 func getTypeFromEnv(runInfo *runInfoStruct, typeStruct *ast.TypeStruct) reflect.Type { 383 var e *env.Env 384 e, runInfo.err = runInfo.env.GetEnvFromPath(typeStruct.Env) 385 if runInfo.err != nil { 386 return nil 387 } 388 389 var t reflect.Type 390 t, runInfo.err = e.Type(typeStruct.Name) 391 return t 392 } 393 394 func makeValue(t reflect.Type) (reflect.Value, error) { 395 switch t.Kind() { 396 case reflect.Chan: 397 return reflect.MakeChan(t, 0), nil 398 case reflect.Func: 399 return reflect.MakeFunc(t, nil), nil 400 case reflect.Map: 401 // note creating slice as work around to create map 402 // just doing MakeMap can give incorrect type for defined types 403 value := reflect.MakeSlice(reflect.SliceOf(t), 0, 1) 404 value = reflect.Append(value, reflect.MakeMap(reflect.MapOf(t.Key(), t.Elem()))) 405 return value.Index(0), nil 406 case reflect.Ptr: 407 ptrV := reflect.New(t.Elem()) 408 v, err := makeValue(t.Elem()) 409 if err != nil { 410 return nilValue, err 411 } 412 413 ptrV.Elem().Set(v) 414 return ptrV, nil 415 case reflect.Slice: 416 return reflect.MakeSlice(t, 0, 0), nil 417 case reflect.Struct: 418 structV := reflect.New(t).Elem() 419 for i := 0; i < structV.NumField(); i++ { 420 if structV.Field(i).Kind() == reflect.Ptr { 421 continue 422 } 423 v, err := makeValue(structV.Field(i).Type()) 424 if err != nil { 425 return nilValue, err 426 } 427 if structV.Field(i).CanSet() { 428 structV.Field(i).Set(v) 429 } 430 } 431 return structV, nil 432 } 433 return reflect.New(t).Elem(), nil 434 } 435 436 // precedenceOfKinds returns the greater of two kinds 437 // string > float > int 438 func precedenceOfKinds(kind1 reflect.Kind, kind2 reflect.Kind) reflect.Kind { 439 if kind1 == kind2 { 440 return kind1 441 } 442 switch kind1 { 443 case reflect.String: 444 return kind1 445 case reflect.Float64, reflect.Float32: 446 switch kind2 { 447 case reflect.String: 448 return kind2 449 } 450 return kind1 451 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 452 switch kind2 { 453 case reflect.String, reflect.Float64, reflect.Float32: 454 return kind2 455 } 456 } 457 return kind1 458 }