├── .gitignore ├── LICENSE ├── README.md ├── eval.go ├── eval_test.go ├── helper.go └── ops.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | .godeps 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Daniel Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # goeval 2 | eval golang code on the fly 3 | -------------------------------------------------------------------------------- /eval.go: -------------------------------------------------------------------------------- 1 | package goeval 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | // "github.com/davecgh/go-spew/spew" 7 | "go/ast" 8 | "go/parser" 9 | "go/token" 10 | "reflect" 11 | "strconv" 12 | ) 13 | 14 | var ( 15 | Builtins = map[string]interface{}{ 16 | "nil": nil, 17 | "true": true, 18 | "false": false, 19 | "append": Append, 20 | "make": Make, 21 | "len": Len, 22 | } 23 | ) 24 | 25 | // variable scope, recursive definition 26 | type Scope struct { 27 | Vals map[string]interface{} // all variables in current scope 28 | Parent *Scope 29 | } 30 | 31 | // create a new variable scope 32 | func NewScope() *Scope { 33 | s := &Scope{ 34 | Vals: map[string]interface{}{}, 35 | } 36 | return s 37 | } 38 | 39 | // search variable from inner-most scope 40 | func (scope *Scope) Get(name string) (val interface{}) { 41 | currentScope := scope 42 | exists := false 43 | for !exists && currentScope != nil { 44 | val, exists = currentScope.Vals[name] 45 | currentScope = currentScope.Parent 46 | } 47 | return 48 | } 49 | 50 | // Set walks the scope and sets a value in a parent scope if it exists, else current. 51 | func (scope *Scope) Set(name string, val interface{}) { 52 | exists := false 53 | currentScope := scope 54 | for !exists && currentScope != nil { 55 | _, exists = currentScope.Vals[name] 56 | if exists { 57 | currentScope.Vals[name] = val 58 | } 59 | currentScope = currentScope.Parent 60 | } 61 | if !exists { 62 | scope.Vals[name] = val 63 | } 64 | } 65 | 66 | // Keys returns all keys in scope 67 | func (scope *Scope) Keys() (keys []string) { 68 | currentScope := scope 69 | for currentScope != nil { 70 | for k := range currentScope.Vals { 71 | keys = append(keys, k) 72 | } 73 | currentScope = scope.Parent 74 | } 75 | return 76 | } 77 | 78 | // NewChild creates a scope under the existing scope. 79 | func (scope *Scope) NewChild() *Scope { 80 | s := NewScope() 81 | s.Parent = scope 82 | return s 83 | } 84 | 85 | // Eval evaluates a string 86 | func (s *Scope) Eval(str string) (interface{}, error) { 87 | expr, err := parser.ParseExpr("func(){" + str + "}()") 88 | if err != nil { 89 | return nil, err 90 | } 91 | return s.Interpret(expr.(*ast.CallExpr).Fun.(*ast.FuncLit).Body) 92 | } 93 | 94 | // Interpret interprets an ast.Node and returns the value. 95 | func (scope *Scope) Interpret(expr ast.Node) (interface{}, error) { 96 | switch e := expr.(type) { 97 | case *ast.Ident: // An Ident node represents an identifier. 98 | typ, err := StringToType(e.Name) 99 | if err == nil { 100 | return typ, err 101 | } 102 | 103 | if obj, exists := Builtins[e.Name]; exists { 104 | return obj, nil 105 | } 106 | 107 | if obj := scope.Get(e.Name); obj != nil { 108 | return obj, nil 109 | } 110 | return nil, fmt.Errorf("can't find EXPR %s", e.Name) 111 | 112 | case *ast.SelectorExpr: // A SelectorExpr node represents an expression followed by a selector. 113 | X, err := scope.Interpret(e.X) 114 | if err != nil { 115 | return nil, err 116 | } 117 | sel := e.Sel 118 | 119 | rVal := reflect.ValueOf(X) 120 | if rVal.Kind() != reflect.Struct && rVal.Kind() != reflect.Ptr { 121 | return nil, fmt.Errorf("%#v is not a struct and thus has no field %#v", X, sel.Name) 122 | } 123 | 124 | if method := rVal.MethodByName(sel.Name); method.IsValid() { 125 | return method.Interface(), nil 126 | } 127 | if rVal.Kind() == reflect.Ptr { 128 | rVal = rVal.Elem() 129 | } 130 | if field := rVal.FieldByName(sel.Name); field.IsValid() { 131 | return field.Interface(), nil 132 | } 133 | return nil, fmt.Errorf("unknown field %#v", sel.Name) 134 | 135 | case *ast.CallExpr: 136 | fun, err := scope.Interpret(e.Fun) 137 | if err != nil { 138 | return nil, err 139 | } 140 | 141 | // make sure fun is a function 142 | rf := reflect.ValueOf(fun) 143 | if rf.Kind() != reflect.Func { 144 | return nil, fmt.Errorf("Not a function %#v", fun) 145 | } 146 | 147 | // interpret args 148 | args := make([]reflect.Value, len(e.Args)) 149 | for i, arg := range e.Args { 150 | interpretedArg, err := scope.Interpret(arg) 151 | if err != nil { 152 | return nil, err 153 | } 154 | args[i] = reflect.ValueOf(interpretedArg) 155 | } 156 | 157 | // call 158 | values := ValuesToInterfaces(rf.Call(args)) 159 | if len(values) == 0 { 160 | return nil, nil 161 | } else if len(values) == 1 { 162 | return values[0], nil 163 | } 164 | err, _ = values[1].(error) 165 | return values[0], err 166 | 167 | case *ast.BasicLit: 168 | switch e.Kind { 169 | case token.INT: 170 | n, err := strconv.ParseInt(e.Value, 0, 64) 171 | return int(n), err 172 | case token.FLOAT, token.IMAG: 173 | return strconv.ParseFloat(e.Value, 64) 174 | case token.CHAR: 175 | return (rune)(e.Value[1]), nil 176 | case token.STRING: 177 | return e.Value[1 : len(e.Value)-1], nil 178 | default: 179 | return nil, fmt.Errorf("unknown basic literal %d", e.Kind) 180 | } 181 | 182 | case *ast.CompositeLit: 183 | typ, err := scope.Interpret(e.Type) 184 | if err != nil { 185 | return nil, err 186 | } 187 | 188 | switch t := e.Type.(type) { 189 | case *ast.ArrayType: 190 | l := len(e.Elts) 191 | slice := reflect.MakeSlice(typ.(reflect.Type), l, l) 192 | for i, elem := range e.Elts { 193 | elemValue, err := scope.Interpret(elem) 194 | if err != nil { 195 | return nil, err 196 | } 197 | slice.Index(i).Set(reflect.ValueOf(elemValue)) 198 | } 199 | return slice.Interface(), nil 200 | 201 | case *ast.MapType: 202 | nMap := reflect.MakeMap(typ.(reflect.Type)) 203 | for _, elem := range e.Elts { 204 | switch eT := elem.(type) { 205 | case *ast.KeyValueExpr: 206 | key, err := scope.Interpret(eT.Key) 207 | if err != nil { 208 | return nil, err 209 | } 210 | val, err := scope.Interpret(eT.Value) 211 | if err != nil { 212 | return nil, err 213 | } 214 | nMap.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(val)) 215 | 216 | default: 217 | return nil, fmt.Errorf("invalid element type %#v to map. Expecting key value pair", eT) 218 | } 219 | } 220 | return nMap.Interface(), nil 221 | 222 | default: 223 | return nil, fmt.Errorf("unknown composite literal %#v", t) 224 | } 225 | 226 | case *ast.BinaryExpr: 227 | x, err := scope.Interpret(e.X) 228 | if err != nil { 229 | return nil, err 230 | } 231 | y, err := scope.Interpret(e.Y) 232 | if err != nil { 233 | return nil, err 234 | } 235 | return ComputeBinaryOp(x, y, e.Op) 236 | 237 | case *ast.UnaryExpr: 238 | x, err := scope.Interpret(e.X) 239 | if err != nil { 240 | return nil, err 241 | } 242 | return ComputeUnaryOp(x, e.Op) 243 | 244 | case *ast.ArrayType: 245 | typ, err := scope.Interpret(e.Elt) 246 | if err != nil { 247 | return nil, err 248 | } 249 | arrType := reflect.SliceOf(typ.(reflect.Type)) 250 | return arrType, nil 251 | 252 | case *ast.MapType: 253 | keyType, err := scope.Interpret(e.Key) 254 | if err != nil { 255 | return nil, err 256 | } 257 | valType, err := scope.Interpret(e.Value) 258 | if err != nil { 259 | return nil, err 260 | } 261 | mapType := reflect.MapOf(keyType.(reflect.Type), valType.(reflect.Type)) 262 | return mapType, nil 263 | 264 | case *ast.ChanType: 265 | typeI, err := scope.Interpret(e.Value) 266 | if err != nil { 267 | return nil, err 268 | } 269 | typ, isType := typeI.(reflect.Type) 270 | if !isType { 271 | return nil, fmt.Errorf("chan needs to be passed a type not %T", typ) 272 | } 273 | return reflect.ChanOf(reflect.BothDir, typ), nil 274 | 275 | case *ast.IndexExpr: 276 | X, err := scope.Interpret(e.X) 277 | if err != nil { 278 | return nil, err 279 | } 280 | i, err := scope.Interpret(e.Index) 281 | if err != nil { 282 | return nil, err 283 | } 284 | xVal := reflect.ValueOf(X) 285 | if reflect.TypeOf(X).Kind() == reflect.Map { 286 | val := xVal.MapIndex(reflect.ValueOf(i)) 287 | if !val.IsValid() { 288 | // If not valid key, return the "zero" type. Eg for int 0, string "" 289 | return reflect.Zero(xVal.Type().Elem()).Interface(), nil 290 | } 291 | return val.Interface(), nil 292 | } 293 | 294 | iVal, isInt := i.(int) 295 | if !isInt { 296 | return nil, fmt.Errorf("index has to be an int not %T", i) 297 | } 298 | if iVal >= xVal.Len() || iVal < 0 { 299 | return nil, errors.New("slice index out of range") 300 | } 301 | return xVal.Index(iVal).Interface(), nil 302 | 303 | case *ast.SliceExpr: 304 | low, err := scope.Interpret(e.Low) 305 | if err != nil { 306 | return nil, err 307 | } 308 | high, err := scope.Interpret(e.High) 309 | if err != nil { 310 | return nil, err 311 | } 312 | X, err := scope.Interpret(e.X) 313 | if err != nil { 314 | return nil, err 315 | } 316 | xVal := reflect.ValueOf(X) 317 | if low == nil { 318 | low = 0 319 | } 320 | if high == nil { 321 | high = xVal.Len() 322 | } 323 | lowVal, isLowInt := low.(int) 324 | highVal, isHighInt := high.(int) 325 | if !isLowInt || !isHighInt { 326 | return nil, fmt.Errorf("slice: indexes have to be an ints not %T and %T", low, high) 327 | } 328 | if lowVal < 0 || highVal >= xVal.Len() { 329 | return nil, errors.New("slice: index out of bounds") 330 | } 331 | return xVal.Slice(lowVal, highVal).Interface(), nil 332 | 333 | case *ast.ParenExpr: 334 | return scope.Interpret(e.X) 335 | 336 | case *ast.ReturnStmt: 337 | results := make([]interface{}, len(e.Results)) 338 | for i, result := range e.Results { 339 | out, err := scope.Interpret(result) 340 | if err != nil { 341 | return out, err 342 | } 343 | results[i] = out 344 | } 345 | 346 | if len(results) == 0 { 347 | return nil, nil 348 | } else if len(results) == 1 { 349 | return results[0], nil 350 | } 351 | return results, nil 352 | 353 | case *ast.AssignStmt: 354 | define := e.Tok == token.DEFINE 355 | lhs := make([]string, len(e.Lhs)) 356 | for i, id := range e.Lhs { 357 | lhsIdent, isIdent := id.(*ast.Ident) 358 | if !isIdent { 359 | return nil, fmt.Errorf("%#v assignment is not ident", id) 360 | } 361 | lhs[i] = lhsIdent.Name 362 | } 363 | rhs := make([]interface{}, len(e.Rhs)) 364 | for i, expr := range e.Rhs { 365 | val, err := scope.Interpret(expr) 366 | if err != nil { 367 | return nil, err 368 | } 369 | rhs[i] = val 370 | } 371 | 372 | if len(rhs) != 1 && len(rhs) != len(lhs) { 373 | return nil, fmt.Errorf("assignment count mismatch: %d = %d", len(lhs), len(rhs)) 374 | } 375 | if len(rhs) == 1 && len(lhs) > 1 && reflect.TypeOf(rhs[0]).Kind() == reflect.Slice { 376 | rhsV := reflect.ValueOf(rhs[0]) 377 | rhsLen := rhsV.Len() 378 | if rhsLen != len(lhs) { 379 | return nil, fmt.Errorf("assignment count mismatch: %d = %d", len(lhs), rhsLen) 380 | } 381 | for i := 0; i < rhsLen; i++ { 382 | variable := lhs[i] 383 | v := scope.Get(variable) 384 | if v == nil && !define { 385 | return nil, fmt.Errorf("variable %#v is not defined", variable) 386 | } 387 | scope.Set(variable, rhsV.Index(i).Interface()) 388 | } 389 | } else { 390 | for i, r := range rhs { 391 | variable := lhs[i] 392 | v := scope.Get(variable) 393 | if v == nil && !define { 394 | return nil, fmt.Errorf("variable %#v is not defined", variable) 395 | } 396 | scope.Set(variable, r) 397 | } 398 | } 399 | 400 | if len(rhs) > 1 { 401 | return rhs, nil 402 | } 403 | return rhs[0], nil 404 | 405 | case *ast.ForStmt: 406 | s := scope.NewChild() 407 | s.Interpret(e.Init) 408 | for { 409 | ok, err := s.Interpret(e.Cond) 410 | if err != nil { 411 | return nil, err 412 | } 413 | if !ok.(bool) { 414 | break 415 | } 416 | s.Interpret(e.Body) 417 | s.Interpret(e.Post) 418 | } 419 | return nil, nil 420 | case *ast.RangeStmt: 421 | s := scope.NewChild() 422 | ranger, err := s.Interpret(e.X) 423 | if err != nil { 424 | return nil, err 425 | } 426 | var key, value string 427 | if e.Key != nil { 428 | key = e.Key.(*ast.Ident).Name 429 | } 430 | if e.Value != nil { 431 | value = e.Value.(*ast.Ident).Name 432 | } 433 | rv := reflect.ValueOf(ranger) 434 | switch rv.Type().Kind() { 435 | case reflect.Array, reflect.Slice: 436 | for i := 0; i < rv.Len(); i++ { 437 | if len(key) > 0 { 438 | s.Set(key, i) 439 | } 440 | if len(value) > 0 { 441 | s.Set(value, rv.Index(i).Interface()) 442 | } 443 | s.Interpret(e.Body) 444 | } 445 | case reflect.Map: 446 | keys := rv.MapKeys() 447 | for _, keyV := range keys { 448 | if len(key) > 0 { 449 | s.Set(key, keyV.Interface()) 450 | } 451 | if len(value) > 0 { 452 | s.Set(value, rv.MapIndex(keyV).Interface()) 453 | } 454 | s.Interpret(e.Body) 455 | } 456 | default: 457 | return nil, fmt.Errorf("ranging on %s is unsupported", rv.Type().Kind().String()) 458 | } 459 | return nil, nil 460 | case *ast.ExprStmt: 461 | return scope.Interpret(e.X) 462 | case *ast.DeclStmt: 463 | return scope.Interpret(e.Decl) 464 | case *ast.GenDecl: 465 | for _, spec := range e.Specs { 466 | if _, err := scope.Interpret(spec); err != nil { 467 | return nil, err 468 | } 469 | } 470 | return nil, nil 471 | case *ast.ValueSpec: 472 | typ, err := scope.Interpret(e.Type) 473 | if err != nil { 474 | return nil, err 475 | } 476 | zero := reflect.Zero(typ.(reflect.Type)).Interface() 477 | for i, name := range e.Names { 478 | if len(e.Values) > i { 479 | v, err := scope.Interpret(e.Values[i]) 480 | if err != nil { 481 | return nil, err 482 | } 483 | scope.Set(name.Name, v) 484 | } else { 485 | scope.Set(name.Name, zero) 486 | } 487 | } 488 | return nil, nil 489 | case *ast.BlockStmt: 490 | var outFinal interface{} 491 | for _, stmts := range e.List { 492 | out, err := scope.Interpret(stmts) 493 | if err != nil { 494 | return out, err 495 | } 496 | outFinal = out 497 | } 498 | return outFinal, nil 499 | 500 | default: 501 | return nil, fmt.Errorf("unknown node %#v", e) 502 | } 503 | } 504 | 505 | // StringToType returns the reflect.Type corresponding to the type string provided. Ex: StringToType("int") 506 | func StringToType(str string) (reflect.Type, error) { 507 | builtinTypes := map[string]reflect.Type{ 508 | "bool": reflect.TypeOf(true), 509 | "byte": reflect.TypeOf(byte(0)), 510 | "rune": reflect.TypeOf(rune(0)), 511 | "string": reflect.TypeOf(""), 512 | "int": reflect.TypeOf(int(0)), 513 | "int8": reflect.TypeOf(int8(0)), 514 | "int16": reflect.TypeOf(int16(0)), 515 | "int32": reflect.TypeOf(int32(0)), 516 | "int64": reflect.TypeOf(int64(0)), 517 | "uint": reflect.TypeOf(uint(0)), 518 | "uint8": reflect.TypeOf(uint8(0)), 519 | "uint16": reflect.TypeOf(uint16(0)), 520 | "uint32": reflect.TypeOf(uint32(0)), 521 | "uint64": reflect.TypeOf(uint64(0)), 522 | "uintptr": reflect.TypeOf(uintptr(0)), 523 | "float32": reflect.TypeOf(float32(0)), 524 | "float64": reflect.TypeOf(float64(0)), 525 | "complex64": reflect.TypeOf(complex64(0)), 526 | "complex128": reflect.TypeOf(complex128(0)), 527 | "error": reflect.TypeOf(errors.New("")), 528 | } 529 | val, present := builtinTypes[str] 530 | if !present { 531 | return nil, fmt.Errorf("type %#v is not in table", str) 532 | } 533 | return val, nil 534 | } 535 | 536 | // ValuesToInterfaces converts a slice of []reflect.Value to []interface{} 537 | func ValuesToInterfaces(vals []reflect.Value) []interface{} { 538 | inters := make([]interface{}, len(vals)) 539 | for i, val := range vals { 540 | inters[i] = val.Interface() 541 | } 542 | return inters 543 | } 544 | -------------------------------------------------------------------------------- /eval_test.go: -------------------------------------------------------------------------------- 1 | package goeval 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestExecute(t *testing.T) { 9 | s := NewScope() 10 | s.Set("print", fmt.Println) 11 | t.Log(s.Eval(`count := 0`)) 12 | t.Log(s.Eval(`for i:=0;i<100;i=i+1 { 13 | count=count+i 14 | }`)) 15 | t.Log(s.Eval(`print(count)`)) 16 | } 17 | -------------------------------------------------------------------------------- /helper.go: -------------------------------------------------------------------------------- 1 | package goeval 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | // Append is a runtime replacement for the append function 10 | func Append(arr interface{}, elems ...interface{}) (interface{}, error) { 11 | arrVal := reflect.ValueOf(arr) 12 | valArr := make([]reflect.Value, len(elems)) 13 | for i, elem := range elems { 14 | if reflect.TypeOf(arr) != reflect.SliceOf(reflect.TypeOf(elem)) { 15 | return nil, fmt.Errorf("%T cannot append to %T", elem, arr) 16 | } 17 | valArr[i] = reflect.ValueOf(elem) 18 | } 19 | return reflect.Append(arrVal, valArr...).Interface(), nil 20 | } 21 | 22 | // Make is a runtime replacement for the make function 23 | func Make(t interface{}, args ...interface{}) (interface{}, error) { 24 | typ, isType := t.(reflect.Type) 25 | if !isType { 26 | return nil, fmt.Errorf("invalid type %#v", t) 27 | } 28 | switch typ.Kind() { 29 | case reflect.Slice: 30 | if len(args) < 1 || len(args) > 2 { 31 | return nil, errors.New("invalid number of arguments. Missing len or extra?") 32 | } 33 | length, isInt := args[0].(int) 34 | if !isInt { 35 | return nil, errors.New("len is not int") 36 | } 37 | capacity := length 38 | if len(args) == 2 { 39 | capacity, isInt = args[0].(int) 40 | if !isInt { 41 | return nil, errors.New("len is not int") 42 | } 43 | } 44 | slice := reflect.MakeSlice(typ, length, capacity) 45 | return slice.Interface(), nil 46 | 47 | case reflect.Chan: 48 | if len(args) > 1 { 49 | fmt.Printf("CHAN ARGS %#v", args) 50 | return nil, errors.New("too many arguments") 51 | } 52 | size := 0 53 | if len(args) == 1 { 54 | var isInt bool 55 | size, isInt = args[0].(int) 56 | if !isInt { 57 | return nil, errors.New("size is not int") 58 | } 59 | } 60 | buffer := reflect.MakeChan(typ, size) 61 | return buffer.Interface(), nil 62 | 63 | default: 64 | return nil, fmt.Errorf("unknown kind type %T", t) 65 | } 66 | } 67 | 68 | // Len is a runtime replacement for the len function 69 | func Len(t interface{}) (interface{}, error) { 70 | return reflect.ValueOf(t).Len(), nil 71 | } 72 | -------------------------------------------------------------------------------- /ops.go: -------------------------------------------------------------------------------- 1 | package goeval 2 | 3 | import ( 4 | "fmt" 5 | "go/token" 6 | "reflect" 7 | ) 8 | 9 | // ComputeBinaryOp executes the corresponding binary operation (+, -, etc) on two interfaces. 10 | func ComputeBinaryOp(xI, yI interface{}, op token.Token) (interface{}, error) { 11 | typeX := reflect.TypeOf(xI) 12 | typeY := reflect.TypeOf(yI) 13 | if typeX == typeY { 14 | switch xI.(type) { 15 | case string: 16 | x := xI.(string) 17 | y := yI.(string) 18 | switch op { 19 | case token.ADD: 20 | return x + y, nil 21 | } 22 | case int: 23 | x := xI.(int) 24 | y := yI.(int) 25 | switch op { 26 | case token.ADD: 27 | return x + y, nil 28 | case token.SUB: 29 | return x - y, nil 30 | case token.MUL: 31 | return x * y, nil 32 | case token.QUO: 33 | return x / y, nil 34 | case token.REM: 35 | return x % y, nil 36 | case token.AND: 37 | return x & y, nil 38 | case token.OR: 39 | return x | y, nil 40 | case token.XOR: 41 | return x ^ y, nil 42 | case token.AND_NOT: 43 | return x &^ y, nil 44 | case token.LSS: 45 | return x < y, nil 46 | case token.GTR: 47 | return x > y, nil 48 | case token.LEQ: 49 | return x <= y, nil 50 | case token.GEQ: 51 | return x >= y, nil 52 | } 53 | case int8: 54 | x := xI.(int8) 55 | y := yI.(int8) 56 | switch op { 57 | case token.ADD: 58 | return x + y, nil 59 | case token.SUB: 60 | return x - y, nil 61 | case token.MUL: 62 | return x * y, nil 63 | case token.QUO: 64 | return x / y, nil 65 | case token.REM: 66 | return x % y, nil 67 | case token.AND: 68 | return x & y, nil 69 | case token.OR: 70 | return x | y, nil 71 | case token.XOR: 72 | return x ^ y, nil 73 | case token.AND_NOT: 74 | return x &^ y, nil 75 | case token.LSS: 76 | return x < y, nil 77 | case token.GTR: 78 | return x > y, nil 79 | case token.LEQ: 80 | return x <= y, nil 81 | case token.GEQ: 82 | return x >= y, nil 83 | } 84 | case int16: 85 | x := xI.(int16) 86 | y := yI.(int16) 87 | switch op { 88 | case token.ADD: 89 | return x + y, nil 90 | case token.SUB: 91 | return x - y, nil 92 | case token.MUL: 93 | return x * y, nil 94 | case token.QUO: 95 | return x / y, nil 96 | case token.REM: 97 | return x % y, nil 98 | case token.AND: 99 | return x & y, nil 100 | case token.OR: 101 | return x | y, nil 102 | case token.XOR: 103 | return x ^ y, nil 104 | case token.AND_NOT: 105 | return x &^ y, nil 106 | case token.LSS: 107 | return x < y, nil 108 | case token.GTR: 109 | return x > y, nil 110 | case token.LEQ: 111 | return x <= y, nil 112 | case token.GEQ: 113 | return x >= y, nil 114 | } 115 | case int32: 116 | x := xI.(int32) 117 | y := yI.(int32) 118 | switch op { 119 | case token.ADD: 120 | return x + y, nil 121 | case token.SUB: 122 | return x - y, nil 123 | case token.MUL: 124 | return x * y, nil 125 | case token.QUO: 126 | return x / y, nil 127 | case token.REM: 128 | return x % y, nil 129 | case token.AND: 130 | return x & y, nil 131 | case token.OR: 132 | return x | y, nil 133 | case token.XOR: 134 | return x ^ y, nil 135 | case token.AND_NOT: 136 | return x &^ y, nil 137 | case token.LSS: 138 | return x < y, nil 139 | case token.GTR: 140 | return x > y, nil 141 | case token.LEQ: 142 | return x <= y, nil 143 | case token.GEQ: 144 | return x >= y, nil 145 | } 146 | case int64: 147 | x := xI.(int64) 148 | y := yI.(int64) 149 | switch op { 150 | case token.ADD: 151 | return x + y, nil 152 | case token.SUB: 153 | return x - y, nil 154 | case token.MUL: 155 | return x * y, nil 156 | case token.QUO: 157 | return x / y, nil 158 | case token.REM: 159 | return x % y, nil 160 | case token.AND: 161 | return x & y, nil 162 | case token.OR: 163 | return x | y, nil 164 | case token.XOR: 165 | return x ^ y, nil 166 | case token.AND_NOT: 167 | return x &^ y, nil 168 | case token.LSS: 169 | return x < y, nil 170 | case token.GTR: 171 | return x > y, nil 172 | case token.LEQ: 173 | return x <= y, nil 174 | case token.GEQ: 175 | return x >= y, nil 176 | } 177 | case uint: 178 | x := xI.(uint) 179 | y := yI.(uint) 180 | switch op { 181 | case token.ADD: 182 | return x + y, nil 183 | case token.SUB: 184 | return x - y, nil 185 | case token.MUL: 186 | return x * y, nil 187 | case token.QUO: 188 | return x / y, nil 189 | case token.REM: 190 | return x % y, nil 191 | case token.AND: 192 | return x & y, nil 193 | case token.OR: 194 | return x | y, nil 195 | case token.XOR: 196 | return x ^ y, nil 197 | case token.AND_NOT: 198 | return x &^ y, nil 199 | case token.LSS: 200 | return x < y, nil 201 | case token.GTR: 202 | return x > y, nil 203 | case token.LEQ: 204 | return x <= y, nil 205 | case token.GEQ: 206 | return x >= y, nil 207 | } 208 | case uint8: 209 | x := xI.(uint8) 210 | y := yI.(uint8) 211 | switch op { 212 | case token.ADD: 213 | return x + y, nil 214 | case token.SUB: 215 | return x - y, nil 216 | case token.MUL: 217 | return x * y, nil 218 | case token.QUO: 219 | return x / y, nil 220 | case token.REM: 221 | return x % y, nil 222 | case token.AND: 223 | return x & y, nil 224 | case token.OR: 225 | return x | y, nil 226 | case token.XOR: 227 | return x ^ y, nil 228 | case token.AND_NOT: 229 | return x &^ y, nil 230 | case token.LSS: 231 | return x < y, nil 232 | case token.GTR: 233 | return x > y, nil 234 | case token.LEQ: 235 | return x <= y, nil 236 | case token.GEQ: 237 | return x >= y, nil 238 | } 239 | case uint16: 240 | x := xI.(uint16) 241 | y := yI.(uint16) 242 | switch op { 243 | case token.ADD: 244 | return x + y, nil 245 | case token.SUB: 246 | return x - y, nil 247 | case token.MUL: 248 | return x * y, nil 249 | case token.QUO: 250 | return x / y, nil 251 | case token.REM: 252 | return x % y, nil 253 | case token.AND: 254 | return x & y, nil 255 | case token.OR: 256 | return x | y, nil 257 | case token.XOR: 258 | return x ^ y, nil 259 | case token.AND_NOT: 260 | return x &^ y, nil 261 | case token.LSS: 262 | return x < y, nil 263 | case token.GTR: 264 | return x > y, nil 265 | case token.LEQ: 266 | return x <= y, nil 267 | case token.GEQ: 268 | return x >= y, nil 269 | } 270 | case uint32: 271 | x := xI.(uint32) 272 | y := yI.(uint32) 273 | switch op { 274 | case token.ADD: 275 | return x + y, nil 276 | case token.SUB: 277 | return x - y, nil 278 | case token.MUL: 279 | return x * y, nil 280 | case token.QUO: 281 | return x / y, nil 282 | case token.REM: 283 | return x % y, nil 284 | case token.AND: 285 | return x & y, nil 286 | case token.OR: 287 | return x | y, nil 288 | case token.XOR: 289 | return x ^ y, nil 290 | case token.AND_NOT: 291 | return x &^ y, nil 292 | case token.LSS: 293 | return x < y, nil 294 | case token.GTR: 295 | return x > y, nil 296 | case token.LEQ: 297 | return x <= y, nil 298 | case token.GEQ: 299 | return x >= y, nil 300 | } 301 | case uint64: 302 | x := xI.(uint64) 303 | y := yI.(uint64) 304 | switch op { 305 | case token.ADD: 306 | return x + y, nil 307 | case token.SUB: 308 | return x - y, nil 309 | case token.MUL: 310 | return x * y, nil 311 | case token.QUO: 312 | return x / y, nil 313 | case token.REM: 314 | return x % y, nil 315 | case token.AND: 316 | return x & y, nil 317 | case token.OR: 318 | return x | y, nil 319 | case token.XOR: 320 | return x ^ y, nil 321 | case token.AND_NOT: 322 | return x &^ y, nil 323 | case token.LSS: 324 | return x < y, nil 325 | case token.GTR: 326 | return x > y, nil 327 | case token.LEQ: 328 | return x <= y, nil 329 | case token.GEQ: 330 | return x >= y, nil 331 | } 332 | case uintptr: 333 | x := xI.(uintptr) 334 | y := yI.(uintptr) 335 | switch op { 336 | case token.ADD: 337 | return x + y, nil 338 | case token.SUB: 339 | return x - y, nil 340 | case token.MUL: 341 | return x * y, nil 342 | case token.QUO: 343 | return x / y, nil 344 | case token.REM: 345 | return x % y, nil 346 | case token.AND: 347 | return x & y, nil 348 | case token.OR: 349 | return x | y, nil 350 | case token.XOR: 351 | return x ^ y, nil 352 | case token.AND_NOT: 353 | return x &^ y, nil 354 | case token.LSS: 355 | return x < y, nil 356 | case token.GTR: 357 | return x > y, nil 358 | case token.LEQ: 359 | return x <= y, nil 360 | case token.GEQ: 361 | return x >= y, nil 362 | } 363 | case complex64: 364 | x := xI.(complex64) 365 | y := yI.(complex64) 366 | switch op { 367 | case token.ADD: 368 | return x + y, nil 369 | case token.SUB: 370 | return x - y, nil 371 | case token.MUL: 372 | return x * y, nil 373 | case token.QUO: 374 | return x / y, nil 375 | } 376 | case complex128: 377 | x := xI.(complex128) 378 | y := yI.(complex128) 379 | switch op { 380 | case token.ADD: 381 | return x + y, nil 382 | case token.SUB: 383 | return x - y, nil 384 | case token.MUL: 385 | return x * y, nil 386 | case token.QUO: 387 | return x / y, nil 388 | } 389 | case float32: 390 | x := xI.(float32) 391 | y := yI.(float32) 392 | switch op { 393 | case token.ADD: 394 | return x + y, nil 395 | case token.SUB: 396 | return x - y, nil 397 | case token.MUL: 398 | return x * y, nil 399 | case token.QUO: 400 | return x / y, nil 401 | case token.LSS: 402 | return x < y, nil 403 | case token.GTR: 404 | return x > y, nil 405 | case token.LEQ: 406 | return x <= y, nil 407 | case token.GEQ: 408 | return x >= y, nil 409 | } 410 | case float64: 411 | x := xI.(float64) 412 | y := yI.(float64) 413 | switch op { 414 | case token.ADD: 415 | return x + y, nil 416 | case token.SUB: 417 | return x - y, nil 418 | case token.MUL: 419 | return x * y, nil 420 | case token.QUO: 421 | return x / y, nil 422 | case token.LSS: 423 | return x < y, nil 424 | case token.GTR: 425 | return x > y, nil 426 | case token.LEQ: 427 | return x <= y, nil 428 | case token.GEQ: 429 | return x >= y, nil 430 | } 431 | case bool: 432 | x := xI.(bool) 433 | y := yI.(bool) 434 | switch op { 435 | // Bool 436 | case token.LAND: 437 | return x && y, nil 438 | case token.LOR: 439 | return x || y, nil 440 | } 441 | } 442 | } 443 | yUint, isUint := yI.(uint64) 444 | if !isUint { 445 | isUint = true 446 | switch yV := yI.(type) { 447 | case int: 448 | yUint = uint64(yV) 449 | case int8: 450 | yUint = uint64(yV) 451 | case int16: 452 | yUint = uint64(yV) 453 | case int32: 454 | yUint = uint64(yV) 455 | case int64: 456 | yUint = uint64(yV) 457 | case uint8: 458 | yUint = uint64(yV) 459 | case uint16: 460 | yUint = uint64(yV) 461 | case uint32: 462 | yUint = uint64(yV) 463 | case uint64: 464 | yUint = uint64(yV) 465 | case float32: 466 | yUint = uint64(yV) 467 | case float64: 468 | yUint = uint64(yV) 469 | default: 470 | isUint = false 471 | } 472 | } 473 | if isUint { 474 | switch xI.(type) { 475 | case int: 476 | x := xI.(int) 477 | switch op { 478 | // Num, uint 479 | case token.SHL: 480 | return x << yUint, nil 481 | case token.SHR: 482 | return x >> yUint, nil 483 | } 484 | case int8: 485 | x := xI.(int8) 486 | switch op { 487 | // Num, uint 488 | case token.SHL: 489 | return x << yUint, nil 490 | case token.SHR: 491 | return x >> yUint, nil 492 | } 493 | case int16: 494 | x := xI.(int16) 495 | switch op { 496 | // Num, uint 497 | case token.SHL: 498 | return x << yUint, nil 499 | case token.SHR: 500 | return x >> yUint, nil 501 | } 502 | case int32: 503 | x := xI.(int32) 504 | switch op { 505 | // Num, uint 506 | case token.SHL: 507 | return x << yUint, nil 508 | case token.SHR: 509 | return x >> yUint, nil 510 | } 511 | case int64: 512 | x := xI.(int64) 513 | switch op { 514 | // Num, uint 515 | case token.SHL: 516 | return x << yUint, nil 517 | case token.SHR: 518 | return x >> yUint, nil 519 | } 520 | case uint: 521 | x := xI.(uint) 522 | switch op { 523 | // Num, uint 524 | case token.SHL: 525 | return x << yUint, nil 526 | case token.SHR: 527 | return x >> yUint, nil 528 | } 529 | case uint8: 530 | x := xI.(uint8) 531 | switch op { 532 | // Num, uint 533 | case token.SHL: 534 | return x << yUint, nil 535 | case token.SHR: 536 | return x >> yUint, nil 537 | } 538 | case uint16: 539 | x := xI.(uint16) 540 | switch op { 541 | // Num, uint 542 | case token.SHL: 543 | return x << yUint, nil 544 | case token.SHR: 545 | return x >> yUint, nil 546 | } 547 | case uint32: 548 | x := xI.(uint32) 549 | switch op { 550 | // Num, uint 551 | case token.SHL: 552 | return x << yUint, nil 553 | case token.SHR: 554 | return x >> yUint, nil 555 | } 556 | case uint64: 557 | x := xI.(uint64) 558 | switch op { 559 | // Num, uint 560 | case token.SHL: 561 | return x << yUint, nil 562 | case token.SHR: 563 | return x >> yUint, nil 564 | } 565 | case uintptr: 566 | x := xI.(uintptr) 567 | switch op { 568 | // Num, uint 569 | case token.SHL: 570 | return x << yUint, nil 571 | case token.SHR: 572 | return x >> yUint, nil 573 | } 574 | } 575 | } 576 | // Anything 577 | switch op { 578 | case token.EQL: 579 | return xI == yI, nil 580 | case token.NEQ: 581 | return xI != yI, nil 582 | } 583 | return nil, fmt.Errorf("unknown operation %#v between %#v and %#v", op, xI, yI) 584 | } 585 | 586 | // ComputeUnaryOp computes the corresponding unary (+x, -x) operation on an interface. 587 | func ComputeUnaryOp(xI interface{}, op token.Token) (interface{}, error) { 588 | switch xI.(type) { 589 | case bool: 590 | x := xI.(bool) 591 | switch op { 592 | case token.NOT: 593 | return !x, nil 594 | } 595 | case int: 596 | x := xI.(int) 597 | switch op { 598 | case token.ADD: 599 | return +x, nil 600 | case token.SUB: 601 | return -x, nil 602 | } 603 | case int8: 604 | x := xI.(int8) 605 | switch op { 606 | case token.ADD: 607 | return +x, nil 608 | case token.SUB: 609 | return -x, nil 610 | } 611 | case int16: 612 | x := xI.(int16) 613 | switch op { 614 | case token.ADD: 615 | return +x, nil 616 | case token.SUB: 617 | return -x, nil 618 | } 619 | case int32: 620 | x := xI.(int32) 621 | switch op { 622 | case token.ADD: 623 | return +x, nil 624 | case token.SUB: 625 | return -x, nil 626 | } 627 | case int64: 628 | x := xI.(int64) 629 | switch op { 630 | case token.ADD: 631 | return +x, nil 632 | case token.SUB: 633 | return -x, nil 634 | } 635 | case uint: 636 | x := xI.(uint) 637 | switch op { 638 | case token.ADD: 639 | return +x, nil 640 | case token.SUB: 641 | return -x, nil 642 | } 643 | case uint8: 644 | x := xI.(uint8) 645 | switch op { 646 | case token.ADD: 647 | return +x, nil 648 | case token.SUB: 649 | return -x, nil 650 | } 651 | case uint16: 652 | x := xI.(uint16) 653 | switch op { 654 | case token.ADD: 655 | return +x, nil 656 | case token.SUB: 657 | return -x, nil 658 | } 659 | case uint32: 660 | x := xI.(uint32) 661 | switch op { 662 | case token.ADD: 663 | return +x, nil 664 | case token.SUB: 665 | return -x, nil 666 | } 667 | case uint64: 668 | x := xI.(uint64) 669 | switch op { 670 | case token.ADD: 671 | return +x, nil 672 | case token.SUB: 673 | return -x, nil 674 | } 675 | case uintptr: 676 | x := xI.(uintptr) 677 | switch op { 678 | case token.ADD: 679 | return +x, nil 680 | case token.SUB: 681 | return -x, nil 682 | } 683 | case float32: 684 | x := xI.(float32) 685 | switch op { 686 | case token.ADD: 687 | return +x, nil 688 | case token.SUB: 689 | return -x, nil 690 | } 691 | case float64: 692 | x := xI.(float64) 693 | switch op { 694 | case token.ADD: 695 | return +x, nil 696 | case token.SUB: 697 | return -x, nil 698 | } 699 | case complex64: 700 | x := xI.(complex64) 701 | switch op { 702 | case token.ADD: 703 | return +x, nil 704 | case token.SUB: 705 | return -x, nil 706 | } 707 | case complex128: 708 | x := xI.(complex128) 709 | switch op { 710 | case token.ADD: 711 | return +x, nil 712 | case token.SUB: 713 | return -x, nil 714 | } 715 | } 716 | return nil, fmt.Errorf("unknown unary operation %#v on %#v", op, xI) 717 | } 718 | --------------------------------------------------------------------------------