Full rewrite of COFFEE

This makes COFFEE completely agnostic on finite element concepts.

Everything, from variable names to algorithms, was adapted to handle kernels/loop nests that are far more general than the usual "ip-j-k" generated through Firedrake. This means that COFFEE is now an optimizer of generic expressions, which can be obtained through other tools as well. Of course some limitations are still present, but the bulk of the abstraction process is carried out in this pull request. The semantics of the various algorithms is unchanged in its essence, though.