Skip to content

Commit

Permalink
Merge pull request #30 from tsandall/basic-indexing
Browse files Browse the repository at this point in the history
Add basic indexing support
  • Loading branch information
tsandall committed May 6, 2016
2 parents 3d10912 + 81459db commit 77a7845
Show file tree
Hide file tree
Showing 63 changed files with 2,990 additions and 611 deletions.
51 changes: 50 additions & 1 deletion eval/hashmap.go
Expand Up @@ -17,10 +17,33 @@ type hashEntry struct {

type hashMap struct {
table map[int]*hashEntry
size int
}

func newHashMap() *hashMap {
return &hashMap{make(map[int]*hashEntry)}
return &hashMap{make(map[int]*hashEntry), 0}
}

func (hm *hashMap) Copy() *hashMap {
cpy := newHashMap()
hm.Iter(func(k, v opalog.Value) bool {
cpy.Put(k, v)
return false
})
return cpy
}

func (hm *hashMap) Equal(other *hashMap) bool {
if hm.Len() != other.Len() {
return false
}
return !hm.Iter(func(k, v opalog.Value) bool {
ov := other.Get(k)
if ov == nil {
return true
}
return !v.Equal(ov)
})
}

func (hm *hashMap) Get(k opalog.Value) opalog.Value {
Expand All @@ -33,6 +56,15 @@ func (hm *hashMap) Get(k opalog.Value) opalog.Value {
return nil
}

func (hm *hashMap) Hash() int {
var hash int
hm.Iter(func(k, v opalog.Value) bool {
hash += k.Hash() + v.Hash()
return false
})
return hash
}

// Iter invokes the iter function for each element in the hashMap.
// If the iter function returns true, iteration stops and the return value is true.
// If the iter function never returns true, iteration proceeds through all elements
Expand All @@ -48,6 +80,10 @@ func (hm *hashMap) Iter(iter func(opalog.Value, opalog.Value) bool) bool {
return false
}

func (hm *hashMap) Len() int {
return hm.size
}

func (hm *hashMap) Put(k opalog.Value, v opalog.Value) {
hash := k.Hash()
head := hm.table[hash]
Expand All @@ -58,6 +94,7 @@ func (hm *hashMap) Put(k opalog.Value, v opalog.Value) {
}
}
hm.table[hash] = &hashEntry{k: k, v: v, next: head}
hm.size++
}

func (hm *hashMap) String() string {
Expand All @@ -68,3 +105,15 @@ func (hm *hashMap) String() string {
})
return "{" + strings.Join(buf, ", ") + "}"
}

// Update returns a new hashMap with elements from the other hashMap put into this hashMap.
// If the other hashMap contains elements with the same key as this hashMap, the value
// from the other hashMap overwrites the value from this hashMap.
func (hm *hashMap) Update(other *hashMap) *hashMap {
updated := hm.Copy()
other.Iter(func(k, v opalog.Value) bool {
updated.Put(k, v)
return false
})
return updated
}
35 changes: 34 additions & 1 deletion eval/hashmap_test.go
Expand Up @@ -24,7 +24,7 @@ func TestHashmapOverwrite(t *testing.T) {
}
}

func TestIter(t *testing.T) {
func TestHashmapIter(t *testing.T) {
m := newHashMap()
keys := []opalog.Number{opalog.Number(1), opalog.Number(2), opalog.Number(1.4)}
value := opalog.Null{}
Expand All @@ -49,3 +49,36 @@ func TestIter(t *testing.T) {
t.Errorf("Expected %v but got %v", expected, results)
}
}

func TestHashmapCompare(t *testing.T) {
m := newHashMap()
n := newHashMap()
k1 := opalog.String("k1")
k2 := opalog.String("k2")
k3 := opalog.String("k3")
v1 := parseTerm(`[{"a": 1, "b": 2}, {"c": 3}]`).Value
v2 := parseTerm(`[{"a": 1, "b": 2}, {"c": 4}]`).Value
m.Put(k1, v1)
if m.Equal(n) {
t.Errorf("Expected hash maps of different size to be non-equal for %v and %v", m, n)
return
}
n.Put(k1, v1)
if m.Hash() != n.Hash() {
t.Errorf("Expected hashes to equal for %v and %v", m, n)
return
}
if !m.Equal(n) {
t.Errorf("Expected hash maps to be equal for %v and %v", m, n)
return
}
m.Put(k2, v2)
n.Put(k3, v2)
if m.Hash() == n.Hash() {
t.Errorf("Did not expect hashes to equal for %v and %v", m, n)
return
}
if m.Equal(n) {
t.Errorf("Did not expect hash maps to be equal for %v and %v", m, n)
}
}

0 comments on commit 77a7845

Please sign in to comment.