From 1aea1c14d2a70059d1529933f86e5c90a62f78bb Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Tue, 19 May 2026 06:42:45 +0200 Subject: [PATCH] LinkedList: added support for index and range extraction --- kern/linked-list.go | 37 ++++++++++++++++++++++++------------- operator-index.go | 10 ++++++++++ parser.go | 2 +- t_list_test.go | 4 +++- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/kern/linked-list.go b/kern/linked-list.go index d61ab3f..5bfd9d0 100644 --- a/kern/linked-list.go +++ b/kern/linked-list.go @@ -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() { diff --git a/operator-index.go b/operator-index.go index 30aa2e2..4f8c473 100644 --- a/operator-index.go +++ b/operator-index.go @@ -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 { diff --git a/parser.go b/parser.go index d3fa388..ce28a55 100644 --- a/parser.go +++ b/parser.go @@ -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) { diff --git a/t_list_test.go b/t_list_test.go index c958a9c..971f303 100644 --- a/t_list_test.go +++ b/t_list_test.go @@ -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) }