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 }