// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // utils.go package expr import ( "fmt" "reflect" ) func isString(v any) (ok bool) { _, ok = v.(string) return ok } func isInteger(v any) (ok bool) { _, ok = v.(int64) return ok } func isFloat(v any) (ok bool) { _, ok = v.(float64) return ok } func isList(v any) (ok bool) { _, ok = v.([]any) return ok } func isDict(v any) (ok bool) { _, ok = v.(map[any]any) return ok } func isNumber(v any) (ok bool) { return isFloat(v) || isInteger(v) } func isNumberString(v any) (ok bool) { return isString(v) || isNumber(v) } func isFunctor(v any) (ok bool) { _, ok = v.(Functor) return } func isIterator(v any) (ok bool) { _, ok = v.(Iterator) return } func numAsFloat(v any) (f float64) { var ok bool if f, ok = v.(float64); !ok { i, _ := v.(int64) f = float64(i) } return } func toBool(v any) (b bool, ok bool) { ok = true switch x := v.(type) { case string: b = len(x) > 0 case float64: b = x != 0.0 case int64: b = x != 0 case bool: b = x default: ok = false } return } func isFunc(v any) bool { return reflect.TypeOf(v).Kind() == reflect.Func } func anyInteger(v any) (i int64, ok bool) { ok = true switch intval := v.(type) { case int: i = int64(intval) case uint8: i = int64(intval) case uint16: i = int64(intval) case uint64: i = int64(intval) case uint32: i = int64(intval) case int8: i = int64(intval) case int16: i = int64(intval) case int32: i = int64(intval) case int64: i = intval default: ok = false } return } func fromGenericAny(v any) (exprAny any, ok bool) { if exprAny, ok = v.(bool); ok { return } if exprAny, ok = v.(string); ok { return } if exprAny, ok = anyInteger(v); ok { return } if exprAny, ok = anyFloat(v); ok { return } return } func anyFloat(v any) (float float64, ok bool) { ok = true switch floatval := v.(type) { case float32: float = float64(floatval) case float64: float = floatval default: ok = false } return } func CopyMap[K comparable, V any](dest, source map[K]V) map[K]V { for k, v := range source { dest[k] = v } return dest } func CloneMap[K comparable, V any](source map[K]V) map[K]V { dest := make(map[K]V, len(source)) return CopyMap(dest, source) } func CopyFilteredMap[K comparable, V any](dest, source map[K]V, filter func(key K) (accept bool)) map[K]V { // fmt.Printf("--- Clone with filter %p\n", filter) if filter == nil { return CopyMap(dest, source) } else { for k, v := range source { if filter(k) { // fmt.Printf("\tClone var %q\n", k) dest[k] = v } } } return dest } func CloneFilteredMap[K comparable, V any](source map[K]V, filter func(key K) (accept bool)) map[K]V { dest := make(map[K]V, len(source)) return CopyFilteredMap(dest, source, filter) } func toInt(value any, description string) (i int, err error) { if valueInt64, ok := value.(int64); ok { i = int(valueInt64) } else { err = fmt.Errorf("%s expected integer, got %T (%v)", description, value, value) } return }