diff options
Diffstat (limited to 'walk')
-rw-r--r-- | walk/walk.go | 85 | ||||
-rw-r--r-- | walk/walk_test.go | 45 |
2 files changed, 85 insertions, 45 deletions
diff --git a/walk/walk.go b/walk/walk.go index 3fba62f..e66feff 100644 --- a/walk/walk.go +++ b/walk/walk.go @@ -148,3 +148,88 @@ func (item WalkItem) Debug() string { builder.WriteString(item.Value.Debug()) return builder.String() } + +func Merge(first Value, second Value) []Value { + switch first := first.(type) { + case NullValue: + return []Value {first, second} + case BoolValue: + return []Value {first, second} + case NumberValue: + return []Value {first, second} + case StringValue: + return []Value {first, second} + case ArrayValue: + secondArr, isArr := second.(ArrayValue) + if !isArr { + return []Value {first, second} + } + + if len(first) == 0 { + return []Value {second} + } + + if len(secondArr) == 0 { + return []Value {first} + } + + var res ArrayValue + for _, el := range first[:len(first) - 1] { + res = append(res, el) + } + midFirst := first[len(first) - 1] + midSecond := secondArr[0] + if midFirst.Index == midSecond.Index { + for _, el := range Merge(midFirst.Value, midSecond.Value) { + res = append(res, ArrayElement { + Index: midFirst.Index, + Value: el, + }) + } + } else { + res = append(res, midFirst, midSecond) + } + for _, el := range secondArr[1:] { + res = append(res, el) + } + + return []Value {res} + case MapValue: + secondMap, isMap := second.(MapValue) + if !isMap { + return []Value {first, second} + } + + if len(first) == 0 { + return []Value {second} + } + + if len(secondMap) == 0 { + return []Value {first} + } + + var res MapValue + for _, el := range first[:len(first) - 1] { + res = append(res, el) + } + midFirst := first[len(first) - 1] + midSecond := secondMap[0] + if midFirst.Key == midSecond.Key { + for _, el := range Merge(midFirst.Value, midSecond.Value) { + res = append(res, MapElement { + Key: midFirst.Key, + Value: el, + }) + } + } else { + res = append(res, midFirst, midSecond) + } + for _, el := range secondMap[1:] { + res = append(res, el) + } + + return []Value {res} + default: + panic("first is invalid value type") + } +} diff --git a/walk/walk_test.go b/walk/walk_test.go deleted file mode 100644 index 759c501..0000000 --- a/walk/walk_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package walk - -import ( - "testing" - "log" -) - -func TestValueIter(t *testing.T) { - values := ValueList{ - NumberValue(1), - NumberValue(2), - NumberValue(3), - } - - valuesCopy := ValueList{} - - iter := NewValueIter(values) - - for { - edible := iter.Next() - if edible == nil { - break - } - - log.Println(edible) - - value, isValue := edible.(Value) - - if !isValue { - t.Fatalf("Iterator produced a non-value") - } - - valuesCopy = append(valuesCopy, value) - } - - if len(values) != len(valuesCopy) { - t.Fatalf("iter gave the wrong number of values") - } - - for i, value := range values { - if value != valuesCopy[i] { - t.Fatalf("iter produced an incorrect value") - } - } -} |