<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/walk/atom.go
blob: 299c39dbacd5267579eba5346102ed661a65dc1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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 (v Atom) Bool() bool {
	if v.Typ != AtomBool {
		panic("Tried to use non-bool as bool")
	}
	return v.data == 1
}
func NewAtomNumber(v float64) Atom {
	return Atom {
		Typ: AtomNumber,
		data: math.Float64bits(v),
	}
}
func (v Atom) Number() float64 {
	if v.Typ != AtomNumber {
		panic("Tried to use non-number as number")
	}
	return math.Float64frombits(v.data)
}
func NewAtomTerminal(v ValueTerminal) Atom {
	return Atom {
		Typ: AtomTerminal,
		data: uint64(v),
	}
}
func (v Atom) Terminal() ValueTerminal {
	if v.Typ != AtomTerminal {
		panic("Tried to use non-terminal as terminal")
	}
	return ValueTerminal(v.data)
}
func NewAtomStringTerminal() Atom {
	return Atom {
		Typ: AtomStringTerminal,
		data: 0,
	}
}
func NewAtomStringRune(v rune) Atom {
	return Atom {
		Typ: AtomStringRune,
		data: uint64(v),
	}
}
func (v Atom) StringRune() rune {
	if v.Typ != AtomStringRune {
		panic("Tried to use non-stringrune as stringrune")
	}
	return rune(v.data)
}
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")
	}
}