vrtbl/passerine

Vaporization vs Perceus?

hcnelson99 opened this issue · 2 comments

I was in the middle of working on a reimplementation of Koka's Perceus when I stumbled upon this project. Could you speak a little bit about the differences between vaporization and perceus? Specifically, what values are reference counted in vaporization? Are the function params that are "passed by value via a copy-on-write reference" reference counted (does that CoW reference include a refcount)? I think the gist of what I'm getting at is that vaporization shifts more of the work of memory management to the runtime compared to Perceus in terms of these CoW references?

Overall this project looks super awesome! Really cool to see such an awesome project at the crossroads between systems programming and functional language design. Also, thanks for pointing me toward the As Static As Possible thesis. I'll definitely be reading that soon.

Right, so Vaporization definitely delegates more to the runtime than Perceus does. From what I understand, most compile time garbage collection works by creating a set of 'paths' (to data) that are accessible at each point in the runtime. As I'm sure you know, these paths can then be used to automatically figure out the lifetimes of most objects - for non-trivial cases, the compiler can delegate checking the liveliness of an object to the runtime.

So what are the differences? What's reference counted? The only reference-counted values are the immutable values captured by closures - the params that are passed by value via a CoW reference are not. When a function passes a value to another, it's still technically immutable, it being CoW and all. When a function returns, it can forget about its reference to the value without repercussions, because the value still exists (either captured or on the stack) in an enclosing scope.

What's important to remember is that the last usage of any value (before being dropped or being mutated) is always that value. (i.e. no CoW). So, for instance, if I had:

x₀ = 7
y₀ = 8
x₁ = foo x'₀ y₀
print y'₀

(Subscript numbers indicate that a variable has the same value, prime (') indicates last usage) when foo x'₀ y₀ is called, x ~ 7 is passed directly to foo, but y is a CoW reference y ~ &8 because it is used later by print. If foo were something like a b -> shift_right x 2, no copies of x would be made, because a is passed right through - x₁ refers to the same location in memory. This is what allows for functional-but-in-place style code.

If you think ASAP is cool, totally check out µ-Mitten!

Oh, and by the way, would you mind sharing your Perceus implementation if it's public? Thanks!