Initial add of the generic optimizer code

Before digging into this code, look at the Rules implemented at the bottom of DagOptimizer.

There are several TODOS here:

- [x] After I split the code into separate files, I started hitting a scala 2.9 compiler bug, that I don't hit in 2.10. I'll try to work around, or possibly hope that Twitter finally gets on 2.9 before we need this.

- [x] Tests tests tests. I played around at the repl, but clearly we need super hardcore tests for any optimization framework.

- [ ] Actually call this code from an existing platform.
so, I know you mention this, but Expr and Literal are almost exactly the same type. The only difference is that Expr has a class method in the trait, and explicitly includes memoization.

Now, it might be worth keeping these types separate, but it feels like there is a core data structure -- the Expr or Literal type -- and then two differen functions which operate on them, one being Literal.evaluate and the other Expr.evaluate (and the method in trait Expr just calls Expr.evaluate).