linked-list supports index assign and concatenation
This commit is contained in:
@@ -16,7 +16,7 @@ const (
|
||||
TypeItem = "item"
|
||||
TypeIterator = "iterator"
|
||||
TypeNumber = "number"
|
||||
TypePair = "pair"
|
||||
TypeIntPair = "int-pair"
|
||||
TypeString = "string"
|
||||
TypeDict = "dict"
|
||||
TypeListOf = "list-of-"
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"git.portale-stac.it/go-pkg/expr/scan"
|
||||
"git.portale-stac.it/go-pkg/expr/types/array"
|
||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
||||
"git.portale-stac.it/go-pkg/expr/types/list"
|
||||
"git.portale-stac.it/go-pkg/expr/util"
|
||||
)
|
||||
|
||||
@@ -73,6 +74,12 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca
|
||||
}
|
||||
case *dict.DictType:
|
||||
collection.SetItem(keyValue, value)
|
||||
case *list.LinkedList:
|
||||
if index, ok := keyValue.(int64); ok {
|
||||
err = collection.SetItem(index, value)
|
||||
} else {
|
||||
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue))
|
||||
}
|
||||
default:
|
||||
err = collectionTerm.Errorf("collection expected")
|
||||
}
|
||||
|
||||
+19
-19
@@ -29,10 +29,10 @@ func verifyKey(indexList *array.ArrayType) (index any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int) (index int, err error) {
|
||||
var v int
|
||||
func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int64) (index int64, err error) {
|
||||
var v int64
|
||||
|
||||
if v, err = types.ToGoInt((*indexList)[0], "index expression"); err == nil {
|
||||
if v, err = types.ToGoInt64((*indexList)[0], "index expression"); err == nil {
|
||||
if v < 0 && v >= -maxValue {
|
||||
v = maxValue + v
|
||||
}
|
||||
@@ -45,18 +45,18 @@ func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int)
|
||||
return
|
||||
}
|
||||
|
||||
func verifyRange(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int) (startIndex, endIndex int, err error) {
|
||||
func verifyRange(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int64) (startIndex, endIndex int64, err error) {
|
||||
v, _ := ((*indexList)[0]).(*intPair)
|
||||
startIndex = v.a
|
||||
endIndex = v.b
|
||||
if endIndex == kern.ConstLastIndex {
|
||||
endIndex = maxValue
|
||||
endIndex = int64(maxValue)
|
||||
}
|
||||
if startIndex < 0 && startIndex >= -maxValue {
|
||||
startIndex = maxValue + startIndex
|
||||
startIndex = int64(maxValue) + startIndex
|
||||
}
|
||||
if endIndex < 0 && endIndex >= -maxValue {
|
||||
endIndex = maxValue + endIndex
|
||||
endIndex = int64(maxValue) + endIndex
|
||||
}
|
||||
if startIndex < 0 || startIndex > maxValue {
|
||||
err = indexTerm.Errorf("range start-index %d is out of bounds", startIndex)
|
||||
@@ -89,18 +89,18 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
if types.IsInteger((*indexList)[0]) {
|
||||
switch unboxedValue := leftValue.(type) {
|
||||
case *array.ArrayType:
|
||||
var index int
|
||||
if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
||||
var index int64
|
||||
if index, err = verifyIndex(indexTerm, indexList, int64(len(*unboxedValue))); err == nil {
|
||||
v = (*unboxedValue)[index]
|
||||
}
|
||||
case *list.LinkedList:
|
||||
var index int
|
||||
if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil {
|
||||
var index int64
|
||||
if index, err = verifyIndex(indexTerm, indexList, int64(unboxedValue.Len())); err == nil {
|
||||
v, err = unboxedValue.At(index)
|
||||
}
|
||||
case string:
|
||||
var index int
|
||||
if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil {
|
||||
var index int64
|
||||
if index, err = verifyIndex(indexTerm, indexList, int64(len(unboxedValue))); err == nil {
|
||||
v = string(unboxedValue[index])
|
||||
}
|
||||
case *dict.DictType:
|
||||
@@ -111,19 +111,19 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
} else if isIntPair((*indexList)[0]) {
|
||||
switch unboxedValue := leftValue.(type) {
|
||||
case *array.ArrayType:
|
||||
var start, end int
|
||||
if start, end, err = verifyRange(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
||||
var start, end int64
|
||||
if start, end, err = verifyRange(indexTerm, indexList, int64(len(*unboxedValue))); err == nil {
|
||||
sublist := array.ArrayType((*unboxedValue)[start:end])
|
||||
v = &sublist
|
||||
}
|
||||
case *list.LinkedList:
|
||||
var start, end int
|
||||
if start, end, err = verifyRange(indexTerm, indexList, unboxedValue.Len()); err == nil {
|
||||
var start, end int64
|
||||
if start, end, err = verifyRange(indexTerm, indexList, int64(unboxedValue.Len())); err == nil {
|
||||
v = unboxedValue.Sub(start, end)
|
||||
}
|
||||
case string:
|
||||
var start, end int
|
||||
if start, end, err = verifyRange(indexTerm, indexList, len(unboxedValue)); err == nil {
|
||||
var start, end int64
|
||||
if start, end, err = verifyRange(indexTerm, indexList, int64(len(unboxedValue))); err == nil {
|
||||
v = unboxedValue[start:end]
|
||||
}
|
||||
default:
|
||||
|
||||
+3
-3
@@ -14,11 +14,11 @@ import (
|
||||
|
||||
// -------- range term
|
||||
type intPair struct {
|
||||
a, b int
|
||||
a, b int64
|
||||
}
|
||||
|
||||
func (p *intPair) TypeName() string {
|
||||
return kern.TypePair
|
||||
return kern.TypeIntPair
|
||||
}
|
||||
|
||||
func (p *intPair) ToString(opt kern.FmtOpt) string {
|
||||
@@ -70,7 +70,7 @@ func evalRange(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
startIndex, _ := leftValue.(int64)
|
||||
endIndex, _ := rightValue.(int64)
|
||||
|
||||
v = &intPair{int(startIndex), int(endIndex)}
|
||||
v = &intPair{startIndex, endIndex}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
||||
"git.portale-stac.it/go-pkg/expr/types/float"
|
||||
"git.portale-stac.it/go-pkg/expr/types/fract"
|
||||
"git.portale-stac.it/go-pkg/expr/types/list"
|
||||
"git.portale-stac.it/go-pkg/expr/types/str"
|
||||
)
|
||||
|
||||
@@ -50,6 +51,12 @@ func sumValues(plusTerm *scan.Term, leftValue, rightValue any) (v any, err error
|
||||
sumList = append(sumList, *leftList...)
|
||||
sumList = append(sumList, *rightList...)
|
||||
v = &sumList
|
||||
} else if list.IsLinkedList(leftValue) && list.IsLinkedList(rightValue) {
|
||||
lsLeft := leftValue.(*list.LinkedList)
|
||||
lsRight := rightValue.(*list.LinkedList)
|
||||
ls := lsLeft.Clone()
|
||||
ls.SeqPushBack(NewLinkedListIterator(lsRight, nil))
|
||||
v = ls
|
||||
} else if (fract.IsFraction(leftValue) && types.IsNumber(rightValue)) || (fract.IsFraction(rightValue) && types.IsNumber(leftValue)) {
|
||||
if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
|
||||
v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue)
|
||||
|
||||
+2
-2
@@ -81,8 +81,8 @@ func TestAccessSubFields(t *testing.T) {
|
||||
/* 1 */ {`D.a.uno`, int64(10), nil},
|
||||
/* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil},
|
||||
/* 3 */ {`D.a.uno = 111; D["a"]["uno"]`, int64(111), nil},
|
||||
// /* 4 */ {`D.b[1] = 22; D["b"][1]`, int64(22), nil},
|
||||
/* 4 */ {`D.b[1] = 22; D["b"][1]`, nil, `[1:3] collection expected`},
|
||||
/* 4 */ {`D.b[1] = 22; D["b"][1]`, int64(22), nil},
|
||||
// /* 4 */ {`D.b[1] = 22; D["b"][1]`, nil, `[1:3] collection expected`},
|
||||
}
|
||||
RunCtxTestSuiteSpec(t, ctx, section, inputs, 4)
|
||||
// runCtxTestSuite(t, ctx, section, inputs)
|
||||
|
||||
@@ -117,7 +117,7 @@ func (ls *LinkedList) LastNode() *ListNode {
|
||||
return ls.last
|
||||
}
|
||||
|
||||
func (ls *LinkedList) Last() (data interface{}, err error) {
|
||||
func (ls *LinkedList) Last() (data any, err error) {
|
||||
if ls.last != nil {
|
||||
data = ls.last.data
|
||||
} else {
|
||||
@@ -126,7 +126,8 @@ func (ls *LinkedList) Last() (data interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ls *LinkedList) NodeAt(index int) (node *ListNode, err error) {
|
||||
func (ls *LinkedList) NodeAt(index64 int64) (node *ListNode, err error) {
|
||||
index := int(index64)
|
||||
if ls.count == 0 {
|
||||
err = errorListEmpty()
|
||||
} else if index > ls.count {
|
||||
@@ -143,7 +144,7 @@ func (ls *LinkedList) NodeAt(index int) (node *ListNode, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ls *LinkedList) At(index int) (data interface{}, err error) {
|
||||
func (ls *LinkedList) At(index int64) (data any, err error) {
|
||||
node, err := ls.NodeAt(index)
|
||||
if err == nil {
|
||||
data = node.data
|
||||
@@ -151,6 +152,14 @@ func (ls *LinkedList) At(index int) (data interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ls *LinkedList) SetItem(index int64, data any) (err error) {
|
||||
node, err := ls.NodeAt(index)
|
||||
if err == nil {
|
||||
node.data = data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ls *LinkedList) Insert(index int, data any) *ListNode {
|
||||
var prev *ListNode
|
||||
|
||||
@@ -183,7 +192,7 @@ func (ls *LinkedList) PushBackStringArray(items []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (ls *LinkedList) Sub(start, end int) (subList *LinkedList) {
|
||||
func (ls *LinkedList) Sub(start, end int64) (subList *LinkedList) {
|
||||
subList = NewLinkedList()
|
||||
if node, err := ls.NodeAt(start); err == nil {
|
||||
for i := start; i < end && node != nil; i++ {
|
||||
|
||||
Reference in New Issue
Block a user