How about
* concurrency (the ability to have zillions of little stacks,
with stack overflow checks and growing the stck on overflow)?
* exception handling (the ability to crawl over the stack
looking for exception catch frames)?
* garbage collection (the ability to find pointers in
Simon Wolfgang:
OK, let me address these as far as I know them from my miniscule
research so far:
Global Register Variables -- I'm not sure I understand the point here.
LLVM is a... well, a virtual machine. It's not a real target. The LLVM
code is then either simulated in a VM (as per, say,
On 21-Dec-06, at 1:26 PM, Michael T. Richter wrote:
Global Register Variables -- I'm not sure I understand the point
here. LLVM is a... well, a virtual machine. It's not a real
target. The LLVM code is then either simulated in a VM (as per,
say, Java) or it is further compiled to a
In general, GHC (like every other compiler that does strictness analysis)
feels free to change non-termination into a call to 'error' and vice versa.
Under what circumstances does the (error - non-termination)
transformation happen? I'd be unhappy if (head ) put me into an
infinite loop
| Do you mean if I have both an infinite loop and an error call, then I
| might get only the loop?
Absolutely.
f x = error urk
loop n = loop (n+1)
main = print (f (loop 0))
The compiler figures out that f is strict, and uses call by value. Result is a
loop.
Simon
| Do you mean if I have both an infinite loop and an error call, then I
| might get only the loop?
Absolutely.
That's fine and what I expected.
I take it, then, that the answer to the question of under what
circumstances does the (error - non-termination) transformation
happen? is that GHC
I've just discovered the {-# INLINE #-} pragma, but it's not
doing as much for me as I had hoped.
My example is complicated, so let me present a simpler analogy.
Suppose I defined
compose :: (b - c) - (a - b) - (a - c)
compose f g = \x - f (g x)
I can easily persuade GHC to inline 'compose'.