listutils.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package glisp
  2. import (
  3. "errors"
  4. )
  5. var NotAList = errors.New("not a list")
  6. func ListToArray(expr Sexp) ([]Sexp, error) {
  7. if !IsList(expr) {
  8. return nil, NotAList
  9. }
  10. arr := make([]Sexp, 0)
  11. for expr != SexpNull {
  12. list := expr.(SexpPair)
  13. arr = append(arr, list.head)
  14. expr = list.tail
  15. }
  16. return arr, nil
  17. }
  18. func MakeList(expressions []Sexp) Sexp {
  19. if len(expressions) == 0 {
  20. return SexpNull
  21. }
  22. return Cons(expressions[0], MakeList(expressions[1:]))
  23. }
  24. func MapList(env *Glisp, fun SexpFunction, expr Sexp) (Sexp, error) {
  25. if expr == SexpNull {
  26. return SexpNull, nil
  27. }
  28. var list SexpPair
  29. switch e := expr.(type) {
  30. case SexpPair:
  31. list = e
  32. default:
  33. return SexpNull, NotAList
  34. }
  35. var err error
  36. list.head, err = env.Apply(fun, []Sexp{list.head})
  37. if err != nil {
  38. return SexpNull, err
  39. }
  40. list.tail, err = MapList(env, fun, list.tail)
  41. if err != nil {
  42. return SexpNull, err
  43. }
  44. return list, nil
  45. }
  46. func ConcatList(a SexpPair, b Sexp) (Sexp, error) {
  47. if !IsList(b) {
  48. return SexpNull, NotAList
  49. }
  50. if a.tail == SexpNull {
  51. return Cons(a.head, b), nil
  52. }
  53. switch t := a.tail.(type) {
  54. case SexpPair:
  55. newtail, err := ConcatList(t, b)
  56. if err != nil {
  57. return SexpNull, err
  58. }
  59. return Cons(a.head, newtail), nil
  60. }
  61. return SexpNull, NotAList
  62. }