Implement lazy program composition

The previous implementation (commit 1d810fe74002b19e2172145895020e)
eagerly generates all partial strings when two programs are composed.
For example, "P | Q" and "P , Q" for two finite programs "P" and "Q"
generates |P| x |Q| partial strings. More generally, therefore, the
repeated composition of such programs requires exponential space.

This turns out to be a significant performance bottleneck due to memory
contention (e.g. page faults). The new lazy program composition avoids
this by generating partial strings only on demand, thereby achieving a
linear space requirement and much higher performance.