Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/walk
diff options
context:
space:
mode:
Diffstat (limited to 'walk')
-rw-r--r--walk/walk.go85
-rw-r--r--walk/walk_test.go45
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")
- }
- }
-}