From 54970c34f06cc23dd32ca7b0855c66be0cd9cee7 Mon Sep 17 00:00:00 2001 From: Ben Kalman Date: Tue, 28 Jun 2016 10:03:00 -0700 Subject: [PATCH] Add set indexing for paths (#1922) --- go/types/path.go | 20 ++++++++++++----- go/types/path_test.go | 52 ++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/go/types/path.go b/go/types/path.go index 2cb9eca143..2f825eb296 100644 --- a/go/types/path.go +++ b/go/types/path.go @@ -180,22 +180,30 @@ func newHashIndexPart(h hash.Hash) hashIndexPart { } func (hip hashIndexPart) Resolve(v Value) (res Value) { - m, ok := v.(Map) - if !ok { + var seq orderedSequence + var getCurrentValue func(cur *sequenceCursor) Value + + switch v := v.(type) { + case Set: + seq = v.seq + getCurrentValue = func(cur *sequenceCursor) Value { return cur.current().(Value) } + case Map: + seq = v.seq + getCurrentValue = func(cur *sequenceCursor) Value { return cur.current().(mapEntry).value } + default: return nil } - cur := newCursorAt(m.seq, orderedKeyFromHash(hip.h), false, false) + cur := newCursorAt(seq, orderedKeyFromHash(hip.h), false, false) if !cur.valid() { return nil } - entry := cur.current().(mapEntry) - if entry.key.Hash() != hip.h { + if getCurrentKey(cur).h != hip.h { return nil } - return entry.value + return getCurrentValue(cur) } func (hip hashIndexPart) String() string { diff --git a/go/types/path_test.go b/go/types/path_test.go index 9eeffbd6d4..6a24946390 100644 --- a/go/types/path_test.go +++ b/go/types/path_test.go @@ -94,48 +94,60 @@ func TestPathHashIndex(t *testing.T) { b := Bool(true) br := NewRef(b) i := Number(0) - s := String("foo") - l := NewList(b, i, s) + str := String("foo") + l := NewList(b, i, str) lr := NewRef(l) m := NewMap( b, br, br, i, - i, s, + i, str, l, lr, lr, b, ) + s := NewSet(b, br, i, str, l, lr) hashStr := func(v Value) string { return fmt.Sprintf("[#%s]", v.Hash()) } + resolvesTo := func(col, exp, val Value) { + assertPathResolvesTo(assert, exp, col, NewPath().AddHashIndex(val.Hash())) + assertPathStringResolvesTo(assert, exp, col, hashStr(val)) + } + // Primitives are only addressable by their values. - assertPathResolvesTo(assert, nil, m, NewPath().AddHashIndex(b.Hash())) - assertPathStringResolvesTo(assert, nil, m, hashStr(b)) - assertPathResolvesTo(assert, nil, m, NewPath().AddHashIndex(i.Hash())) - assertPathStringResolvesTo(assert, nil, m, hashStr(i)) - assertPathResolvesTo(assert, nil, m, NewPath().AddHashIndex(s.Hash())) - assertPathStringResolvesTo(assert, nil, m, hashStr(s)) + resolvesTo(m, nil, b) + resolvesTo(m, nil, i) + resolvesTo(m, nil, str) + resolvesTo(s, nil, b) + resolvesTo(s, nil, i) + resolvesTo(s, nil, str) // Other values are only addressable by their hashes. - assertPathResolvesTo(assert, i, m, NewPath().AddHashIndex(br.Hash())) - assertPathStringResolvesTo(assert, i, m, hashStr(br)) - assertPathResolvesTo(assert, lr, m, NewPath().AddHashIndex(l.Hash())) - assertPathStringResolvesTo(assert, lr, m, hashStr(l)) - assertPathResolvesTo(assert, b, m, NewPath().AddHashIndex(lr.Hash())) - assertPathStringResolvesTo(assert, b, m, hashStr(lr)) + + resolvesTo(m, i, br) + resolvesTo(m, lr, l) + resolvesTo(m, b, lr) + resolvesTo(s, br, br) + resolvesTo(s, l, l) + resolvesTo(s, lr, lr) // Lists cannot be addressed by hashes, obviously. - assertPathResolvesTo(assert, nil, l, NewPath().AddHashIndex(i.Hash())) - assertPathStringResolvesTo(assert, nil, l, hashStr(i)) + resolvesTo(l, nil, i) } -func TestPathHashIndexOfSingletonMap(t *testing.T) { +func TestPathHashIndexOfSingletonCollection(t *testing.T) { // This test is to make sure we don't accidentally return |b| if it's the only element. assert := assert.New(t) + + resolvesToNil := func(col, val Value) { + assertPathResolvesTo(assert, nil, col, NewPath().AddHashIndex(val.Hash())) + assertPathStringResolvesTo(assert, nil, col, fmt.Sprintf("[#%s]", val.Hash())) + } + b := Bool(true) - m := NewMap(b, b) - assertPathResolvesTo(assert, nil, m, NewPath().AddHashIndex(b.Hash())) + resolvesToNil(NewMap(b, b), b) + resolvesToNil(NewSet(b), b) } func TestPathMulti(t *testing.T) {