at operator return -1 when fails in lists and arrays; insert operators (<< and >>) changes che container if it is a variable
This commit is contained in:
+2
-2
@@ -123,7 +123,7 @@ func intFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
|
||||
return
|
||||
}
|
||||
|
||||
func decFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func floatFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
result = float64(v)
|
||||
@@ -318,7 +318,7 @@ func ImportBuiltinsFuncs(ctx kern.ExprContext) {
|
||||
|
||||
ctx.RegisterFunc("bool", kern.NewGolangFunctor(boolFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("int", kern.NewGolangFunctor(intFunc), kern.TypeInt, anyParams)
|
||||
ctx.RegisterFunc("dec", kern.NewGolangFunctor(decFunc), kern.TypeFloat, anyParams)
|
||||
ctx.RegisterFunc("float", kern.NewGolangFunctor(floatFunc), kern.TypeFloat, anyParams)
|
||||
ctx.RegisterFunc("string", kern.NewGolangFunctor(stringFunc), kern.TypeString, anyParams)
|
||||
ctx.RegisterFunc("fract", kern.NewGolangFunctor(fractFunc), kern.TypeFraction, []kern.ExprFuncParam{
|
||||
kern.NewFuncParam(kern.ParamValue),
|
||||
|
||||
+6
-1
@@ -15,7 +15,12 @@ type Term interface {
|
||||
GetChildCount() (count int)
|
||||
GetChild(index int) Term
|
||||
GetChildSource(index int) string
|
||||
Compute(ctx ExprContext) (result any, err error)
|
||||
GetLeftChild() (c Term)
|
||||
GetRightChild() (c Term)
|
||||
IsAssign() bool
|
||||
IsVar() bool
|
||||
Compute(ctx ExprContext) (result any, err error)
|
||||
EvalInfix(ctx ExprContext) (leftValue, rightValue any, err error)
|
||||
Errorf(template string, args ...any) (err error)
|
||||
ErrIncompatibleTypes(leftValue, rightValue any) error
|
||||
}
|
||||
|
||||
+4
-1
@@ -36,6 +36,7 @@ func evalAt(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
v = int64(-1) // default value if not found
|
||||
if array.IsArray(rightValue) {
|
||||
a, _ := rightValue.(*array.ArrayType)
|
||||
if index := a.IndexDeepSameCmp(leftValue); index >= 0 {
|
||||
@@ -45,14 +46,16 @@ func evalAt(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
dict, _ := rightValue.(*dict.DictType)
|
||||
if k, exists := dict.FindKey(leftValue); exists {
|
||||
v = k
|
||||
} else {
|
||||
v = nil
|
||||
}
|
||||
|
||||
} else if list.IsLinkedList(rightValue) {
|
||||
ls, _ := rightValue.(*list.LinkedList)
|
||||
if index := ls.Index(leftValue); index >= 0 {
|
||||
v = index
|
||||
}
|
||||
} else {
|
||||
v = nil
|
||||
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return
|
||||
|
||||
+10
-20
@@ -33,7 +33,7 @@ func newAppendTerm(tk *scan.Token) (inst *scan.Term) {
|
||||
}
|
||||
}
|
||||
|
||||
func prependToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err error) {
|
||||
func prependToList(opTerm kern.Term, leftValue, rightValue any) (result any, err error) {
|
||||
if a, ok := rightValue.(*array.ArrayType); ok {
|
||||
var it kern.Iterator
|
||||
if it, ok = leftValue.(kern.Iterator); !ok {
|
||||
@@ -53,6 +53,10 @@ func prependToList(opTerm *scan.Term, leftValue, rightValue any) (result any, er
|
||||
for _, item := range *a {
|
||||
newArray = append(newArray, item)
|
||||
}
|
||||
if opTerm.GetRightChild().IsVar() {
|
||||
// Update the original array if the right operand is a variable
|
||||
*a = newArray
|
||||
}
|
||||
result = &newArray
|
||||
} else if ll, ok := rightValue.(*list.LinkedList); ok {
|
||||
var it kern.Iterator
|
||||
@@ -78,7 +82,7 @@ func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func appendToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err error) {
|
||||
func appendToList(opTerm kern.Term, leftValue, rightValue any) (result any, err error) {
|
||||
if a, ok := leftValue.(*array.ArrayType); ok {
|
||||
var it kern.Iterator
|
||||
if it, ok = rightValue.(kern.Iterator); !ok {
|
||||
@@ -98,6 +102,10 @@ func appendToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err
|
||||
for node := ls.FirstNode(); node != nil; node = node.Next() {
|
||||
newArray = append(newArray, node.Data())
|
||||
}
|
||||
if opTerm.GetLeftChild().IsVar() {
|
||||
// Update the original array if the left operand is a variable
|
||||
*a = newArray
|
||||
}
|
||||
result = &newArray
|
||||
} else if ll, ok := leftValue.(*list.LinkedList); ok {
|
||||
var it kern.Iterator
|
||||
@@ -124,24 +132,6 @@ func evalAppend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// // func evalAssignAppend(ctx ExprContext, self *term) (v any, err error) {
|
||||
// // var leftValue, rightValue any
|
||||
|
||||
// // if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
// // return
|
||||
// // }
|
||||
|
||||
// // if IsArray(leftValue) {
|
||||
// // list, _ := leftValue.(*ListType)
|
||||
// // newList := append(*list, rightValue)
|
||||
// // v = &newList
|
||||
// // if
|
||||
// // } else {
|
||||
// // err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
// // }
|
||||
// // return
|
||||
// // }
|
||||
|
||||
// init
|
||||
func init() {
|
||||
scan.RegisterTermConstructor(scan.SymPlusGreater, newPrependTerm)
|
||||
|
||||
@@ -186,10 +186,32 @@ func (t *Term) GetChildSource(index int) (s string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Term) GetLeftChild() (c kern.Term) {
|
||||
if t.Position == PosInfix && len(t.Children) > 0 {
|
||||
c = t.Children[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Term) GetRightChild() (c kern.Term) {
|
||||
if t.Position == PosInfix && len(t.Children) > 1 {
|
||||
c = t.Children[1]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Term) IsAssign() bool {
|
||||
return t.Symbol() == SymEqual
|
||||
}
|
||||
|
||||
func (t *Term) IsVar() bool {
|
||||
return t.Symbol() == SymVariable
|
||||
}
|
||||
|
||||
// func (t *Term) IsFunc() bool {
|
||||
// return t.Symbol() == SymFunction
|
||||
// }
|
||||
|
||||
func (t *Term) Compute(ctx kern.ExprContext) (v any, err error) {
|
||||
if t.EvalFunc == nil {
|
||||
err = t.Errorf("undefined eval-func for %q term", t.Source())
|
||||
|
||||
+22
-24
@@ -25,8 +25,8 @@ func TestArray(t *testing.T) {
|
||||
/* 9 */ {`builtin "math.arith"; mul([1,4,3.0,2])`, float64(24.0), nil},
|
||||
/* 10 */ {`builtin "math.arith"; add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`},
|
||||
/* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
|
||||
/* 12 */ {`[1,2,3] <+ 2+2`, array.NewArrayA(int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 13 */ {`2-1 +> [2,3]`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 12 */ {`[1,2,3] <+ 2+2`, array.ArrayFromIntsA(1, 2, 3, 4), nil},
|
||||
/* 13 */ {`2-1 +> [2,3]`, array.ArrayFromIntsA(1, 2, 3), nil},
|
||||
/* 14 */ {`[1,2,3][1]`, int64(2), nil},
|
||||
/* 15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil},
|
||||
/* 16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil},
|
||||
@@ -41,31 +41,26 @@ func TestArray(t *testing.T) {
|
||||
/* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
|
||||
/* 26 */ {`[0,1,2,3,4][:]`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`},
|
||||
/* 28 */ {`2 << 3;`, int64(16), nil},
|
||||
/* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`},
|
||||
/* 30 */ {`2 >> 3;`, int64(0), nil},
|
||||
/* 31 */ {`a=[1,2]; a<+3`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 32 */ {`a=[1,2]; 5+>a`, array.NewArrayA(int64(5), int64(1), int64(2)), nil},
|
||||
/* 33 */ {`L=[1,2]; L[0]=9; L`, array.NewArrayA(int64(9), int64(2)), nil},
|
||||
/* 34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
|
||||
/* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [array]`},
|
||||
/* 36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
|
||||
/* 37 */ {`[0,1,2,3,4][2:3]`, array.NewArrayA(int64(2)), nil},
|
||||
/* 38 */ {`[0,1,2,3,4][3:-1]`, array.NewArrayA(int64(3)), nil},
|
||||
/* 30 */ {`[0,1,2,3,4][-3:-1]`, array.NewArrayA(int64(2), int64(3)), nil},
|
||||
/* 40 */ {`[0,1,2,3,4][0:]`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 41 */ {`[0] << $([1,2,3,4])`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 42 */ {`L=[]; [1] >> L; L`, array.NewArrayA(), nil},
|
||||
/* 43 */ {`L=[]; L << [1]; L`, array.NewArrayA(), nil},
|
||||
/* 44 */ {`2 IN [1,2,3]`, true, nil},
|
||||
/* 45 */ {`2 AT [1,2,3]`, int64(1), nil},
|
||||
/* 46 */ {`4 AT [1,2,3]`, int64(-1), nil},
|
||||
/* 28 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`},
|
||||
/* 29 */ {`a=[1,2]; a<+3`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 30 */ {`a=[1,2]; 5+>a`, array.NewArrayA(int64(5), int64(1), int64(2)), nil},
|
||||
/* 31 */ {`L=[1,2]; L[0]=9; L`, array.NewArrayA(int64(9), int64(2)), nil},
|
||||
/* 32 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
|
||||
/* 33 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [array]`},
|
||||
/* 34 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
|
||||
/* 35 */ {`[0,1,2,3,4][2:3]`, array.NewArrayA(int64(2)), nil},
|
||||
/* 36 */ {`[0,1,2,3,4][3:-1]`, array.NewArrayA(int64(3)), nil},
|
||||
/* 37 */ {`[0,1,2,3,4][-3:-1]`, array.NewArrayA(int64(2), int64(3)), nil},
|
||||
/* 38 */ {`[0,1,2,3,4][0:]`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 39 */ {`2 IN [1,2,3]`, true, nil},
|
||||
/* 40 */ {`2 AT [1,2,3]`, int64(1), nil},
|
||||
/* 41 */ {`4 AT [1,2,3]`, int64(-1), nil},
|
||||
// /* 44 */ {`[0,1,2,3,4][2:3]`, kern.NewListA(int64(20)), nil},
|
||||
}
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 44)
|
||||
// RunTestSuiteSpec(t, section, inputs, 43)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
@@ -82,11 +77,14 @@ func TestArrayInsert(t *testing.T) {
|
||||
/* 8 */ {`$([]) >> ["a", "b"]`, array.NewArrayA("a", "b"), nil},
|
||||
/* 9 */ {`["a", "b"] << $([1,2,3])`, array.NewArrayA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||
/* 10 */ {`L=["a", "b"]; L << $([1,2,3])`, array.NewArrayA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||
/* 11 */ {`L=["a", "b"]; L << $([1,2,3]); L`, array.NewArrayA("a", "b"), nil},
|
||||
/* 11 */ {`L=["a", "b"]; L << $([1,2,3]); L`, array.NewArrayA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||
/* 12 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
|
||||
/* 13 */ {`[0] << $([1,2,3,4])`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 14 */ {`L=[]; [1] >> L; L`, array.NewArrayA(array.ArrayFromIntsA(1)), nil},
|
||||
/* 15 */ {`L=[]; L << [1]; L`, array.NewArrayA(array.ArrayFromIntsA(1)), nil},
|
||||
}
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 9)
|
||||
// RunTestSuiteSpec(t, section, inputs, 14)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -40,13 +40,13 @@ func TestFuncBase(t *testing.T) {
|
||||
/* 23 */ {`fract("1.21(3)")`, fract.NewFraction(91, 75), nil},
|
||||
/* 24 */ {`fract(1.21(3))`, fract.NewFraction(91, 75), nil},
|
||||
/* 25 */ {`fract(1.21)`, fract.NewFraction(121, 100), nil},
|
||||
/* 26 */ {`dec(2)`, float64(2), nil},
|
||||
/* 27 */ {`dec(2.0)`, float64(2), nil},
|
||||
/* 28 */ {`dec("2.0")`, float64(2), nil},
|
||||
/* 29 */ {`dec(true)`, float64(1), nil},
|
||||
/* 30 */ {`dec(true")`, nil, "[1:11] expected one of `,`, `)`, got `\"`"},
|
||||
/* 31 */ {`dec()`, nil, `dec(): too few params -- expected 1, got 0`},
|
||||
/* 32 */ {`dec(1,2,3)`, nil, `dec(): too many params -- expected 1, got 3`},
|
||||
/* 26 */ {`float(2)`, float64(2), nil},
|
||||
/* 27 */ {`float(2.0)`, float64(2), nil},
|
||||
/* 28 */ {`float("2.0")`, float64(2), nil},
|
||||
/* 29 */ {`float(true)`, float64(1), nil},
|
||||
/* 30 */ {`float(true")`, nil, "[1:13] expected one of `,`, `)`, got `\"`"},
|
||||
/* 31 */ {`float()`, nil, `float(): too few params -- expected 1, got 0`},
|
||||
/* 32 */ {`float(1,2,3)`, nil, `float(): too many params -- expected 1, got 3`},
|
||||
/* 33 */ {`isBool(false)`, true, nil},
|
||||
/* 34 */ {`fract(1:2)`, fract.NewFraction(1, 2), nil},
|
||||
/* 35 */ {`fract(12,2)`, fract.NewFraction(6, 1), nil},
|
||||
@@ -59,9 +59,9 @@ func TestFuncBase(t *testing.T) {
|
||||
/* 42 */ {`bool([])`, false, nil},
|
||||
/* 43 */ {`bool({})`, false, nil},
|
||||
/* 44 */ {`bool({1:"one"})`, true, nil},
|
||||
/* 45 */ {`dec(false)`, float64(0), nil},
|
||||
/* 46 */ {`dec(1:2)`, float64(0.5), nil},
|
||||
/* 47 */ {`dec([1])`, nil, `dec(): can't convert array to float`},
|
||||
/* 45 */ {`float(false)`, float64(0), nil},
|
||||
/* 46 */ {`float(1:2)`, float64(0.5), nil},
|
||||
/* 47 */ {`float([1])`, nil, `float(): can't convert array to float`},
|
||||
/* 48 */ {`eval("a=3"); a`, int64(3), nil},
|
||||
/* 49 */ {`int(5:2)`, int64(2), nil},
|
||||
|
||||
|
||||
+2
-2
@@ -38,10 +38,10 @@ func TestLinkedInsert(t *testing.T) {
|
||||
section := "LinkedList-Insert"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`[<>] << 1`, list.NewLinkedListA(1), nil},
|
||||
/* 2 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 2 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.ArrayFromIntsA(1, 2)), nil},
|
||||
/* 3 */ {`[<>] << [<1,2>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 4 */ {`1 >> [<>]`, list.NewLinkedListA(1), nil},
|
||||
/* 5 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 5 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.ArrayFromIntsA(1, 2)), nil},
|
||||
/* 6 */ {`[<1,2>] >> [<>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 7 */ {`$([1,2]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
/* 8 */ {`$([<1,2>]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
|
||||
@@ -42,6 +42,8 @@ func TestOperator(t *testing.T) {
|
||||
/* 26 */ {`a="1"; --a`, nil, `[1:9] prefix/postfix operator "--" does not support operand '1' [string]`},
|
||||
/* 27 */ {`a="1"; a++`, nil, `[1:10] prefix/postfix operator "++" does not support operand '1' [string]`},
|
||||
/* 28 */ {`a="1"; a--`, nil, `[1:10] prefix/postfix operator "--" does not support operand '1' [string]`},
|
||||
/* 29 */ {`2 << 3;`, int64(16), nil},
|
||||
/* 30 */ {`2 >> 3;`, int64(0), nil},
|
||||
}
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
@@ -51,6 +51,18 @@ func ArrayFromStrings(stringSlice []string) (aRef *ArrayType) {
|
||||
return
|
||||
}
|
||||
|
||||
func ArrayFromIntsA(ints ...int) (aRef *ArrayType) {
|
||||
return ArrayFromInts(ints)
|
||||
}
|
||||
|
||||
func ArrayFromInts(intSlice []int) (aRef *ArrayType) {
|
||||
aRef = MakeArray(len(intSlice), 0)
|
||||
for i, s := range intSlice {
|
||||
(*aRef)[i] = int64(s)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) ToString(opt kern.FmtOpt) (s string) {
|
||||
indent := kern.GetFormatIndent(opt)
|
||||
flags := kern.GetFormatFlags(opt)
|
||||
|
||||
@@ -141,6 +141,19 @@ func (ls *LinkedList) Last() (data any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// func (ls *LinkedList) Reverse() *ListNode {
|
||||
// var prev *ListNode
|
||||
|
||||
// for current := ls.first; current != nil; {
|
||||
// succ := current.next
|
||||
// prev = succ.next
|
||||
// succ.next = current
|
||||
// current = prev
|
||||
// }
|
||||
// ls.first, ls.last = ls.last, ls.first
|
||||
// return ls.first
|
||||
// }
|
||||
|
||||
func (ls *LinkedList) NodeAt(index64 int64) (node *ListNode, err error) {
|
||||
index := int(index64)
|
||||
if ls.count == 0 {
|
||||
|
||||
Reference in New Issue
Block a user