[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: inline declaration for FLET and LABELS
Date: Thu 27 Mar 86 13:40:03-EST
From: "Rodney A. Brooks" <BROOKS%OZ.AI.MIT.EDU@XX.LCS.MIT.EDU>
The problem is that when you expand an FLET'ed or LABELS'ed function,
you have to 'fool' somebody by backing up the lexical environment
correctly. Consider this contoration:
(compiler-let ((*foo* 'foo))
(macrolet ((foo () `'(outer ,*foo*)))
(flet ((foo1 () (foo)))
(flet ((foo2 () (foo1)))
(declare (inline foo2))
(compiler-let ((*foo* 'bar))
(macrolet ((foo () `'(inner ,*foo*)))
(flet ((foo1 () (foo)))
(foo2))))))))
This is supposed to return (OUTER FOO). If the call to FOO2 were
expanded into FOO1 but the environment were not unrolled, it would
instead return (INNER BAR). I'm not saying it is impossible; I'm saying
it is probably damn hard to implement.
Correct. It is hard but not impossible. For Lucid's compiler this was
one of three places (the other two were to do with shared environments
for closures) I had to introduce variations on source level special
forms during alphatization that are not available at user level.
Basically I alphatize the body of the flet defined function in the
environment where it is defined, and then for inline susbstitution
protect it from re-alphatization with an extension to locally.
Alphatization uniquifies everything so eventually all the references
are right.
(I'm not sure this is yet in any released version but will be soon.)
Indeed, I can see how that can work. [Putting on my programming
environment hat...] Implemenations should be careful that what they put
in source locators and debugging information should correspond to what
the user input, not what the compiler uniquified things to. For
example, in the Symbolics implementation, the function spec of FLET and
LABELS functions is
(:INTERNAL <parent-fspec> <unique-index> <user-name-of-local-function>)
For example, the FOO1, FOO2 and (the second) FOO1 in the above form, if
they were in a function called BAR, would be
(:INTERNAL BAR 0 FOO1)
(:INTERNAL BAR 1 FOO2)
(:INTERNAL BAR 2 FOO1)