Slightly optimize dbm storage.
Avoid possible infinite loop in dbm-backed collections.

The dbm code neglected to suppress delta tuples that were duplicates of tuples
already stored in the collection's @storage. Hence, a simple rule like:

    t1 <= t1

would induce an infinite delta processing loop, if t1 was a dbm-backed
collection.
Minor optimization for dbm-backed collections.

Comment cleanup.
Make debugging message conditional on $BUD_DEBUG.
Minor improvements to syntax error reporting.
Remove unused test.
Code cleanup for aggs.
Dup-elim input to grouping operations with non-exemplary aggs.

Because non-exemplary aggs (e.g., sum, count, average) may be
duplicate-sensitive, we need to do duplicate elimination, because dups might be
introduced in at least two possible ways:

    1. In the output of a projection operator (since we don't do duplicate
       elimination in this case)

    2. Due to the vagaries of the rescan/invalidation logic in the push-based
       runtime, which might cause one of the agg's inputs to rescan its output
       (#278).

will be useful for the lattice-based runtime anyway. Note that unfortunately
this commit introduces a performance penalty for grouping ops: on every input,
we need to do an additional hash table probe (+ likely ht insertion), as well as
pay the associated space cost of keeping around the hash table.

Closes #278.
Add another test case for dup input to aggs.
Avoid needless dups in some cases of join rescan.

The previous behavior (after f7bd5357e47c18ec54077ce8a7f9988a55270014) was to
replay join outputs during PushSHJoin#flush(). Since #flush() is called after
running the scanners in a given stratum, this resulted in emitting duplicates
for any newly-produced join outputs. If all operators are idempotent (see #278)
that is harmless, but still needlessly inefficient.

Hence, we now check if we need to do join replay both during #flush() and at the
beginning of #insert() (of course, we rescan a given operator at most once per
tick).
Minor code cleanup for aggs.
Optimize grouping code by up to 40%.

Several related micro-optimizations:

  * Do only 1-2 lookups per tuple in the main grouping hash table,
    instead of 4.
  * Hoist some conditional logic outside the per-agg loop
  * Replace needless `send` with a direct method call

For a micro-benchmark that sums 2,000 tuples 25 times, this improves performance
by almost 40%! (From ~0.8 seconds to ~0.5 seconds using MRI 1.9).  The first
change is by far the most significant, performance-wise.
Optimize grouping for exemplary aggs.

This is similar to the previous perf tuning for non-exemplary aggs
(f4a7c5610cb0e102a4c3396cc5b91b640d80c7e7). It also achieves a speedup of ~40%
on a grouping microbenchmark.
Optimize grouping to reduce duplicate outputs on flush().

The previous implementation of #flush() for both PushGroup and PushArgAgg
emitted a new result set unconditionally. That is overly enthusiastic: if the
grouping operator has not received any new input since the last call to
copy of our previous result set.

On a microbenchmark (an aggregation operation with 2000 distinct groups), this
improves performance by ~40%.
Minor code cleanup.
Tweak test case.
Fix semantic and performance problems in push-based sorting.

The previous coding got the rescan behavior for sorting operators wrong (sort
failed to reproduce its output when in rescan mode, since flush() emptied the
sort buffer). Morever, the previous approach had poor performance, since
emptying the sort buffer would require refilling it via asking for a rescan of
the sort's input elements.

Instead, keep the sort buffer around, but only re-emit it during flush() if
we've seen a new input tuple.

Along the way, rejigger a bunch of the rescan logic for stateful operators;
setting #rescan_at_tick to true for stateful operators by default doesn't make
sense to me. The grouping and outer join operators still need to be reconsidered
under the new scheme, which I will do shortly.
Code cleanup.
Remove PushNotIn#invalidate_at_tick().

As far as I can tell, this is dead code: the 0-arity version of
invalidate_at_tick() is only called on collections, not push-based dataflow
elements.
Remove unused code.