Revert "eval: remove deprecated dict+dict operator (#54)" (#71)

This reverts commit 345cac49c6fe34e03558fbc9c7413401ede9252:
This operator is deprecated but still widely used by Bazel.
diff --git a/doc/spec.md b/doc/spec.md
index 780d83a..a15c273 100644
--- a/doc/spec.md
+++ b/doc/spec.md
@@ -787,6 +787,13 @@
 A dictionary used in a Boolean context is considered true if it is
 non-empty.
 
+The binary `+` operation may be applied to two dictionaries.  It
+yields a new dictionary whose elements are the union of the two
+operands.  If a key is present in both operands, the result contains
+the value from the right operand.
+<b>Note:</b> this feature is deprecated.  Use the
+`dict.update` method instead.
+
 Dictionaries may be compared for equality using `==` and `!=`.  Two
 dictionaries compare equal if they contain the same number of items
 and each key/value item (k, v) found in one dictionary is also present
@@ -1795,6 +1802,7 @@
    string + string
      list + list
     tuple + tuple
+     dict + dict                # (deprecated)
 
 Repetition (string/list/tuple)
       int * sequence
@@ -1826,6 +1834,15 @@
 [1, 2] + [3, 4]			# [1, 2, 3, 4]
 ```
 
+The `x + y` operation is deprecated for `dict` operands; see Google Issue b/31994014.
+Use the [dict·update](dict·update) method instead:
+
+```python
+# z = x + y
+z = dict(x)
+z.update(y)
+```
+
 The `*` operator may be applied to an integer _n_ and a value of type
 `string`, `list`, or `tuple`, in which case it yields a new value
 of the same sequence type consisting of _n_ repetitions of the original sequence.
diff --git a/eval.go b/eval.go
index 132c66d..d99c363 100644
--- a/eval.go
+++ b/eval.go
@@ -953,6 +953,21 @@
 				z = append(z, y...)
 				return z, nil
 			}
+		case *Dict:
+			// Python doesn't have dict+dict, and I can't find
+			// it documented for Skylark.  But it is used; see:
+			//   tools/build_defs/haskell/def.bzl:448
+			// TODO(adonovan): clarify spec; see b/36360157.
+			if y, ok := y.(*Dict); ok {
+				z := new(Dict)
+				for _, item := range x.Items() {
+					z.Set(item[0], item[1])
+				}
+				for _, item := range y.Items() {
+					z.Set(item[0], item[1])
+				}
+				return z, nil
+			}
 		}
 
 	case syntax.MINUS:
diff --git a/testdata/dict.sky b/testdata/dict.sky
index 15b36be..e948e72 100644
--- a/testdata/dict.sky
+++ b/testdata/dict.sky
@@ -11,8 +11,8 @@
 assert.true({False: False})
 assert.true(not {})
 
-# dict + dict is no longer supported; use dict.update.
-assert.fails(lambda: {} + {}, r'unknown binary op: dict \+ dict')
+# dict + dict (undocumented and deprecated; see b/36360157).
+assert.eq({"a": 1, "b": 2} + {"a": 3, "c": 4}, {"a": 3, "b": 2, "c": 4})
 
 # dict comprehension
 assert.eq({x: x*x for x in range(3)}, {0: 0, 1: 1, 2: 4})