[comp.lang.functional] Q: compilers written in lazy languages

mikpe@IDA.LiU.SE (Mikael Pettersson) (11/09/90)

I'd like to ask those of you who have implemented compilers using
_lazy_ functional languages a couple of questions:

    Did you make significant use of the laziness of the implementation
    language, i.e. were there parts the the compilers that
    would have been considerably more difficult to implement
    or less efficient had the impl. language been applicative?
    If so, what were those parts and for what kinds of object
    languages (the input lang. to the compilers) did this occur?

email replies ==> I'll do a followup in, say, 10 days from now.


/Mike
--
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: mpe@ida.liu.se or ...!{mcsun,munnari,uunet,unido,...}!sunic!liuida!mpe

mikpe@IDA.LiU.SE (Mikael Pettersson) (11/24/90)

In article <1990Nov8.175822.19565@ida.liu.se> I wrote:
>I'd like to ask those of you who have implemented compilers using
>_lazy_ functional languages a couple of questions:
>
>    Did you make significant use of the laziness of the implementation
>    language, i.e. were there parts the the compilers that
>    would have been considerably more difficult to implement
>    or less efficient had the impl. language been applicative?
>    If so, what were those parts and for what kinds of object
>    languages (the input lang. to the compilers) did this occur?
>
>email replies ==> I'll do a followup in, say, 10 days from now.

Well, that was two weeks ago. In the mean time, I have received
five email comments about this topic. They are included here
(in slightly edited versions). At the end of this message you
will find my own "conclusion".

================================================================
From: rej@ukc.ac.uk

I've built a compiler for an intermediate language (something like FLIC)
in Miranda. The abstract machine is essentially a G machine.

Off the top of my head, I recall using laziness for the following:

1) Generating Unique Labels
   Suppose I want to translate, say, an application

   Trans labelsupply (App e1 e2) = Trans labelsupply2 e2 ++
				   Trans labelsupply1 e1 ++
				   [MKAP]
				   where
				   labelsupply1, labelsupply2 = split labelsupply

   The labels in labelsupply1 and labelsupply2 must be distinct.
   One way would be to pass the new name supply as well as the G code
   back. However I chose to do it differently. "labelsupply" is an
   infinite tree of distinct labels -- when I need a new labelsupplies 
   I simply split this tree in half.

2) Of course laziness isn't essential for the above problem.
   In the back end of the compiler I simulated the G machine stacks.
   This meant passing simulated stacks in one direction, and usage information
   in the other. In Miranda this was simple; in a strict language it
   would be harder. See Johnsson's thesis on the Gmachine for details.
================================================================
From: beemster@fwi.uva.nl (Marcel Beemster)

About your question of implementing a compiler in a lazy functional
language. I did write a compiler in a lazy functional language called
stoffel. The language is very small, but large enough to write its own
compiler in itself.

I use a bootstrap compiler that compiler stoffel into FLIC, which is
itself compiled into C.

In the non-bootstrap compiler, which compiles stoffel into C and which
is itself written in stoffel, I make extensive use of attribute
grammars. To implement these the laziness of stoffel is used. Without
this laziness, no use of attribute grammars could have been made.

As for results, not universally positive. Although attribute grammars
are quoted as being ideal for writing compilers, the code easily gets 
quite hairy. I spent many days rewriting code until I was satisfied with
clarity.

A second problem may have to do with the underlying implementation. When
I try to compile the expression: f (g "abcdefghikjlasuhshafkjhkgskdj"),
something with a large string that is, the compiler runs out of memory.
This may have to do with the effects described in:

%A Philip Wadler
%T Fixing Some Space Leaks with a Garbage Collector
%K FPL
%X Software-practice and expreience, V17#9, 1987

in combination with the use of attribute grammars (laziness), but I have
not been able to determine where the problems come from yet.
================================================================
From: Nigel Perry <np@doc.imperial.ac.uk>

	Here at Imperial Keith Sephton & I wrote the Hope+C compiler
in Hope+C - at the time Hope+C was call-by-whnf so the lazy purists
who like evaluating 1/0 will complain... However this makes no real
difference, and anyway there is now a lazy version (just changed the
abstract machine, compiler still the same code). The only real use of
laziness was in one place where I needed a supply of unique
identifiers, so I used a non-strict list - most of our unique
identifiers are supplied by the symbol table WITHOUT using laziness I
just didn't have access to the symbol table at that point in the code
and wasn't prepared to change it so I did. You don't need laziness to
compile a lazy language, all the other laziness in the compiler is
"accidental" i.e. the language just supplied it.

/* Controversial... */ 

Trouble with laziness is that in most implementations it costs you a
lot but you rarely need it. Of course there are times when you do
(before I get flamed) but most of this is non-strict construction i.e.
call-by-whnf.

/* safe again */
================================================================
From: Kevin Hammond <kh@cs.glasgow.ac.uk>

The following is forwarded from Simon Peyton Jones.

Kevin

----- Begin Included Message -----

Subject: Re: Lazy implementation question 
Date: Mon, 12 Nov 90 09:26:22 +0000
From: Simon L Peyton Jones <simonpj>

I once wrote a code generator in LML, for LML.  It made essential
use of lazy evaluation to mix together several passes.  The code
generator was quite large: about 3000 lines of LML.

For example, at the beginning of each basic block there is a test
for heap exhaustion, which depends on how much heap will be consumed
by the basic block.  This could be precomputed by an earlier pass,
but that is rather error prone: the earlier pass has to guess 
how much heap will actually be allocated by the instructions generated
in later pass.  In the code gen I wrote, the very same piece of code that
emits the instruction also increments the heap usage.

This turned out to be a really nice way to write the code generator, except
for one thing: it is easy to introduce a strictness bug.  In its most obvious
form, consider
	if e then (b,e1) else (b,e2)
The first component of the result is always b, but if e depends on b the
value of the expression is bottom.  I found a number of bugs of this
sort, but far more heavily disguised.

Simon
----- End Included Message -----
================================================================
From: schiex@irit.irit.fr (Thomas Schiex CAP SESA - TDV)

I personnaly wrote a compiler for a lazy dialect of Lisp (called HELP) in HELP, 
and indeed used lazyness for "programming with unknowns" to compute
closure strictness.. but this was an aesthetic choice...

I think that there is no necessity to use a lazy language for writing lazy 
language compilers...
================================================================

My interpretation of these comments is that laziness most of the
time isn't essential. Convenient perhaps, but not an absolute must.

The attribute grammar example (Marcel Beemster) and the lazy, functional
version of "backpatching" (Peyton Jones' compiler) use laziness
in a more substantial way. Regarding attribute grammars: my
impression is that most AG users are content with the evaluation
order restrictions imposed by the various non-lazy AG systems out
there. As for the "backpatch" application: well, that could be done
by adding an extra pass computing the information before sending
the basic block to the binary code generator. (Not quite as neat of course)
If the language has side-effects (my apologies to the purists for
even mentioning this abomination) a simple assignment would do the job.


My thanks to the people who responded to this query.

/Mike
--
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: mpe@ida.liu.se or ...!{mcsun,munnari,uunet,unido,...}!sunic!liuida!mpe