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  }