Files
monkey/internal/object/hash.go
csmith 99f7553d67
Some checks failed
Publish Image / publish (push) Waiting to run
Test / build (push) Waiting to run
Build / build (push) Has been cancelled
refactor objects
2024-04-01 17:34:10 -04:00

119 lines
1.9 KiB
Go

package object
import (
"bytes"
"fmt"
"strings"
)
type HashKey struct {
Type Type
Value uint64
}
type HashPair struct {
Key Object
Value Object
}
type Hash struct {
Pairs map[HashKey]HashPair
}
func (h *Hash) Len() int {
return len(h.Pairs)
}
func (h *Hash) Bool() bool {
return len(h.Pairs) > 0
}
func (h *Hash) Type() Type {
return HashType
}
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) Add(other Object) (Object, error) {
if other.Type() != h.Type() {
return nil, NewBinaryOpError(h, other, "+")
}
pairs := make(map[HashKey]HashPair)
for k, v := range h.Pairs {
pairs[k] = v
}
for k, v := range other.(*Hash).Pairs {
pairs[k] = v
}
return &Hash{Pairs: pairs}, nil
}
func (h *Hash) Get(index Object) (Object, error) {
key, ok := index.(Hasher)
if !ok {
return nil, fmt.Errorf("invalid hash key %s", index.Type())
}
pair, found := h.Pairs[key.Hash()]
if !found {
return Null{}, nil
}
return pair.Value, nil
}
func (h *Hash) Set(index, other Object) error {
key, ok := index.(Hasher)
if !ok {
return fmt.Errorf("invalid hash key %s", index.Type())
}
h.Pairs[key.Hash()] = HashPair{Key: index, Value: other}
return nil
}
func (h *Hash) Compare(other Object) int {
if obj, ok := other.(*Hash); ok {
if len(h.Pairs) != len(obj.Pairs) {
return -1
}
for _, pair := range h.Pairs {
left := pair.Value
hashed := left.(Hasher)
right, ok := obj.Pairs[hashed.Hash()]
if !ok {
return -1
}
cmp, ok := left.(Comparable)
if !ok {
return -1
}
if cmp.Compare(right.Value) != 0 {
return cmp.Compare(right.Value)
}
}
return 0
}
return -1
}