Arc Forumnew | comments | leaders | submitlogin
1 point by almkglor 4993 days ago | link | parent


It seems that closures aren't nested (i.e. do not refer to other frames). In short, when we have a closure within a closure:

  (fn (x)
    (fn (y)
      (fn (z)
        (prn x)
        (prn y)
        (prn z))))
This compiles to (pseudo-Arc):

  (fn (self x)
      (fn (self y)
          (fn (self z)
            (prn self.0)
            (prn self.1)
            (prn z))
          (list self.0 y)))
      (list x)))
(here, self means the closure of the function, not 'afn self).

Because the frames aren't shared, this means the current closure-conversion model can't be easily(?) modified made to work on the following code:

  (fn (x)
      (fn () x)
      (fn (v) (set x v))))
I'm not sure how to resolve this unfortunately. And again I'm not 100% sure of my analysis.

4 points by stefano 4991 days ago | link

You could try transforming

(fn (x) (list (fn () x) (fn (v) (set x v))))


  (fn (x)
    (let x (cons x nil)
        (fn () (car x))
        (fn (v) (set-car x v)))))
This way the adress of the cons cell x isn't shared, but the cell itself is shared. The compiler would do this transformation automatically.


3 points by almkglor 4991 days ago | link

Done and on the git.

Some notes:

1) I use a new structure, the sharedvar, which doesn't correspond to any Arc structure. See the other post which had me blinking stupidly at stefano's transformation before I realized how cool it was:

2) This new structure is untyped (i.e doesn't have type tags, unlike the pair and symbol structures). I intend to make shared variables "seamless" to the upper Arc though, so this should be fine...

3) My original name for this structure was closure-settable, which I shortened to sharedvar instead.

PS f34r my new gravatar


1 point by stefano 4990 days ago | link

Wow. You implemented it very quickly.

Making the new structure untyped shouldn't create problems, but it could make development difficult: if you have a bug in the transformer or in something related to it, you'll probably get a Seg. fault error instead of a clean "Not a sharedvar" error. The check could then be removed when the code is released.


1 point by almkglor 4990 days ago | link

Hmm. So far the transformation seems correct anyway; and really, the transform is quite simple and appears mathematically correct. Also, because of the way the compile-file driver is structured, it would be possible to remove/replace each individual transform.

Which reminds me, we need to have a proper error continuation too.


2 points by almkglor 4991 days ago | link


blinks stupidly


Why didn't I....




Edit: Okay, I managed to snap out of shock.

The base idea is pretty good, although the 'cons cell (which is composed of a type id, a car pointer, and a cdr pointer) can be replaced with a smaller "closure-settable" cell, which would be an untyped object composed of a single pointer:

  (fn (x)
    ; % means it's a primitive
    (let x (%closure-settable x)
        (fn () (%closure-settable-read x))
        (fn (v) (%closure-settable-write x v)))))
Because the closure variable abstraction is not accessible from the high-level Arc language, the closure-settable doesn't need to be typed tagged