LinkedList: added support for index and range extraction

This commit is contained in:
2026-05-19 06:42:45 +02:00
parent 081395be5f
commit 1aea1c14d2
4 changed files with 38 additions and 15 deletions
+24 -13
View File
@@ -19,7 +19,7 @@ func (self *ListNode) Data() any {
}
type LinkedList struct {
count uint32
count int
first *ListNode
last *ListNode
}
@@ -29,7 +29,7 @@ func NewLinkedList() (list *LinkedList) {
return
}
func (ls *LinkedList) Len() uint32 {
func (ls *LinkedList) Len() int {
return ls.count
}
@@ -121,7 +121,7 @@ func (ls *LinkedList) Last() (data interface{}, err error) {
return
}
func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
func (ls *LinkedList) NodeAt(index int) (node *ListNode, err error) {
if ls.count == 0 {
err = errorListEmpty()
} else if index > ls.count {
@@ -130,7 +130,7 @@ func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
node = ls.last
} else {
current := ls.first
for pos := uint32(0); pos < index; pos++ {
for range index {
current = current.next
}
node = current
@@ -138,7 +138,7 @@ func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
return
}
func (ls *LinkedList) At(index uint32) (data interface{}, err error) {
func (ls *LinkedList) At(index int) (data interface{}, err error) {
node, err := ls.NodeAt(index)
if err == nil {
data = node.data
@@ -146,12 +146,12 @@ func (ls *LinkedList) At(index uint32) (data interface{}, err error) {
return
}
func (ls *LinkedList) Insert(index uint32, data interface{}) *ListNode {
func (ls *LinkedList) Insert(index int, data any) *ListNode {
var prev *ListNode
prev = nil
current := ls.first
for pos := uint32(0); current != nil && pos < index; pos++ {
for pos := 0; current != nil && pos < index; pos++ {
prev = current
current = current.next
}
@@ -178,10 +178,21 @@ func (ls *LinkedList) PushBackStringArray(items []string) {
}
}
// type TraverseOperator func(index uint32, elem interface{}, userData interface{}) (err error)
func (ls *LinkedList) Sub(start, end int) (subList *LinkedList) {
subList = NewLinkedList()
if node, err := ls.NodeAt(start); err == nil {
for i := start; i < end && node != nil; i++ {
subList.PushBack(node.data)
node = node.next
}
}
return
}
// type TraverseOperator func(index int, elem interface{}, userData interface{}) (err error)
// func (self *LinkedList) Traverse(op TraverseOperator, user_data interface{}) (err error) {
// index := uint32(0)
// index := int(0)
// for current := self.first; current != nil; current = current.next {
// err = op(index, current.data, user_data)
// if err != nil {
@@ -193,7 +204,7 @@ func (ls *LinkedList) PushBackStringArray(items []string) {
// }
// func (self *LinkedList) Traverse2(observer Observer, abortOnError bool) (err error) {
// index := uint32(0)
// index := int(0)
// for current := self.first; current != nil; current = current.next {
// err = observer.Observe(current, index)
// if err != nil && abortOnError {
@@ -227,9 +238,9 @@ func (ls *LinkedList) FindNext(eqFunc EqualFunc, startNode *ListNode) (targetNod
}
// type DataFeeder func(user_data interface{}) interface{}
// type NodeObserver func(node *ListNode, index uint32, userData interface{})
// type NodeObserver func(node *ListNode, index int, userData interface{})
// func (self *LinkedList) FeedTail(feeder DataFeeder, feederUserData interface{}, observer NodeObserver, observerUserData interface{}) (count uint32) {
// func (self *LinkedList) FeedTail(feeder DataFeeder, feederUserData interface{}, observer NodeObserver, observerUserData interface{}) (count int) {
// count = 0
// for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) {
// // fmt.Println("Item", count, item)
@@ -242,7 +253,7 @@ func (ls *LinkedList) FindNext(eqFunc EqualFunc, startNode *ListNode) (targetNod
// return
// }
// func (self *LinkedList) FeedTail2(feeder Feeder, observer Observer, abortOnError bool) (count uint32, err error) {
// func (self *LinkedList) FeedTail2(feeder Feeder, observer Observer, abortOnError bool) (count int, err error) {
// count = 0
// // item := feeder.Next()
// for item, err1 := feeder.Next(); item != nil; item, err1 = feeder.Next() {
+10
View File
@@ -89,6 +89,11 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
v = (*unboxedValue)[index]
}
case *kern.LinkedList:
var index int
if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil {
v, err = unboxedValue.At(index)
}
case string:
var index int
if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil {
@@ -107,6 +112,11 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
sublist := kern.ListType((*unboxedValue)[start:end])
v = &sublist
}
case *kern.LinkedList:
var start, end int
if start, end, err = verifyRange(indexTerm, indexList, 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 {
+1 -1
View File
@@ -408,7 +408,7 @@ func couldBeACollection(t *scan.Term) bool {
sym = t.Symbol()
}
// return sym == scan.SymList || sym == scan.SymString || sym == scan.SymDict || sym == scan.SymExpression || sym == scan.SymVariable
return slices.Contains([]scan.Symbol{scan.SymList, scan.SymString, scan.SymDict, scan.SymExpression, scan.SymVariable, scan.SymIndex}, sym)
return slices.Contains([]scan.Symbol{scan.SymList, scan.SymLinkedList, scan.SymString, scan.SymDict, scan.SymExpression, scan.SymVariable, scan.SymIndex}, sym)
}
func listSubTree(tree *scan.Ast, listTerm *scan.Term, allowIndeces bool) (root *scan.Term, err error) {
+3 -1
View File
@@ -73,10 +73,12 @@ func TestLinkedListParser(t *testing.T) {
/* 1 */ {`[<1,2>]`, kern.NewLinkedListA(1, 2), nil},
/* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil},
/* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), nil},
/* 4 */ {`[<1,2,3>][0]`, int64(1), nil},
/* 5 */ {`[<1,2,3>][0:2]`, kern.NewLinkedListA(1, 2), nil},
}
// t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 3)
// runTestSuiteSpec(t, section, inputs, 4)
runTestSuite(t, section, inputs)
}