The plus and minus operators now support lists for join and difference respectively
This commit is contained in:
parent
f540ec28e8
commit
85fb007a2b
@ -6,6 +6,7 @@ package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
//-------- plus term
|
||||
@ -39,6 +40,23 @@ func evalPlus(ctx exprContext, self *term) (v any, err error) {
|
||||
rightInt, _ := rightValue.(int64)
|
||||
v = leftInt + rightInt
|
||||
}
|
||||
} else if isList(leftValue) || isList(rightValue) {
|
||||
var leftList, rightList []any
|
||||
var ok bool
|
||||
if leftList, ok = leftValue.([]any); !ok {
|
||||
leftList = []any{leftValue}
|
||||
}
|
||||
if rightList, ok = rightValue.([]any); !ok {
|
||||
rightList = []any{rightValue}
|
||||
}
|
||||
sumList := make([]any, 0, len(leftList)+len(rightList))
|
||||
for _, item := range leftList {
|
||||
sumList = append(sumList, item)
|
||||
}
|
||||
for _, item := range rightList {
|
||||
sumList = append(sumList, item)
|
||||
}
|
||||
v = sumList
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
@ -74,6 +92,16 @@ func evalMinus(ctx exprContext, self *term) (v any, err error) {
|
||||
rightInt, _ := rightValue.(int64)
|
||||
v = leftInt - rightInt
|
||||
}
|
||||
} else if isList(leftValue) && isList(rightValue) {
|
||||
leftList, _ := leftValue.([]any)
|
||||
rightList, _ := rightValue.([]any)
|
||||
diffList := make([]any, 0, len(leftList)-len(rightList))
|
||||
for _, item := range leftList {
|
||||
if slices.Index(rightList, item) < 0 {
|
||||
diffList = append(diffList, item)
|
||||
}
|
||||
}
|
||||
v = diffList
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
|
@ -11,38 +11,6 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
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 TestParser(t *testing.T) {
|
||||
type inputType struct {
|
||||
source string
|
||||
@ -54,7 +22,8 @@ func TestParser(t *testing.T) {
|
||||
ctx := NewSimpleFuncStore()
|
||||
ctx.SetValue("var1", int64(123))
|
||||
ctx.SetValue("var2", "abc")
|
||||
ctx.addFunc("add", addFunc)
|
||||
// ctx.addFunc("add", addFunc)
|
||||
importMathFuncs(ctx)
|
||||
|
||||
// inputs1 := []inputType{
|
||||
// {`add(1,2,3)`, int64(6), nil},
|
||||
@ -94,10 +63,10 @@ func TestParser(t *testing.T) {
|
||||
/* 31 */ {"(1+1)*5", int64(10), nil},
|
||||
/* 32 */ {"200 / (1+1) - 1", int64(99), nil},
|
||||
/* 33 */ {`add(1,2,3)`, int64(6), nil},
|
||||
/* 34 */ {`mul(1,2,3)`, nil, errors.New(`unknown function "mul"`)},
|
||||
/* 34 */ {`mulX(1,2,3)`, nil, errors.New(`unknown function mulX()`)},
|
||||
/* 35 */ {`add(1+4,3+2,5*(3-2))`, int64(15), nil},
|
||||
/* 36 */ {`add(add(1+4),3+2,5*(3-2))`, int64(15), nil},
|
||||
/* 37 */ {`add(add(1+4),/*3+2,*/5*(3-2))`, int64(10), nil},
|
||||
/* 37 */ {`add(add(1,4),/*3+2,*/5*(3-2))`, int64(10), nil},
|
||||
/* 38 */ {`1+(1+(1+(1)+1)+1)+1`, int64(7), nil},
|
||||
/* 39 */ {`(((1)))`, int64(1), nil},
|
||||
/* 40 */ {`"uno_" + var2`, `uno_abc`, nil},
|
||||
@ -209,7 +178,8 @@ func TestListParser(t *testing.T) {
|
||||
ctx := NewSimpleFuncStore()
|
||||
ctx.SetValue("var1", int64(123))
|
||||
ctx.SetValue("var2", "abc")
|
||||
ctx.addFunc("add", addFunc)
|
||||
// ctx.addFunc("add", addFunc)
|
||||
importMathFuncs(ctx)
|
||||
|
||||
// inputs1 := []inputType{
|
||||
// {`add(1,2,3)`, int64(6), nil},
|
||||
@ -220,6 +190,14 @@ func TestListParser(t *testing.T) {
|
||||
/* 2 */ {`[1,2,3]`, []any{int64(1), int64(2), int64(3)}, nil},
|
||||
/* 3 */ {`[1,2,"hello"]`, []any{int64(1), int64(2), "hello"}, nil},
|
||||
/* 4 */ {`[1+2, not true, "hello"]`, []any{int64(3), false, "hello"}, nil},
|
||||
/* 5 */ {`[1,2]+[3]`, []any{int64(1), int64(2), int64(3)}, nil},
|
||||
/* 6 */ {`[1,4,3,2]-[3]`, []any{int64(1), int64(4), int64(2)}, nil},
|
||||
/* 7 */ {`add([1,4,3,2])`, int64(10), nil},
|
||||
/* 8 */ {`add([1,[2,2],3,2])`, int64(10), nil},
|
||||
/* 9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil},
|
||||
/* 10 */ {`add([1,"hello"])`, nil, errors.New(`add(): param nr 2 has wrong type string, number expected`)},
|
||||
// /* 8 */ {`[int(x)|x=csv("test.csv",1,all(),1)]`, []any{int64(10), int64(40), int64(20)}, nil},
|
||||
// /* 9 */ {`sum(@[int(x)|x=csv("test.csv",1,all(),1)])`, []any{int64(10), int64(40), int64(20)}, nil},
|
||||
}
|
||||
|
||||
succeeded := 0
|
||||
@ -232,9 +210,9 @@ func TestListParser(t *testing.T) {
|
||||
var gotErr error
|
||||
|
||||
if input.wantErr == nil {
|
||||
t.Log(fmt.Sprintf("[+]Test nr %2d -- %q", i+1, input.source))
|
||||
t.Log(fmt.Sprintf("[+]Test nr %2d -- %q --> %v", i+1, input.source, input.wantResult))
|
||||
} else {
|
||||
t.Log(fmt.Sprintf("[-]Test nr %2d -- %q", i+1, input.source))
|
||||
t.Log(fmt.Sprintf("[-]Test nr %2d -- %q --> %v", i+1, input.source, input.wantResult))
|
||||
}
|
||||
|
||||
r := strings.NewReader(input.source)
|
||||
|
Loading…
Reference in New Issue
Block a user