92 lines
1.5 KiB
Go
92 lines
1.5 KiB
Go
package object
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"hash/fnv"
|
|
"strings"
|
|
)
|
|
|
|
type HashKey struct {
|
|
Type ObjectType
|
|
Value uint64
|
|
}
|
|
|
|
func (b *Boolean) HashKey() HashKey {
|
|
var value uint64
|
|
|
|
if b.Value {
|
|
value = 1
|
|
} else {
|
|
value = 0
|
|
}
|
|
|
|
return HashKey{Type: b.Type(), Value: value}
|
|
}
|
|
|
|
func (i *Integer) HashKey() HashKey {
|
|
return HashKey{Type: i.Type(), Value: uint64(i.Value)}
|
|
}
|
|
|
|
func (s *String) HashKey() HashKey {
|
|
h := fnv.New64a()
|
|
h.Write([]byte(s.Value))
|
|
|
|
return HashKey{Type: s.Type(), Value: h.Sum64()}
|
|
}
|
|
|
|
type HashPair struct {
|
|
Key Object
|
|
Value Object
|
|
}
|
|
|
|
type Hash struct {
|
|
Pairs map[HashKey]HashPair
|
|
}
|
|
|
|
func (h *Hash) Type() ObjectType {
|
|
return HASH_OBJ
|
|
}
|
|
func (h *Hash) Inspect() string {
|
|
var out bytes.Buffer
|
|
|
|
pairs := []string{}
|
|
for _, pair := range h.Pairs {
|
|
pairs = append(pairs, fmt.Sprintf("%s: %s", pair.Key.Inspect(), pair.Value.Inspect()))
|
|
}
|
|
|
|
out.WriteString("{")
|
|
out.WriteString(strings.Join(pairs, ", "))
|
|
out.WriteString("}")
|
|
|
|
return out.String()
|
|
}
|
|
func (h *Hash) String() string {
|
|
return h.Inspect()
|
|
}
|
|
func (h *Hash) Equal(other Object) bool {
|
|
if obj, ok := other.(*Hash); ok {
|
|
if len(h.Pairs) != len(obj.Pairs) {
|
|
return false
|
|
}
|
|
for _, pair := range h.Pairs {
|
|
left := pair.Value
|
|
hashed := left.(Hashable)
|
|
right, ok := obj.Pairs[hashed.HashKey()]
|
|
if !ok {
|
|
return false
|
|
}
|
|
cmp, ok := left.(Comparable)
|
|
if !ok {
|
|
return false
|
|
}
|
|
if !cmp.Equal(right.Value) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
return false
|
|
}
|