Hi,
I'd like to work on the primitives first. They are relatively easy to implement. Here's how I figure it;
The internal representation of the floats in the cmm is as a Rational (ratio of Integers), so they have "infinite precision". I can implement all the constant folding by just writing my own operations on these rationals; ie, ** takes the power of the top/bottom and reconstructs a new Rational, log takes the difference between the log of the top/bottom etc. This is all very easy to fold.
I can encode errors in the Rational where infinity is >0 %: 0 and NaN is 0 %: 0. Since the size of floating point constants is more of an architecture specific thing, and floats don't wrap around like integers do, it would make more sense (in my opinion) to only reduce the value to the architecture specific precision (or clip it to a NaN or such) in the **final** stage as apposed to trying to emulate the behavior of a double native to the architecture (which is a very hard thing to do, and results in precision errors -- the real question is, do people want precision errors when they write literals in code, or are they really looking for the compiler to do a better job than them at making sure they stay precise?)