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 { hashed := pair.Value.(Hasher) right, ok := obj.Pairs[hashed.Hash()] if !ok { return -1 } val := pair.Value.Compare(right.Value) if val != 0 { return val } } return 0 } return -1 }