linked-list supports index assign and concatenation
This commit is contained in:
@@ -16,7 +16,7 @@ const (
|
|||||||
TypeItem = "item"
|
TypeItem = "item"
|
||||||
TypeIterator = "iterator"
|
TypeIterator = "iterator"
|
||||||
TypeNumber = "number"
|
TypeNumber = "number"
|
||||||
TypePair = "pair"
|
TypeIntPair = "int-pair"
|
||||||
TypeString = "string"
|
TypeString = "string"
|
||||||
TypeDict = "dict"
|
TypeDict = "dict"
|
||||||
TypeListOf = "list-of-"
|
TypeListOf = "list-of-"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"git.portale-stac.it/go-pkg/expr/scan"
|
"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/array"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
"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"
|
"git.portale-stac.it/go-pkg/expr/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,6 +74,12 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca
|
|||||||
}
|
}
|
||||||
case *dict.DictType:
|
case *dict.DictType:
|
||||||
collection.SetItem(keyValue, value)
|
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:
|
default:
|
||||||
err = collectionTerm.Errorf("collection expected")
|
err = collectionTerm.Errorf("collection expected")
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -29,10 +29,10 @@ func verifyKey(indexList *array.ArrayType) (index any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int) (index int, err error) {
|
func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int64) (index int64, err error) {
|
||||||
var v int
|
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 {
|
if v < 0 && v >= -maxValue {
|
||||||
v = maxValue + v
|
v = maxValue + v
|
||||||
}
|
}
|
||||||
@@ -45,18 +45,18 @@ func verifyIndex(indexTerm *scan.Term, indexList *array.ArrayType, maxValue int)
|
|||||||
return
|
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)
|
v, _ := ((*indexList)[0]).(*intPair)
|
||||||
startIndex = v.a
|
startIndex = v.a
|
||||||
endIndex = v.b
|
endIndex = v.b
|
||||||
if endIndex == kern.ConstLastIndex {
|
if endIndex == kern.ConstLastIndex {
|
||||||
endIndex = maxValue
|
endIndex = int64(maxValue)
|
||||||
}
|
}
|
||||||
if startIndex < 0 && startIndex >= -maxValue {
|
if startIndex < 0 && startIndex >= -maxValue {
|
||||||
startIndex = maxValue + startIndex
|
startIndex = int64(maxValue) + startIndex
|
||||||
}
|
}
|
||||||
if endIndex < 0 && endIndex >= -maxValue {
|
if endIndex < 0 && endIndex >= -maxValue {
|
||||||
endIndex = maxValue + endIndex
|
endIndex = int64(maxValue) + endIndex
|
||||||
}
|
}
|
||||||
if startIndex < 0 || startIndex > maxValue {
|
if startIndex < 0 || startIndex > maxValue {
|
||||||
err = indexTerm.Errorf("range start-index %d is out of bounds", startIndex)
|
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]) {
|
if types.IsInteger((*indexList)[0]) {
|
||||||
switch unboxedValue := leftValue.(type) {
|
switch unboxedValue := leftValue.(type) {
|
||||||
case *array.ArrayType:
|
case *array.ArrayType:
|
||||||
var index int
|
var index int64
|
||||||
if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
if index, err = verifyIndex(indexTerm, indexList, int64(len(*unboxedValue))); err == nil {
|
||||||
v = (*unboxedValue)[index]
|
v = (*unboxedValue)[index]
|
||||||
}
|
}
|
||||||
case *list.LinkedList:
|
case *list.LinkedList:
|
||||||
var index int
|
var index int64
|
||||||
if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil {
|
if index, err = verifyIndex(indexTerm, indexList, int64(unboxedValue.Len())); err == nil {
|
||||||
v, err = unboxedValue.At(index)
|
v, err = unboxedValue.At(index)
|
||||||
}
|
}
|
||||||
case string:
|
case string:
|
||||||
var index int
|
var index int64
|
||||||
if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil {
|
if index, err = verifyIndex(indexTerm, indexList, int64(len(unboxedValue))); err == nil {
|
||||||
v = string(unboxedValue[index])
|
v = string(unboxedValue[index])
|
||||||
}
|
}
|
||||||
case *dict.DictType:
|
case *dict.DictType:
|
||||||
@@ -111,19 +111,19 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
} else if isIntPair((*indexList)[0]) {
|
} else if isIntPair((*indexList)[0]) {
|
||||||
switch unboxedValue := leftValue.(type) {
|
switch unboxedValue := leftValue.(type) {
|
||||||
case *array.ArrayType:
|
case *array.ArrayType:
|
||||||
var start, end int
|
var start, end int64
|
||||||
if start, end, err = verifyRange(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
if start, end, err = verifyRange(indexTerm, indexList, int64(len(*unboxedValue))); err == nil {
|
||||||
sublist := array.ArrayType((*unboxedValue)[start:end])
|
sublist := array.ArrayType((*unboxedValue)[start:end])
|
||||||
v = &sublist
|
v = &sublist
|
||||||
}
|
}
|
||||||
case *list.LinkedList:
|
case *list.LinkedList:
|
||||||
var start, end int
|
var start, end int64
|
||||||
if start, end, err = verifyRange(indexTerm, indexList, unboxedValue.Len()); err == nil {
|
if start, end, err = verifyRange(indexTerm, indexList, int64(unboxedValue.Len())); err == nil {
|
||||||
v = unboxedValue.Sub(start, end)
|
v = unboxedValue.Sub(start, end)
|
||||||
}
|
}
|
||||||
case string:
|
case string:
|
||||||
var start, end int
|
var start, end int64
|
||||||
if start, end, err = verifyRange(indexTerm, indexList, len(unboxedValue)); err == nil {
|
if start, end, err = verifyRange(indexTerm, indexList, int64(len(unboxedValue))); err == nil {
|
||||||
v = unboxedValue[start:end]
|
v = unboxedValue[start:end]
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
+3
-3
@@ -14,11 +14,11 @@ import (
|
|||||||
|
|
||||||
// -------- range term
|
// -------- range term
|
||||||
type intPair struct {
|
type intPair struct {
|
||||||
a, b int
|
a, b int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *intPair) TypeName() string {
|
func (p *intPair) TypeName() string {
|
||||||
return kern.TypePair
|
return kern.TypeIntPair
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *intPair) ToString(opt kern.FmtOpt) string {
|
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)
|
startIndex, _ := leftValue.(int64)
|
||||||
endIndex, _ := rightValue.(int64)
|
endIndex, _ := rightValue.(int64)
|
||||||
|
|
||||||
v = &intPair{int(startIndex), int(endIndex)}
|
v = &intPair{startIndex, endIndex}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
"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/float"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/fract"
|
"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"
|
"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, *leftList...)
|
||||||
sumList = append(sumList, *rightList...)
|
sumList = append(sumList, *rightList...)
|
||||||
v = &sumList
|
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)) {
|
} else if (fract.IsFraction(leftValue) && types.IsNumber(rightValue)) || (fract.IsFraction(rightValue) && types.IsNumber(leftValue)) {
|
||||||
if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
|
if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
|
||||||
v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue)
|
v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue)
|
||||||
|
|||||||
+2
-2
@@ -81,8 +81,8 @@ func TestAccessSubFields(t *testing.T) {
|
|||||||
/* 1 */ {`D.a.uno`, int64(10), nil},
|
/* 1 */ {`D.a.uno`, int64(10), nil},
|
||||||
/* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil},
|
/* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil},
|
||||||
/* 3 */ {`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]`, int64(22), nil},
|
||||||
/* 4 */ {`D.b[1] = 22; D["b"][1]`, nil, `[1:3] collection expected`},
|
// /* 4 */ {`D.b[1] = 22; D["b"][1]`, nil, `[1:3] collection expected`},
|
||||||
}
|
}
|
||||||
RunCtxTestSuiteSpec(t, ctx, section, inputs, 4)
|
RunCtxTestSuiteSpec(t, ctx, section, inputs, 4)
|
||||||
// runCtxTestSuite(t, ctx, section, inputs)
|
// runCtxTestSuite(t, ctx, section, inputs)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func (ls *LinkedList) LastNode() *ListNode {
|
|||||||
return ls.last
|
return ls.last
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *LinkedList) Last() (data interface{}, err error) {
|
func (ls *LinkedList) Last() (data any, err error) {
|
||||||
if ls.last != nil {
|
if ls.last != nil {
|
||||||
data = ls.last.data
|
data = ls.last.data
|
||||||
} else {
|
} else {
|
||||||
@@ -126,7 +126,8 @@ func (ls *LinkedList) Last() (data interface{}, err error) {
|
|||||||
return
|
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 {
|
if ls.count == 0 {
|
||||||
err = errorListEmpty()
|
err = errorListEmpty()
|
||||||
} else if index > ls.count {
|
} else if index > ls.count {
|
||||||
@@ -143,7 +144,7 @@ func (ls *LinkedList) NodeAt(index int) (node *ListNode, err error) {
|
|||||||
return
|
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)
|
node, err := ls.NodeAt(index)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
data = node.data
|
data = node.data
|
||||||
@@ -151,6 +152,14 @@ func (ls *LinkedList) At(index int) (data interface{}, err error) {
|
|||||||
return
|
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 {
|
func (ls *LinkedList) Insert(index int, data any) *ListNode {
|
||||||
var prev *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()
|
subList = NewLinkedList()
|
||||||
if node, err := ls.NodeAt(start); err == nil {
|
if node, err := ls.NodeAt(start); err == nil {
|
||||||
for i := start; i < end && node != nil; i++ {
|
for i := start; i < end && node != nil; i++ {
|
||||||
|
|||||||
Reference in New Issue
Block a user