Correctly handle while loops with non-constant tests.

In this scenario we can't predict how many times the loop will run or
whether it will even terminate, so we're forced to be cautious and consider
any symbol that can potentially be mutated by the loop as unknown when
we evaluate the block.

We'll then proceed with the rest of the program with these symbols marked
as unknown.

This requires a new concept in the AST of enumerating all symbols assigned
by a node or its descendents without actually executing the node.

This fixes issue #1.