<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/walk
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-21 16:22:16 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-21 16:22:16 +0100
commit12c1d179f32c38a929fcc9adb326a9f44c8288ae (patch)
treed685922ed93708cbaf01357a95989283a7b86443 /walk
parent5d8582711936cae3c42f2645d0f304418b17fb7e (diff)
downloadstred-go-12c1d179f32c38a929fcc9adb326a9f44c8288ae.tar
Replaces the interfaces implementation of Atom with a tagged union based implementation
Diffstat (limited to 'walk')
-rw-r--r--walk/walk.go150
1 files changed, 115 insertions, 35 deletions
diff --git a/walk/walk.go b/walk/walk.go
index 490a6f2..949b6a2 100644
--- a/walk/walk.go
+++ b/walk/walk.go
@@ -50,7 +50,7 @@ const (
MapEnd
)
func (value TerminalValue) Atomise(in []Atom) []Atom {
- return append(in, value)
+ return append(in, NewAtomTerminal(value))
}
func (value TerminalValue) String() string {
switch value {
@@ -69,7 +69,7 @@ func (value TerminalValue) String() string {
type ValueNull struct {}
func (value ValueNull) Atomise(in []Atom) []Atom {
- return append(in, value)
+ return append(in, NewAtomNull())
}
func (value ValueNull) String() string {
return "null"
@@ -77,7 +77,7 @@ func (value ValueNull) String() string {
type ValueBool bool
func (value ValueBool) Atomise(in []Atom) []Atom {
- return append(in, value)
+ return append(in, NewAtomBool(bool(value)))
}
func (value ValueBool) String() string {
if value {
@@ -89,38 +89,113 @@ func (value ValueBool) String() string {
type ValueNumber float64
func (value ValueNumber) Atomise(in []Atom) []Atom {
- return append(in, value)
+ return append(in, NewAtomNumber(float64(value)))
}
func (value ValueNumber) String() string {
v := float64(value)
return fmt.Sprintf("%f", v)
}
-type StringTerminal struct {}
-func (value StringTerminal) String() string {
- return "\""
-}
-
-type StringAtom rune
-func (value StringAtom) String() string {
- return string(value)
-}
-
type ValueString string
func (value ValueString) Atomise(in []Atom) []Atom {
- in = append(in, StringTerminal{})
+ in = append(in, NewAtomStringTerminal())
for _, char := range value {
- in = append(in, StringAtom(char))
+ in = append(in, NewAtomStringRune(char))
}
- in = append(in, StringTerminal{})
+ in = append(in, NewAtomStringTerminal())
return in
}
func (value ValueString) String() string {
return fmt.Sprintf("\"%s\"", string(value))
}
-type Atom interface {
- String() string
+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 TerminalValue) 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 TerminalValue(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")
+ }
}
type WalkValue interface {
@@ -481,12 +556,12 @@ func Compound(in []Atom) (out []WalkValue, error error) {
i := 0
inString := false
for _, atom := range in {
- switch atom.(type) {
- case TerminalValue, ValueNull, ValueBool, ValueNumber:
+ switch atom.Typ {
+ case AtomNull, AtomBool, AtomNumber, AtomTerminal:
if !inString {
numValues++
}
- case StringTerminal:
+ case AtomStringTerminal:
if inString {
numValues++
}
@@ -501,32 +576,37 @@ func Compound(in []Atom) (out []WalkValue, error error) {
}
atom := in[i]
i++
- switch v := atom.(type) {
- case TerminalValue, ValueNull, ValueBool, ValueNumber:
- out = append(out, v.(WalkValue))
+ switch atom.Typ {
+ case AtomNull:
+ out = append(out, ValueNull{})
continue
- case StringAtom:
+ case AtomBool:
+ out = append(out, ValueBool(atom.data != 0))
+ continue
+ case AtomNumber:
+ out = append(out, ValueNumber(math.Float64frombits(atom.data)))
+ continue
+ case AtomTerminal:
+ out = append(out, TerminalValue(atom.data))
+ continue
+ case AtomStringRune:
return nil, CompoundRuneOutsideString
- case StringTerminal:
+ case AtomStringTerminal:
default:
return nil, CompoundUnknownAtom
}
// Handle string start
var builder strings.Builder
- loop: for {
+ for {
if i >= len(in) {
return nil, CompoundMissingEnd
}
atom := in[i]
i++
- switch v := atom.(type) {
- case StringTerminal:
- break loop
- case StringAtom, ValueNull, ValueBool, ValueNumber, TerminalValue:
- builder.WriteString(v.String())
- default:
- return nil, CompoundInvalidStringAtom
+ if atom.Typ == AtomStringTerminal {
+ break
}
+ builder.WriteString(atom.String())
}
out = append(out, ValueString(builder.String()))
}