peachy-go/csexp/sexp.go

88 lines
1.4 KiB
Go
Raw Normal View History

2024-08-29 05:01:38 +00:00
package csexp
import (
"bytes"
"fmt"
"io"
"slices"
"git.codemonkeysoftware.net/b/peachy-go/shortcircuit"
)
type Sexp interface {
isSexp()
WriteTo(w io.Writer) (n int64, err error)
String() string
Equal(Sexp) bool
Clone() Sexp
}
type Atom []byte
func (a Atom) isSexp() {}
func (a Atom) WriteTo(w io.Writer) (int64, error) {
if scw, ok := w.(*shortcircuit.Writer); ok && scw.Failed() {
return 0, nil
}
n, err := fmt.Fprintf(w, "%d:%s", len(a), []byte(a))
return int64(n), err
}
func (a Atom) String() string {
var buf bytes.Buffer
a.WriteTo(&buf)
return buf.String()
}
func (a Atom) Equal(s Sexp) bool {
a2, ok := s.(Atom)
return ok && bytes.Equal([]byte(a), []byte(a2))
}
func (a Atom) Clone() Sexp {
return Atom(bytes.Clone([]byte(a)))
}
type List []Sexp
func (l List) isSexp() {}
func (l List) WriteTo(w io.Writer) (int64, error) {
scw := shortcircuit.EnsureWriter(w)
if scw.Failed() {
return 0, nil
}
io.WriteString(scw, "(")
for _, child := range l {
child.WriteTo(scw)
}
io.WriteString(scw, ")")
return scw.Status()
}
func (l List) String() string {
var buf bytes.Buffer
l.WriteTo(&buf)
return buf.String()
}
func (l List) Equal(s Sexp) bool {
l2, ok := s.(List)
return ok && slices.EqualFunc(l, l2, Sexp.Equal)
}
func (l List) Clone() Sexp {
l2 := make(List, len(l))
for i, child := range l {
l2[i] = child.Clone()
}
return l2
}
func Parse(data []byte) (Sexp, error) {
return nil, nil
}