This message is directed specifically at people who are interested in the
*internals* of the Glasgow Haskell compiler.  If you aren't, then just
delete this message.  We don't have an exhaustive list of all ghc-internals
users, which is why this message is going to the Haskell mailing list.

Simon

        **********************************************

Dear ghc-internals person,

We want to consult you about a proposed change to the definition of the Core
data type, which plays a central role in the compiler.  Because any change
to Core affects virtually everyone, we thought we should propose it first
before doing it by fiat!

PROPOSED CHANGE 
~~~~~~~~~~~~~~~ 
At the moment, an application (CoApp) can have an arbitrary expression as
argument.  Instead, we'd like to restrict the arguemnt to be atomic -- that
is, a variable, literal or niladic constructor.   And likewise for primitive
applications (CoPrim) and constructor applications (CoCon).  That's it.

Incidentally, we already enforce the atomic-arg constraint for constructors;
this proposal just extends the idea to primitives and general applications,
and encodes it in the data type.  

It would be possible to enforce the constraint without changing the data
type, but it seems tidier to encode the constraint in the data type itself.

The atomic-arg constraint would make Core look much more like STG code;
indeed STG would be more-or-less an annotated form of Core.  Other things
being equal this would be a Good Thing.

EXAMPLE
~~~~~~~
For example, consider the following expression

        f (g x)

In current Core it would be expressed like this:

        CoApp (CoVar f) (CoApp (CoVar g) (CoVar x))

[the f,g,x being suitable Ids].  Under the new proposal, you'd have to write

        let a = g x in f a

or, in Core,

        CoLet (CoNonRec a (CoApp g x)) (CoApp f a)

(of course, nobody writes Core, except the compiler itself!)

WHY DO IT?
~~~~~~~~~~
We've found that there is a small raft of transformations which have
to be duplicated if the above transformation isn't applied.  For example,
suppose you have

        let x = let y = ... 
                in y:ys
        in ...

It is often a Jolly Good Idea to transform to

        let y = ... 
        in let x = y:ys
        in ...

(Why?  Because then x is allocated as a fixed, unchanging cons cell, rather
than as a thunk which later has to be updated.)  Supposing, anyway, that
this *is* a transformation you want to do, there is another very similar one:

        f (let y = ... in y:ys)
becomes
        let y = ... in f (y:ys)

Now the argument of f is non-updatable, and we save an update as before.
If function arguments are forced to be atomic, then the first transformation
subsumes the second.

There are several other transformations which suffer a similar duplication. 
The compiler becomes simpler if arguments are atomic.  


ANY DISADVANTAGES?
~~~~~~~~~~~~~~~~~~
I havn't been able to think of any serious disadvantages; but maybe you can
(hence this msg).  The only time it seems less convenient is when
rearranging associative operators:

        (a `op` b) `op` c  ===> a `op` (b `op` c)

is definitely more tiresome in the let-form.  But that's a very localised
problem, and quite soluble.



Over to you. To save troubling everyone else, maybe you should send replies
direct to me, and I'll bundle them together and send them to all responders.

If we hear nothing we'll just do it!

Best wishes

Simon

Reply via email to