-
Notifications
You must be signed in to change notification settings - Fork 8
/
value.go
129 lines (106 loc) · 2.45 KB
/
value.go
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
120
121
122
123
124
125
126
127
128
129
package bytecode
import (
"fmt"
"strconv"
"strings"
"evylang.dev/evy/pkg/parser"
)
type value interface {
Type() *parser.Type
Equals(value) bool
String() string
}
type numVal float64
func (n numVal) Type() *parser.Type { return parser.NUM_TYPE }
func (n numVal) String() string {
return strconv.FormatFloat(float64(n), 'f', -1, 64)
}
func (n numVal) Equals(v value) bool {
n2, ok := v.(numVal)
if !ok {
panic("internal error: Num.Equals called with non-Num value")
}
return n == n2
}
type boolVal bool
func (boolVal) Type() *parser.Type { return parser.BOOL_TYPE }
func (b boolVal) String() string {
return strconv.FormatBool(bool(b))
}
func (b boolVal) Equals(v value) bool {
b2, ok := v.(boolVal)
if !ok {
panic("internal error: Bool.Equals called with non-Bool value")
}
return b == b2
}
type stringVal string
func (s stringVal) Type() *parser.Type { return parser.STRING_TYPE }
func (s stringVal) String() string {
return string(s)
}
func (s stringVal) Equals(v value) bool {
s2, ok := v.(stringVal)
if !ok {
panic("internal error: String.Equals called with non-String value")
}
return s == s2
}
type arrayVal struct {
Elements []value
}
func (a arrayVal) Type() *parser.Type {
// Revisit this when adding the typeof builtin: https://github.com/evylang/evy/pull/305#discussion_r1531149977
return parser.GENERIC_ARRAY
}
func (a arrayVal) String() string {
elements := make([]string, len(a.Elements))
for i, e := range a.Elements {
elements[i] = e.String()
}
return "[" + strings.Join(elements, " ") + "]"
}
func (a arrayVal) Equals(v value) bool {
a2, ok := v.(arrayVal)
if !ok {
panic("internal error: Array.Equals called with non-Array value")
}
if len(a.Elements) != len(a2.Elements) {
return false
}
elements2 := a2.Elements
for i, e := range a.Elements {
e2 := elements2[i]
if !e.Equals(e2) {
return false
}
}
return true
}
type mapVal map[string]value
func (m mapVal) Type() *parser.Type {
return parser.GENERIC_MAP
}
func (m mapVal) String() string {
pairs := []string{}
for k, v := range m {
pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
}
return "{" + strings.Join(pairs, ", ") + "}"
}
func (m mapVal) Equals(v value) bool {
m2, ok := v.(mapVal)
if !ok {
panic("internal error: Map.Equals called with non-Map value")
}
if len(m) != len(m2) {
return false
}
for key, val := range m {
val2 := m2[key]
if val2 == nil || !val.Equals(val2) {
return false
}
}
return true
}