alias operators: '<<' same as '<+', '>>' same as '+>'. Insert and append operation optimized with linked lists
This commit is contained in:
@@ -0,0 +1,273 @@
|
|||||||
|
// simple-list project slist.go
|
||||||
|
package kern
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
data any
|
||||||
|
next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *ListNode) Next() *ListNode {
|
||||||
|
return node.next
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListNode) Data() any {
|
||||||
|
return self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinkedList struct {
|
||||||
|
count uint32
|
||||||
|
first *ListNode
|
||||||
|
last *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinkedList() (list *LinkedList) {
|
||||||
|
list = &LinkedList{0, nil, nil}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) Len() uint32 {
|
||||||
|
return ls.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) Empty() bool {
|
||||||
|
return ls.count == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) PushFront(data any) *ListNode {
|
||||||
|
ls.first = &ListNode{data, ls.first}
|
||||||
|
if ls.last == nil {
|
||||||
|
ls.last = ls.first
|
||||||
|
}
|
||||||
|
ls.count++
|
||||||
|
return ls.first
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) {
|
||||||
|
switch seq := data.(type) {
|
||||||
|
case Iterator:
|
||||||
|
result = ls.IterPushFront(seq)
|
||||||
|
default:
|
||||||
|
ls.PushFront(data)
|
||||||
|
result = ls
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) IterPushFront(it Iterator) *LinkedList {
|
||||||
|
for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
|
||||||
|
ls.PushFront(item)
|
||||||
|
}
|
||||||
|
return ls
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) PushBack(data any) (node *ListNode) {
|
||||||
|
node = &ListNode{data, nil}
|
||||||
|
if ls.last != nil {
|
||||||
|
ls.last.next = node
|
||||||
|
}
|
||||||
|
ls.last = node
|
||||||
|
if ls.first == nil {
|
||||||
|
ls.first = node
|
||||||
|
}
|
||||||
|
ls.count++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) {
|
||||||
|
switch seq := data.(type) {
|
||||||
|
case Iterator:
|
||||||
|
result = ls.IterPushBack(seq)
|
||||||
|
default:
|
||||||
|
ls.PushBack(data)
|
||||||
|
result = ls
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) IterPushBack(it Iterator) *LinkedList {
|
||||||
|
for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
|
||||||
|
ls.PushBack(item)
|
||||||
|
}
|
||||||
|
return ls
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) FirstNode() *ListNode {
|
||||||
|
return ls.first
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) First() (data any, err error) {
|
||||||
|
if ls.first != nil {
|
||||||
|
data = ls.first.data
|
||||||
|
} else {
|
||||||
|
err = errorListEmpty()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) LastNode() *ListNode {
|
||||||
|
return ls.last
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) Last() (data interface{}, err error) {
|
||||||
|
if ls.last != nil {
|
||||||
|
data = ls.last.data
|
||||||
|
} else {
|
||||||
|
err = errorListEmpty()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) NodeAt(index uint32) (node *ListNode, err error) {
|
||||||
|
if ls.count == 0 {
|
||||||
|
err = errorListEmpty()
|
||||||
|
} else if index > ls.count {
|
||||||
|
err = errorOutOfRange()
|
||||||
|
} else if index == ls.count-1 {
|
||||||
|
node = ls.last
|
||||||
|
} else {
|
||||||
|
current := ls.first
|
||||||
|
for pos := uint32(0); pos < index; pos++ {
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
node = current
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) At(index uint32) (data interface{}, err error) {
|
||||||
|
node, err := ls.NodeAt(index)
|
||||||
|
if err == nil {
|
||||||
|
data = node.data
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) Insert(index uint32, data interface{}) *ListNode {
|
||||||
|
var prev *ListNode
|
||||||
|
|
||||||
|
prev = nil
|
||||||
|
current := ls.first
|
||||||
|
for pos := uint32(0); current != nil && pos < index; pos++ {
|
||||||
|
prev = current
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
node := &ListNode{data, current}
|
||||||
|
|
||||||
|
if prev != nil {
|
||||||
|
prev.next = node
|
||||||
|
}
|
||||||
|
|
||||||
|
if ls.first == current {
|
||||||
|
ls.first = node
|
||||||
|
}
|
||||||
|
if node.next == nil {
|
||||||
|
ls.last = node
|
||||||
|
}
|
||||||
|
ls.count++
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) PushBackStringArray(items []string) {
|
||||||
|
for _, v := range items {
|
||||||
|
ls.PushBack(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// type TraverseOperator func(index uint32, elem interface{}, userData interface{}) (err error)
|
||||||
|
|
||||||
|
// func (self *LinkedList) Traverse(op TraverseOperator, user_data interface{}) (err error) {
|
||||||
|
// index := uint32(0)
|
||||||
|
// for current := self.first; current != nil; current = current.next {
|
||||||
|
// err = op(index, current.data, user_data)
|
||||||
|
// if err != nil {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// index++
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (self *LinkedList) Traverse2(observer Observer, abortOnError bool) (err error) {
|
||||||
|
// index := uint32(0)
|
||||||
|
// for current := self.first; current != nil; current = current.next {
|
||||||
|
// err = observer.Observe(current, index)
|
||||||
|
// if err != nil && abortOnError {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// index++
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
type EqualFunc func(current, target any) bool
|
||||||
|
|
||||||
|
func (ls *LinkedList) FindFirst(eqFunc EqualFunc, targetData any) (targetNode *ListNode) {
|
||||||
|
for current := ls.first; current != nil && targetNode == nil; current = current.next {
|
||||||
|
if eqFunc(current.data, targetData) {
|
||||||
|
targetNode = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinkedList) FindNext(eqFunc EqualFunc, startNode *ListNode) (targetNode *ListNode) {
|
||||||
|
if startNode != nil {
|
||||||
|
for current := startNode.next; current != nil && targetNode == nil; current = current.next {
|
||||||
|
if eqFunc(current.data, startNode.Data()) {
|
||||||
|
targetNode = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// type DataFeeder func(user_data interface{}) interface{}
|
||||||
|
// type NodeObserver func(node *ListNode, index uint32, userData interface{})
|
||||||
|
|
||||||
|
// func (self *LinkedList) FeedTail(feeder DataFeeder, feederUserData interface{}, observer NodeObserver, observerUserData interface{}) (count uint32) {
|
||||||
|
// count = 0
|
||||||
|
// for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) {
|
||||||
|
// // fmt.Println("Item", count, item)
|
||||||
|
// node := self.PushBack(item)
|
||||||
|
// if observer != nil {
|
||||||
|
// observer(node, count, observerUserData)
|
||||||
|
// }
|
||||||
|
// count++
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (self *LinkedList) FeedTail2(feeder Feeder, observer Observer, abortOnError bool) (count uint32, err error) {
|
||||||
|
// count = 0
|
||||||
|
// // item := feeder.Next()
|
||||||
|
// for item, err1 := feeder.Next(); item != nil; item, err1 = feeder.Next() {
|
||||||
|
// if err1 != nil {
|
||||||
|
// if err == nil {
|
||||||
|
// err = err1
|
||||||
|
// }
|
||||||
|
// if abortOnError {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // fmt.Println("Item", count, item)
|
||||||
|
// node := self.PushBack(item)
|
||||||
|
// if observer != nil {
|
||||||
|
// observer.Observe(node, count)
|
||||||
|
// }
|
||||||
|
// count++
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
func errorListEmpty() error {
|
||||||
|
return fmt.Errorf("List is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorOutOfRange() error {
|
||||||
|
return fmt.Errorf("Out of range")
|
||||||
|
}
|
||||||
+6
-6
@@ -50,13 +50,13 @@ func ListFromStrings(stringList []string) (list *ListType) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dict *ListType) ToString(opt FmtOpt) (s string) {
|
func (ls *ListType) ToString(opt FmtOpt) (s string) {
|
||||||
indent := GetFormatIndent(opt)
|
indent := GetFormatIndent(opt)
|
||||||
flags := GetFormatFlags(opt)
|
flags := GetFormatFlags(opt)
|
||||||
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
sb.WriteByte('[')
|
sb.WriteByte('[')
|
||||||
if len(*dict) > 0 {
|
if len(*ls) > 0 {
|
||||||
innerOpt := MakeFormatOptions(flags, indent+1)
|
innerOpt := MakeFormatOptions(flags, indent+1)
|
||||||
nest := strings.Repeat(" ", indent+1)
|
nest := strings.Repeat(" ", indent+1)
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ func (dict *ListType) ToString(opt FmtOpt) (s string) {
|
|||||||
sb.WriteByte('\n')
|
sb.WriteByte('\n')
|
||||||
sb.WriteString(nest)
|
sb.WriteString(nest)
|
||||||
}
|
}
|
||||||
for i, item := range []any(*dict) {
|
for i, item := range []any(*ls) {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
if flags&MultiLine != 0 {
|
if flags&MultiLine != 0 {
|
||||||
sb.WriteString(",\n")
|
sb.WriteString(",\n")
|
||||||
@@ -96,11 +96,11 @@ func (dict *ListType) ToString(opt FmtOpt) (s string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dict *ListType) String() string {
|
func (ls *ListType) String() string {
|
||||||
return dict.ToString(0)
|
return ls.ToString(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dict *ListType) TypeName() string {
|
func (ls *ListType) TypeName() string {
|
||||||
return "list"
|
return "list"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+69
-16
@@ -31,6 +31,41 @@ func newAppendTerm(tk *scan.Token) (inst *scan.Term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prependToList(ctx kern.ExprContext, opTerm *scan.Term, leftValue, rightValue any) (result any, err error) {
|
||||||
|
if list, ok := rightValue.(*kern.ListType); ok {
|
||||||
|
var it kern.Iterator
|
||||||
|
if it, ok = leftValue.(kern.Iterator); !ok {
|
||||||
|
if it, err = NewIterator(ctx, leftValue, nil); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ls := kern.NewLinkedList()
|
||||||
|
ls.SeqPushBack(it)
|
||||||
|
|
||||||
|
newList := kern.ListType(nil)
|
||||||
|
if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) {
|
||||||
|
newList = make([]any, 0, newSize)
|
||||||
|
for node := ls.FirstNode(); node != nil; node = node.Next() {
|
||||||
|
newList = append(newList, node.Data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range *list {
|
||||||
|
newList = append(newList, item)
|
||||||
|
}
|
||||||
|
result = &newList
|
||||||
|
|
||||||
|
// ***** EVENTUALMENTE ABILITARE LA MODIFICA DELLA VARIABILE
|
||||||
|
// ***** CON UN OPERATORE SPECIFICO
|
||||||
|
// if opTerm.Children[1].Symbol() == scan.SymVariable {
|
||||||
|
// ctx.UnsafeSetVar(opTerm.Children[1].Source(), result)
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
var leftValue, rightValue any
|
var leftValue, rightValue any
|
||||||
|
|
||||||
@@ -38,13 +73,39 @@ func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsList(rightValue) {
|
v, err = prependToList(ctx, opTerm, leftValue, rightValue)
|
||||||
list, _ := rightValue.(*kern.ListType)
|
return
|
||||||
newList := append(kern.ListType{leftValue}, *list...)
|
}
|
||||||
v = &newList
|
|
||||||
if opTerm.Children[1].Symbol() == scan.SymVariable {
|
func appendToList(ctx kern.ExprContext, opTerm *scan.Term, leftValue, rightValue any) (result any, err error) {
|
||||||
ctx.UnsafeSetVar(opTerm.Children[1].Source(), v)
|
if list, ok := leftValue.(*kern.ListType); ok {
|
||||||
|
var it kern.Iterator
|
||||||
|
if it, ok = rightValue.(kern.Iterator); !ok {
|
||||||
|
if it, err = NewIterator(ctx, rightValue, nil); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ls := kern.NewLinkedList()
|
||||||
|
ls.SeqPushBack(it)
|
||||||
|
|
||||||
|
newList := *list
|
||||||
|
if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) {
|
||||||
|
newList = make([]any, 0, newSize)
|
||||||
|
for _, item := range *list {
|
||||||
|
newList = append(newList, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for node := ls.FirstNode(); node != nil; node = node.Next() {
|
||||||
|
newList = append(newList, node.Data())
|
||||||
|
}
|
||||||
|
result = &newList
|
||||||
|
|
||||||
|
// ***** EVENTUALMENTE ABILITARE LA MODIFICA DELLA VARIABILE
|
||||||
|
// ***** CON UN OPERATORE SPECIFICO
|
||||||
|
// if opTerm.Children[0].Symbol() == scan.SymVariable {
|
||||||
|
// ctx.UnsafeSetVar(opTerm.Children[0].Source(), result)
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
||||||
}
|
}
|
||||||
@@ -58,16 +119,8 @@ func evalAppend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if kern.IsList(leftValue) {
|
v, err = appendToList(ctx, opTerm, leftValue, rightValue)
|
||||||
list, _ := leftValue.(*kern.ListType)
|
|
||||||
newList := append(*list, rightValue)
|
|
||||||
v = &newList
|
|
||||||
if opTerm.Children[0].Symbol() == scan.SymVariable {
|
|
||||||
ctx.UnsafeSetVar(opTerm.Children[0].Source(), v)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -39,7 +39,9 @@ func evalRightShift(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err = bitRightShift(opTerm, leftValue, rightValue)
|
if v, err = bitRightShift(opTerm, leftValue, rightValue); err != nil {
|
||||||
|
v, err = prependToList(ctx, opTerm, leftValue, rightValue)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +73,9 @@ func evalLeftShift(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err = bitLeftShift(opTerm, leftValue, rightValue)
|
if v, err = bitLeftShift(opTerm, leftValue, rightValue); err != nil {
|
||||||
|
v, err = appendToList(ctx, opTerm, leftValue, rightValue)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -54,10 +54,13 @@ func TestListParser(t *testing.T) {
|
|||||||
/* 38 */ {`[0,1,2,3,4][3:-1]`, kern.NewListA(int64(3)), nil},
|
/* 38 */ {`[0,1,2,3,4][3:-1]`, kern.NewListA(int64(3)), nil},
|
||||||
/* 30 */ {`[0,1,2,3,4][-3:-1]`, kern.NewListA(int64(2), int64(3)), nil},
|
/* 30 */ {`[0,1,2,3,4][-3:-1]`, kern.NewListA(int64(2), int64(3)), nil},
|
||||||
/* 40 */ {`[0,1,2,3,4][0:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
/* 40 */ {`[0,1,2,3,4][0:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||||
|
/* 41 */ {`[0] << $([1,2,3,4])`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||||
|
/* 42 */ {`L=[]; [1] >> L; L`, kern.NewListA(), nil},
|
||||||
|
/* 43 */ {`L=[]; L << [1]; L`, kern.NewListA(), nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.Setenv("EXPR_PATH", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// runTestSuiteSpec(t, section, inputs, 1)
|
// runTestSuiteSpec(t, section, inputs, 42)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,25 @@ func TestOperator(t *testing.T) {
|
|||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOperatorInsert(t *testing.T) {
|
||||||
|
section := "Operator-Insert"
|
||||||
|
inputs := []inputType{
|
||||||
|
/* 1 */ {`["a", "b"] << nil`, kern.NewListA("a", "b"), nil},
|
||||||
|
/* 2 */ {`["a", "b"] << []`, kern.NewListA("a", "b"), nil},
|
||||||
|
/* 3 */ {`["a", "b"] << 3`, kern.NewListA("a", "b", int64(3)), nil},
|
||||||
|
/* 4 */ {`3 << ["a", "b"]`, nil, `[1:5] left operand '3' [integer] and right operand '["a", "b"]' [list] are not compatible with operator "<<"`},
|
||||||
|
/* 5 */ {`nil >> ["a", "b"]`, kern.NewListA("a", "b"), nil},
|
||||||
|
/* 6 */ {`[] >> ["a", "b"]`, kern.NewListA("a", "b"), nil},
|
||||||
|
/* 7 */ {`["a", "b"] << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||||
|
/* 8 */ {`L=["a", "b"]; L << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||||
|
/* 9 */ {`L=["a", "b"]; L << $([1,2,3]); L`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||||
|
/* 10 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
|
||||||
|
}
|
||||||
|
|
||||||
|
// runTestSuiteSpec(t, section, inputs, 9)
|
||||||
|
runTestSuite(t, section, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
func TestOperatorDigest(t *testing.T) {
|
func TestOperatorDigest(t *testing.T) {
|
||||||
section := "Operator-Digest"
|
section := "Operator-Digest"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
|
|||||||
+9
-9
@@ -32,15 +32,15 @@ func testStringEndingWithOperator(source string) bool {
|
|||||||
return scan.StringEndsWithOperator(source)
|
return scan.StringEndsWithOperator(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStringArrayEndingWithOperatorSpec(t *testing.T, section string, inputs []inputType, spec ...int) {
|
// func testStringArrayEndingWithOperatorSpec(t *testing.T, section string, inputs []inputType, spec ...int) {
|
||||||
for i := range spec {
|
// for i := range spec {
|
||||||
if spec[i] < 1 || spec[i] > len(inputs) {
|
// if spec[i] < 1 || spec[i] > len(inputs) {
|
||||||
t.Errorf("Invalid test spec index: %d (must be between 1 and %d)", spec[i], len(inputs))
|
// t.Errorf("Invalid test spec index: %d (must be between 1 and %d)", spec[i], len(inputs))
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
doEndingTest(t, section, inputs[spec[i]-1], spec[i]-1)
|
// doEndingTest(t, section, inputs[spec[i]-1], spec[i]-1)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func testStringArrayEndingWithOperator(t *testing.T, section string, inputs []inputType) {
|
func testStringArrayEndingWithOperator(t *testing.T, section string, inputs []inputType) {
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
|
|||||||
Reference in New Issue
Block a user