expr/utils.go

189 lines
3.2 KiB
Go

// 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.(*ListType)
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 isNumOrFract(v any) (ok bool) {
return isFloat(v) || isInteger(v) || isFraction(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 {
if fract, ok := v.(*fraction); ok {
f = fract.toFloat()
} else {
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
}