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 { type LinkedList struct {
count uint32 count int
first *ListNode first *ListNode
last *ListNode last *ListNode
} }
@@ -29,7 +29,7 @@ func NewLinkedList() (list *LinkedList) {
return return
} }
func (ls *LinkedList) Len() uint32 { func (ls *LinkedList) Len() int {
return ls.count return ls.count
} }
@@ -121,7 +121,7 @@ func (ls *LinkedList) Last() (data interface{}, err error) {
return 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 { if ls.count == 0 {
err = errorListEmpty() err = errorListEmpty()
} else if index > ls.count { } else if index > ls.count {
@@ -130,7 +130,7 @@ func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
node = ls.last node = ls.last
} else { } else {
current := ls.first current := ls.first
for pos := uint32(0); pos < index; pos++ { for range index {
current = current.next current = current.next
} }
node = current node = current
@@ -138,7 +138,7 @@ func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
return 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) node, err := ls.NodeAt(index)
if err == nil { if err == nil {
data = node.data data = node.data
@@ -146,12 +146,12 @@ func (ls *LinkedList) At(index uint32) (data interface{}, err error) {
return return
} }
func (ls *LinkedList) Insert(index uint32, data interface{}) *ListNode { func (ls *LinkedList) Insert(index int, data any) *ListNode {
var prev *ListNode var prev *ListNode
prev = nil prev = nil
current := ls.first current := ls.first
for pos := uint32(0); current != nil && pos < index; pos++ { for pos := 0; current != nil && pos < index; pos++ {
prev = current prev = current
current = current.next 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) { // 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 { // for current := self.first; current != nil; current = current.next {
// err = op(index, current.data, user_data) // err = op(index, current.data, user_data)
// if err != nil { // if err != nil {
@@ -193,7 +204,7 @@ func (ls *LinkedList) PushBackStringArray(items []string) {
// } // }
// func (self *LinkedList) Traverse2(observer Observer, abortOnError bool) (err error) { // 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 { // for current := self.first; current != nil; current = current.next {
// err = observer.Observe(current, index) // err = observer.Observe(current, index)
// if err != nil && abortOnError { // 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 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 // count = 0
// for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) { // for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) {
// // fmt.Println("Item", count, item) // // fmt.Println("Item", count, item)
@@ -242,7 +253,7 @@ func (ls *LinkedList) FindNext(eqFunc EqualFunc, startNode *ListNode) (targetNod
// return // 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 // count = 0
// // item := feeder.Next() // // item := feeder.Next()
// for item, err1 := feeder.Next(); item != nil; item, err1 = 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 { if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
v = (*unboxedValue)[index] 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: case string:
var index int var index int
if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil { 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]) sublist := kern.ListType((*unboxedValue)[start:end])
v = &sublist 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: case string:
var start, end int var start, end int
if start, end, err = verifyRange(indexTerm, indexList, len(unboxedValue)); err == nil { 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() sym = t.Symbol()
} }
// return sym == scan.SymList || sym == scan.SymString || sym == scan.SymDict || sym == scan.SymExpression || sym == scan.SymVariable // 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) { 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}, /* 1 */ {`[<1,2>]`, kern.NewLinkedListA(1, 2), nil},
/* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil}, /* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil},
/* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), 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", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 3) // runTestSuiteSpec(t, section, inputs, 4)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }