diff --git a/funcs-math.go b/funcs-math.go new file mode 100644 index 0000000..567adbd --- /dev/null +++ b/funcs-math.go @@ -0,0 +1,139 @@ +// funcs-math.go +package expr + +import ( + "fmt" + "io" +) + +// func addFunc(ctx exprContext, name string, args []any) (result any, err error) { +// var sumAsFloat = false +// var floatSum float64 = 0.0 +// var intSum int64 = 0 + +// for i, v := range args { +// if !isNumber(v) { +// err = fmt.Errorf("add(): param nr %d has wrong type %T, number expected", i+1, v) +// break +// } + +// if !sumAsFloat && isFloat(v) { +// sumAsFloat = true +// floatSum = float64(intSum) +// } +// if sumAsFloat { +// floatSum += numAsFloat(v) +// } else { +// iv, _ := v.(int64) +// intSum += iv +// } +// } +// if err == nil { +// if sumAsFloat { +// result = floatSum +// } else { +// result = intSum +// } +// } +// return +// } + +func checkNumberParamExpected(funcName string, paramValue any, paramPos int) (err error) { + if !(isNumber(paramValue) || isList(paramValue)) { + err = fmt.Errorf("%s(): param nr %d has wrong type %T, number expected", funcName, paramPos+1, paramValue) + } + return +} + +func doAdd(ctx exprContext, name string, it Iterator) (result any, err error) { + var sumAsFloat = false + var floatSum float64 = 0.0 + var intSum int64 = 0 + var v any + + for v, err = it.Next(); err == nil; v, err = it.Next() { + if err = checkNumberParamExpected(name, v, it.Index()); err != nil { + break + } + + if array, ok := v.([]any); ok { + if v, err = doAdd(ctx, name, NewFlatArrayIterator(array)); err != nil { + break + } + } + + if !sumAsFloat && isFloat(v) { + sumAsFloat = true + floatSum = float64(intSum) + } + if sumAsFloat { + floatSum += numAsFloat(v) + } else { + iv, _ := v.(int64) + intSum += iv + } + } + if err == nil || err == io.EOF { + err = nil + if sumAsFloat { + result = floatSum + } else { + result = intSum + } + } + return +} + +func addFunc(ctx exprContext, name string, args []any) (result any, err error) { + result, err = doAdd(ctx, name, NewFlatArrayIterator(args)) + return +} + +func doMul(ctx exprContext, name string, it Iterator) (result any, err error) { + var mulAsFloat = false + var floatProd float64 = 1.0 + var intProd int64 = 1 + var v any + + for v, err = it.Next(); err == nil; v, err = it.Next() { + if err = checkNumberParamExpected(name, v, it.Index()); err != nil { + break + } + + if array, ok := v.([]any); ok { + if v, err = doAdd(ctx, name, NewFlatArrayIterator(array)); err != nil { + break + } + } + + if !mulAsFloat && isFloat(v) { + mulAsFloat = true + floatProd = float64(intProd) + } + if mulAsFloat { + floatProd *= numAsFloat(v) + } else { + iv, _ := v.(int64) + intProd *= iv + } + } + if err == nil || err == io.EOF { + err = nil + if mulAsFloat { + result = floatProd + } else { + result = intProd + } + } + return +} + +func mulFunc(ctx exprContext, name string, args []any) (result any, err error) { + result, err = doMul(ctx, name, NewFlatArrayIterator(args)) + return +} + +func importMathFuncs(ctx exprContext) { + ctx.RegisterFunc("add", addFunc, 0, -1) + ctx.RegisterFunc("mul", mulFunc, 0, -1) +}