[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)