Font rendering now happens off the real screen, which provides the effect
of double-buffering.
Apps can now also use convert-graphemes-to-pixels for more traditional
double-buffering.
Two interesting things:
- We don't really need double-buffering for rendering the screen on the
sandbox as a progress indicator. Everything else is untouched, and render-screen
should be doing that as well.
- Rendering just pixels of the fake screen is buttery smooth. It's the
_graphemes_ that are slowing things down. Even though there's so many
fewer of them!
As a result, drawing the fake screen less frequently in `evaluate` doesn't
actually help with flicker. Even though it'll make the debug cycle shorter.
So my current plan is to attack flicker in isolation before I mess with
the render frequency.
In this commit I optimized away the cursor handling. Still doesn't seem
to be helping. In fact it actually seems _worse_.
Rename cells containing screens to screen vars because of the ambiguity
that each grapheme in fake screens is represented by a type screen-cell.
While we're at it, we also analogously rename keyboard vars.
I wrote a comment about how some code was not covered by tests, and then
promptly forgot what it was for. This is why we need tests.
Now the hack is gone.
I was aware of some complications. The various indexes and y coordinates
in the trace's cache would be unstable and need to be recomputed. But it's
surprising that the trace _completely disappears_.
The goal: the sandbox initially maintains a shallow trace. As you expand
into the trace, the environment reruns the sandbox at greater depth as
needed.
The challenge: expanding happens within edit-trace, which doesn't have
the whole sandbox needed to re-run the sandbox. We'll either need to expand
the trace's capabilities to include the whole sandbox, or duplicate some
logic to decide when to run the sandbox.
We now use traces everywhere for error-checking. Null traces introduce
the possibility of changing a functions error response, and therefore its
semantics.