<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/walk
diff options
context:
space:
mode:
Diffstat (limited to 'walk')
-rw-r--r--walk/walk.go85
1 files changed, 85 insertions, 0 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")
+ }
+}