Various COFFEE improvements

Three major points are addressed:
- The code has been refactored and now is much more clean. I like the way it is, although something else could be done in the future. You'll see lots of changes if you compare the code, but actually most of them are just about moving things around and renaming methods/variables etc. 
- Fix a few nasty bugs when symbolically executing the kernel to track the propagation of zeros
- Improves code motion by also recognizing the presence of duplicates in the hoisted code (this was done also previously, but not in the systematic way we do it now)
The right way to write multiline C macros is:

```c
#define PRINT_ARRAY(ARR, SZ) do { \
    printf("ARR: "); \
    for ( int k = 0; k < (SZ); ++k) { \
        printf("%e ", (ARR)[k]); \
    } \
    printf("\n"); \
    while (0)