Preevaluate nested expressions to avoid stack overflow

Bug: 33262515

Before we evaluate an expression, find all referenced expressions,
and evaluate them in an order likely to minimize recursion.

This compensates for the fact that our normal evaluation mechanism
relies on a simple recursive descent parser, which tends to need
a fair amount of stack space for each expression, and the fact that
we process previously unevaluated referenced expressions recursively,
effectively stacking many such parse stacks on top of each other.
This largely avoids the latter phenomenon, getting us back to roughly
the same situation we had before we added history.

This could be improved, at some cost, but doing a real topological
sort, or, with more difficulty, by replacing the parser with something
less recursive.

Includes some minor drive-by comment and formatting fixes.

Change-Id: Ie0a900c82d8bfbb48896fc2b938ef28e588163bb
4 files changed