+str: Implement efficient stream op DSL

Explanation in the doc comment for Interpreter
> This exit seems wrong to me: cancellation is not really stoppable, it must always just punch through to the boundary (and in fact I cannot find an implementation that contradicts me). 

My intention was to make cancel stoppable. After thinking though, that would allow again the formation of isolated execution islands that are not driven by external signals. I wanted to allow isolated upstreams and downstreams that connect to the external world but it's not going to work. I agree that cancel should be unstoppable.

>  If I am right then the allowedToPush problem goes away: finishing somewhere in the middle means that that element had the ball at that point in time, so there cannot be a ball downstream when this is invoked.

You almost convinced me here and I started to get excited, but unfortunately the above statement is not correct. The problem is not just finishing in the middle but that onComplete is a non-backpressured signal -- it is not a ball because it does not obey the exactly-one constraint. It is true that DeterministicOp and DetachedOp can only produce a finish() as a response to an external event, but even this could violate ball-count (pushAndFinish!) and BoundaryOps can generate an onComplete/finish at arbitrary time without respecting the position of the ball.

For example if the external upstream is a TCP connection then onComplete can come at any time irregardless of downstream demand. Now taking a chain of only one op, on the onUpstreamFinish call:
 - if the op answered an onPull with a ctxt.pull as the last action then it is allowed to push after receiving the finish event
- if the op answered an onPush with a ctxt.push as the last action then it is not allowed to push, it must wait for a pull event first
i.e. any action on onUpstreamFinished that would create a backpressured signal (a ball) need to know the state of the current op. 

The basic problem here is turning a non-backpressured signal (onComplete) to a backpressured one (onNext) which is the main source of current and previous corner-cases not to mention our experiences with onError which is not just non-backpressured but out-of-order -- hence the even more serious corner cases of converting a non-backpressured out-of-order to a backpressured in-order event.