Major refactor.  Tests don't pass yet, but might as well commit.