On Jul 6, 2007, at 6:28 PM, Michael FIG wrote:

>       (let ((bar 1)
>           (bot (lambda ()
>                  (set bar 3))))

Currently Jolt's lambdas are not closures.  Local variables from  
enclosing contexts cannot appear free (and are simply out of scope,  
as you found out) within them.

> How do I construct a closure in Jolt that can bind to variables that
> are local to the function in which the closure was created?  I'd like
> this in order to implement a useful callback function (which modifies
> the state of its lexical environment, regardless of its caller).  I
> don't want to use global variables due to multithreading concerns.

Since Jolt is designed (at least initially) to be a replacement for C  
as the target language for Pepsi, the lack of free variables is not a  
serious deficiency.  The back end just generates the same 'linked  
list of state arrays' code that the current C back end generates, and  
the initialisation of the state array argument is done in value[:...]  
methods before invoking the closure's function (see below for some  
clarifications).

More generally, there are at least four possibilities.

First, if you don't mind having a special calling convention for  
closures, create a tuple containing a function pointer (lambda) and  
the data it is supposed to operate on.  Invoke all your closures  
using a function that calls the closure's function pointer, passing  
the closure's data as an argument.  The data can be anything,  
including an array of 'free variables' or even a list of such arrays  
linked through their first element (this is actually pretty close to  
the way Pepsi implements blocks).

Second, if you don't mind your closures having dynamic extent (i.e.,  
all closures that refer to free variables are implicitly destroyed  
when the context that created them exits), you can create a  
trampoline on the stack by manually assembling a few machine  
instructions that call a given lambda function passing the addresses  
of the free variables of interest.  This is probably doable but very  
tricky (and definitely not portable) in the absence of a stack  
allocator equivalent to alloca().  (An alloca() is, FWIW, on the to- 
do list.)

Third, if you don't mind waiting, you could arrange (maybe by  
persuading me to do it) for the compiler to provide the second  
possibility for you automatically whenever it notices accesses to  
free variables.

Fourth, if you want closures with indefinite extent and don't mind  
making the entire runtime dependent on the presence of a garbage  
collector, would be the third possibility but with the trampoline  
allocated in the heap rather than on the stack and the free variables  
collected together in a state array (iow, the first solution  
implemented automatically for you by the compiler with the fallout  
cleaned up by a GC).

I'd love for someone to come up with a better solution for full  
closures in Jolt.  My current plan, to go with something like the  
fourth possibility, brings a GC firmly into the list of  
indispensables and is almost certainly a severe compromise.   
Desiderata for a cool closure implementation would include:

1. Closures look like functions (you can call them from statically- 
compiled C programs just like a pointer-to-function).
2. They accept arguments (even when passed from C code, without  
special precautions in that C code).
3. They look like objects too (you can send messages to them, in  
particular those of the 'value[:...]' variety).
4. They are cheap to instantiate and initialise.
5. They don't generate huge amounts of garbage.  (I doubt that zero  
garbage is attainable, in a non-linear non-functional language, for  
closures of indefinite extent.)

Cheers,
Ian





_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to