Track spawns.

Every time we launch a process, use the process dictionary to store
information about the exact caller; we can't use the process_info/1
command because it doesn't track the calling args.
Track read.

When a read request happens, track the calling function through the use
of the process dictionary.
Track readers.

Every time a read is performed, track the calling MFA, so we are able to
know which completed functions should be re-executed if the state of the
lattice changes.
Ignore earlier lattice states.

If we attempt to bind a lattice with a value we've already progressed
past, ignore it, but don't return an error.  This is semantically
equivalent to allowing rebinds of the same value in the single
assignment store.
Consume isn't tracked.

Don't count calls to consume on a stream as a read call, thereby
dirtying the re-execution chain.  This is problematic as we're not sure
what the semantics on reading a stream of lattices is.

For example, given a stream of G-Sets.  If the first G-set is consumed,
and a LWW-register is updated as a result, when we consume the second
G-set, do we re-evaluate the entire stream again, as the second write to
the LWW-register causes the original write to be marked for
re-execution.

For now, only explicit reads of values are tracked.
Add additional logging.
Inflations are only increases.

Technically, an inflation is the same value (I think?), however, for the
purposes of updating the ETS backend, and from preventing circular
dependencies between executing processes, only modify the value if
necessary.
Whitespace adjustment.
If assigning nil, don't generate id.

For ease in debugging, don't generate a following id for streams if we
are binding the nil value.
Add prototype function composition.

Provide the ability to re-execute functions which operate over lattices
and have them differentially compute their next state.  Provide an
example where a predicate is used to maintain a computed view.