mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-18 13:01:11 +01:00
added
This commit is contained in:
119
vendor/github.com/glycerine/zygomys/zygo/listutils.go
generated
vendored
Normal file
119
vendor/github.com/glycerine/zygomys/zygo/listutils.go
generated
vendored
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user