// 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) }