github.com/expr-lang/expr@v1.16.9/builtin/utils.go (about) 1 package builtin 2 3 import ( 4 "fmt" 5 "reflect" 6 "time" 7 ) 8 9 var ( 10 anyType = reflect.TypeOf(new(any)).Elem() 11 integerType = reflect.TypeOf(0) 12 floatType = reflect.TypeOf(float64(0)) 13 arrayType = reflect.TypeOf([]any{}) 14 mapType = reflect.TypeOf(map[any]any{}) 15 timeType = reflect.TypeOf(new(time.Time)).Elem() 16 locationType = reflect.TypeOf(new(time.Location)) 17 ) 18 19 func kind(t reflect.Type) reflect.Kind { 20 if t == nil { 21 return reflect.Invalid 22 } 23 return t.Kind() 24 } 25 26 func types(types ...any) []reflect.Type { 27 ts := make([]reflect.Type, len(types)) 28 for i, t := range types { 29 t := reflect.TypeOf(t) 30 if t.Kind() == reflect.Ptr { 31 t = t.Elem() 32 } 33 if t.Kind() != reflect.Func { 34 panic("not a function") 35 } 36 ts[i] = t 37 } 38 return ts 39 } 40 41 func toInt(val any) (int, error) { 42 switch v := val.(type) { 43 case int: 44 return v, nil 45 case int8: 46 return int(v), nil 47 case int16: 48 return int(v), nil 49 case int32: 50 return int(v), nil 51 case int64: 52 return int(v), nil 53 case uint: 54 return int(v), nil 55 case uint8: 56 return int(v), nil 57 case uint16: 58 return int(v), nil 59 case uint32: 60 return int(v), nil 61 case uint64: 62 return int(v), nil 63 default: 64 return 0, fmt.Errorf("cannot use %T as argument (type int)", val) 65 } 66 } 67 68 func bitFunc(name string, fn func(x, y int) (any, error)) *Function { 69 return &Function{ 70 Name: name, 71 Func: func(args ...any) (any, error) { 72 if len(args) != 2 { 73 return nil, fmt.Errorf("invalid number of arguments for %s (expected 2, got %d)", name, len(args)) 74 } 75 x, err := toInt(args[0]) 76 if err != nil { 77 return nil, fmt.Errorf("%v to call %s", err, name) 78 } 79 y, err := toInt(args[1]) 80 if err != nil { 81 return nil, fmt.Errorf("%v to call %s", err, name) 82 } 83 return fn(x, y) 84 }, 85 Types: types(new(func(int, int) int)), 86 } 87 }