Skip to content

Instantly share code, notes, and snippets.

@chrisbarrett
Created May 17, 2017 08:01
Show Gist options
  • Save chrisbarrett/a8b0c94b6d71bda91b80bc8c8a683844 to your computer and use it in GitHub Desktop.
Save chrisbarrett/a8b0c94b6d71bda91b80bc8c8a683844 to your computer and use it in GitHub Desktop.
// Compiler from Go types to an S-Expression representation.
//
// The output a drop-in replacement for the Elisp JSON parser output, and can be
// consumed directly with `read`.
package main
import (
"strconv"
"strings"
)
type JsRepr interface {
ToJs() js
}
// TODO: Implement conversions from k8s types to this JSON representation.
func Compile(o JsRepr) string {
return o.ToJs().toSexp().render()
}
// JSON representation
type js interface {
toSexp() sexp
}
type jarray struct {
contents []js
}
func (a jarray) toSexp() sexp {
sexps := make([]sexp, len(a.contents))
for i := range a.contents {
entry := a.contents[i]
sexps[i] = entry.toSexp()
}
return svector{sexps}
}
type jobject struct {
contents map[string]js
}
func (o jobject) toSexp() sexp {
kvps := make([]sexp, len(o.contents))
i := 0
for key, value := range o.contents {
car := ssymbol{key}
cdr := value.toSexp()
kvps[i] = scons{car, cdr}
i++
}
return slist{kvps}
}
type jstring struct {
value string
}
func (s jstring) toSexp() sexp {
return sstring{s.value}
}
type jnumber struct {
value float64
}
func (n jnumber) toSexp() sexp {
return snumber{n.value}
}
type jtrue struct{}
func (t jtrue) toSexp() sexp {
return ssymbol{"t"}
}
type jfalse struct{}
func (f jfalse) toSexp() sexp {
return ssymbol{":json-false"}
}
type jnull struct{}
func (n jnull) toSexp() sexp {
return ssymbol{"nil"}
}
// Raw S-Expressions
type sexp interface {
render() string
}
type slist struct {
contents []sexp
}
func (ls slist) render() string {
inner := make([]string, len(ls.contents))
for i := range ls.contents {
entry := ls.contents[i]
inner[i] = entry.render()
}
rendered := strings.Join(inner, " ")
return "(" + rendered + ")"
}
type svector struct {
contents []sexp
}
func (v svector) render() string {
inner := make([]string, len(v.contents))
for i := range v.contents {
entry := v.contents[i]
inner[i] = entry.render()
}
rendered := strings.Join(inner, " ")
return "[" + rendered + "]"
}
type scons struct {
car sexp
cdr sexp
}
func (c scons) render() string {
car := c.car.render()
cdr := c.cdr.render()
return "(" + car + " . " + cdr + ")"
}
type snumber struct {
value float64
}
func (n snumber) render() string {
return strconv.FormatFloat(n.value, 'f', -1, 64)
}
type sstring struct {
value string
}
func (s sstring) render() string {
return s.value
}
type ssymbol struct {
value string
}
func (s ssymbol) render() string {
return s.value
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment