The conversations I had with Carl, Darius and Joel this week have helped me form a clearer picture of the spread of projects ahead.
The work of Kiwi is to write an R7RS Scheme on Truffle (in Kotlin). The purpose of this project is to read / digest Scheme implementation papers and then actually implement them for real.
Right now, Ive done flat closures from The Three Implementations of Scheme (Dybvig, 1987).
Here is the pending list of papers to imlement:
Also Manuel’s work on Delimited Continuations inLispX is also a thing to implement.
Eddy is now the project to take Deuce source code from infix Dylan and porting them to Scheme. Like I wrote earlier, a suitable runtime is needed to test that the port actually works. Such a system must be:
unwind-protect
(This list should be updated as I learn more)
I tried to start the port using Guile
, but that didn’t go thru because keyword support is poor in GOOPS (though I did learn that someone defined as define-method*
that adds keywords, so maybe I can fallback to Guile if the others don’t work out).
I also tried STklos, but having to run it inside Docker is just too slow, but its macro-expander seems a bit wobbly.
Now I’m trying Sagittarius Scheme, which seems viable.
Turns out there’s a list of other implementations here.
The inconsistent handling of keywords between implementations is particularly irksome - on top of the different ways to denote a symbol (is it foo:
, :foo
, or #:foo
?) the syntax of lambda lists is also different (#key
, :key
or nothing in Racket’s case). Perhaps I should write an external program that converts from one notation to another. I like #:foo
, but I’m also okay with foo:
which is DSSSL style. It’s a pain that Sagittarius only supports :foo
.
One possible system that could run Eddy is if I port TinyCLOS + Dylan-like syntax to Kawa, this is the same as the old KLOS project that I tried a few years ago and didn’t figure out then.
One place to start is to go take r7rs-tinyclos and make it run on Kawa, and then add the missing support:
define-class
, define-method
, keyword arguments)make
into a generic function, i.e. understand / streamline the differences between the TinyCLOS MOP and Dylan.One thing I realized now (that I didn’t get years ago) is that JVM integration is optional - there’s a viable path to getting a working system without exposing CLOS classes as JVM classes. So really, it boils down to 3 points:
TinyCLOS uses the most low-tech technique available in R4RS - Scheme vectors.
R7RS-CLOS represent them as Scheme records (R5RS and onwards)
On a system like Kawa, they can represent be as Java classes, but coming up with an encoding requires some novel technique to be determined.
On Truffle, the Static Object Model or Dynamic Object Model can be used
How do you call Java methods?
Learning from Joe Marshall’s technique from Common Larceny, turns out (c) is not the only way to do it. You could always just reflect the Java class hierarchy and replicate them into the CLOS side and install bridges.
How would Java call your methods?
This point I never figured out, while it’s cool to allow that, it turns out it’s not at all necessary for my purpose of implementing an editor.
There’s a neat research paper in this space also:
Fast Generic Dispatch for Common Lisp (Strandh, 2014) presents a cool way to do method dispatch.
When Kiwi is mature enough to run actual code, KLOS is going to be the first big piece of code for Kiwi to run.
Lastly, just because it’s a good name, it will be interesting to also port the Deuce data structures to JS, and the name of that project is Juice
.