From 4df222496de74abd2295ef1717636f693496ec12 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Mon, 13 Jul 2026 11:34:25 +0200 Subject: [PATCH] linked-list supports index assign and concatenation --- kern/common-type-names.go | 2 +- operator-assign.go | 7 +++++++ operator-index.go | 38 +++++++++++++++++++------------------- operator-range.go | 6 +++--- operator-sum.go | 7 +++++++ t_dict_test.go | 4 ++-- types/list/linked-list.go | 17 +++++++++++++---- 7 files changed, 52 insertions(+), 29 deletions(-) diff --git a/kern/common-type-names.go b/kern/common-type-names.go index 531eb43..b45e91e 100644 --- a/kern/common-type-names.go +++ b/kern/common-type-names.go @@ -16,7 +16,7 @@ const ( TypeItem = "item" TypeIterator = "iterator" TypeNumber = "number" - TypePair = "pair" + TypeIntPair = "int-pair" TypeString = "string" TypeDict = "dict" TypeListOf = "list-of-" diff --git a/operator-assign.go b/operator-assign.go index 5252aea..4a4688f 100644 --- a/operator-assign.go +++ b/operator-assign.go @@ -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") } diff --git a/operator-index.go b/operator-index.go index 24baa55..8e81817 100644 --- a/operator-index.go +++ b/operator-index.go @@ -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: diff --git a/operator-range.go b/operator-range.go index 1585e2d..2b95db3 100644 --- a/operator-range.go +++ b/operator-range.go @@ -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 } diff --git a/operator-sum.go b/operator-sum.go index 3a7465e..218f238 100644 --- a/operator-sum.go +++ b/operator-sum.go @@ -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) diff --git a/t_dict_test.go b/t_dict_test.go index 1bae236..f4ec8e6 100644 --- a/t_dict_test.go +++ b/t_dict_test.go @@ -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) diff --git a/types/list/linked-list.go b/types/list/linked-list.go index 6feb7c5..d652187 100644 --- a/types/list/linked-list.go +++ b/types/list/linked-list.go @@ -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++ {