Files
expr/operator-insert.go
T

148 lines
3.6 KiB
Go

// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-insert.go
package expr
import (
"git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan"
)
//-------- prepend term
func newPrependTerm(tk *scan.Token) (inst *scan.Term) {
return &scan.Term{
Tk: *tk,
Children: make([]*scan.Term, 0, 2),
Position: scan.PosInfix,
Priority: scan.PriInsert,
EvalFunc: evalPrepend,
}
}
func newAppendTerm(tk *scan.Token) (inst *scan.Term) {
return &scan.Term{
Tk: *tk,
Children: make([]*scan.Term, 0, 2),
Position: scan.PosInfix,
Priority: scan.PriInsert,
EvalFunc: evalAppend,
}
}
func prependToList(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 {
it = NewFormalIterator(leftValue)
}
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
} else if list, ok := rightValue.(*kern.LinkedList); ok {
var it kern.Iterator
if it, ok = leftValue.(kern.Iterator); !ok {
it = NewFormalIterator(leftValue)
}
result = list.SeqPushBack(it)
} else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
return
}
v, err = prependToList(opTerm, leftValue, rightValue)
return
}
func appendToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err error) {
if list, ok := leftValue.(*kern.ListType); ok {
var it kern.Iterator
if it, ok = rightValue.(kern.Iterator); !ok {
it = NewFormalIterator(rightValue)
}
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
} else if list, ok := leftValue.(*kern.LinkedList); ok {
var it kern.Iterator
if it, ok = rightValue.(kern.Iterator); !ok {
it = NewFormalIterator(rightValue)
}
result = list.SeqPushBack(it)
} else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalAppend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
return
}
v, err = appendToList(opTerm, leftValue, rightValue)
return
}
// func evalAssignAppend(ctx ExprContext, self *term) (v any, err error) {
// var leftValue, rightValue any
// if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
// return
// }
// if IsList(leftValue) {
// list, _ := leftValue.(*ListType)
// newList := append(*list, rightValue)
// v = &newList
// if
// } else {
// err = self.errIncompatibleTypes(leftValue, rightValue)
// }
// return
// }
// init
func init() {
scan.RegisterTermConstructor(scan.SymPlusGreater, newPrependTerm)
scan.RegisterTermConstructor(scan.SymLessPlus, newAppendTerm)
}