package walk import ( "math" "fmt" ) type AtomType int64 const ( AtomNull AtomType = iota AtomBool AtomNumber AtomTerminal AtomStringTerminal AtomStringRune ) type Atom struct { Typ AtomType data uint64 } func NewAtomNull() Atom { return Atom { Typ: AtomNull, data: 0, } } func NewAtomBool(v bool) Atom { if v { return Atom { Typ: AtomBool, data: 1, } } else { return Atom { Typ: AtomBool, data: 0, } } } func NewAtomNumber(v float64) Atom { return Atom { Typ: AtomNumber, data: math.Float64bits(v), } } func NewAtomTerminal(v ValueTerminal) Atom { return Atom { Typ: AtomTerminal, data: uint64(v), } } func NewAtomStringTerminal() Atom { return Atom { Typ: AtomStringTerminal, data: 0, } } func NewAtomStringRune(v rune) Atom { return Atom { Typ: AtomStringRune, data: uint64(v), } } func (v Atom) String() string { switch v.Typ { case AtomNull: return "null" case AtomBool: if v.data == 0 { return "false" } return "true" case AtomNumber: return fmt.Sprintf("%v", math.Float64frombits(v.data)) case AtomTerminal: switch ValueTerminal(v.data) { case MapBegin: return "{" case MapEnd: return "}" case ArrayBegin: return "[" case ArrayEnd: return "]" default: panic("Invalid terminal atom") } case AtomStringTerminal: return "\"" case AtomStringRune: return string(rune(v.data)) default: panic("Invalid atom type") } }