linked-list supports index assign and concatenation

This commit is contained in:
2026-07-13 11:34:25 +02:00
parent 072fd9af39
commit 4df222496d
7 changed files with 52 additions and 29 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ const (
TypeItem = "item"
TypeIterator = "iterator"
TypeNumber = "number"
TypePair = "pair"
TypeIntPair = "int-pair"
TypeString = "string"
TypeDict = "dict"
TypeListOf = "list-of-"
+7
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+7
View File
@@ -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
View File
@@ -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)
+13 -4
View File
@@ -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++ {