This commit is contained in:
2024-05-14 12:10:58 +02:00
parent a9bb79b01c
commit 59911aebb9
645 changed files with 263320 additions and 0 deletions

119
vendor/github.com/glycerine/zygomys/zygo/listutils.go generated vendored Normal file
View File

@@ -0,0 +1,119 @@
package zygo
import (
"errors"
"fmt"
)
var NotAList = errors.New("not a list")
func ListToArray(expr Sexp) ([]Sexp, error) {
if !IsList(expr) {
return nil, NotAList
}
arr := make([]Sexp, 0)
for expr != SexpNull {
list := expr.(*SexpPair)
arr = append(arr, list.Head)
expr = list.Tail
}
return arr, nil
}
func MakeList(expressions []Sexp) Sexp {
if len(expressions) == 0 {
return SexpNull
}
return Cons(expressions[0], MakeList(expressions[1:]))
}
func MapList(env *Zlisp, fun *SexpFunction, expr Sexp) (Sexp, error) {
if expr == SexpNull {
return SexpNull, nil
}
var list = &SexpPair{}
switch e := expr.(type) {
case *SexpPair:
list.Head = e.Head
list.Tail = e.Tail
default:
return SexpNull, NotAList
}
var err error
list.Head, err = env.Apply(fun, []Sexp{list.Head})
if err != nil {
return SexpNull, err
}
list.Tail, err = MapList(env, fun, list.Tail)
if err != nil {
return SexpNull, err
}
return list, nil
}
// O(n^2) for n total nodes in all lists. So this is
// not super efficient. We have to
// find the tail of each list in turn by
// linear search. Avoid lists if possible in favor
// of arrays.
func ConcatLists(a *SexpPair, bs []Sexp) (Sexp, error) {
result := a
for _, b := range bs {
res, err := ConcatTwoLists(result, b)
if err != nil {
return SexpNull, err
}
x, ok := res.(*SexpPair)
if !ok {
return SexpNull, NotAList
}
result = x
}
return result, nil
}
func ConcatTwoLists(a *SexpPair, b Sexp) (Sexp, error) {
if !IsList(b) {
return SexpNull, NotAList
}
if a.Tail == SexpNull {
return Cons(a.Head, b), nil
}
switch t := a.Tail.(type) {
case *SexpPair:
newtail, err := ConcatTwoLists(t, b)
if err != nil {
return SexpNull, err
}
return Cons(a.Head, newtail), nil
}
return SexpNull, NotAList
}
func ListLen(expr Sexp) (int, error) {
sz := 0
var list *SexpPair
ok := false
for expr != SexpNull {
list, ok = expr.(*SexpPair)
if !ok {
return 0, fmt.Errorf("ListLen() called on non-list")
}
sz++
expr = list.Tail
}
return sz, nil
}