high-level sketch of a functional interpreter

The main idea is pretty straightforward - instead of having mutable environment,
we make it immutable and pass it explicitly to every method of the intepreter.
an example of how one threads state in the proposed design

Nothing too fancy - no implicits, no State monad, just good old pattern matching
and variable renaming to keep track of updates to state.
pattern match that covers all interpretable TSTs

In order to save you the time of looking into what we want to interpret,
I've thrown together a pattern match that covers all typed ASTs (aka TSTs)
that can be interpreted.

Note that some of the trees described in http://den.sh/quasiquotes.html#syntax-overview
are ignored here. That's because typechecking changes the shapes of the trees,
and the guide linked above is about ASTs in general, not just TSTs.
trees that we want to skip

Some trees should be understandable by our interpreter, but it shouldn't do
anything about them.

These trees include EmptyTree (when used in an interpretable position it means "skip me"),
type definitions (types are irrelevant to interpretation, and imports (after typechecking,
imports no longer matter, because typer has already resolved them).
interprets literals

Nothing fancy here, we just introduce a special method to go
from the world of JVM values to the world of interpreter values.

Note that we throw an unsupported exception when encountering classOf[T].
In principle, we could support those later on, but it's not that important
for macro interpretation, so let's skip that for now.
interprets blocks: immutability rocks!!

This commit shows off the niceties of immutable design.

Thanks to Env being immutable, interpretation of blocks is as simple as
interpretation of every statement from that block individually. Indeed,
purely functional programs compose very well!
interprets local declarations

The previous commit demonstrated updating the heap, and this commit
shows how to update lexical scope when we interpret local declarations.

Note that this code is only about locals. Since we ignore templates
(parts of classes, traits and modules) that define members, interpretation
never reaches non-local declarations.