deuce

Edwin + Deuce = Eddy?

Deuce internals

Rereading BruceM’s note on Deuce’s architecture, I was motivated to look into the core data structures that drive the entire app. I have also started looking from the other direction, and started from start.dylan of Deuce to see how the editor gets booted up.

It looks like Bruce might be right, and there are many parts of the editor that’s not tied to the UI system, in which case, I could start porting that code back to a lisp well before having a running Kiwi system.

This investligation revealed clearly one of the difficulties in the Scheme ecosystem - even though there are many choices, the feature sets are all over the place, and you’re not gonna find the right mix of features that you’re looking for.

In Deuce’s case, I’m looking for a R7RS Scheme that supports the following:

  • R7RS module system
  • CLOS style classes (multiple inheritence) and generic functions (with particular syntax for each of those forms)
  • unwind-protect and bind-exit
  • Support for keyword arguments

I’ve checked Kawa (doesn’t support CLOS), MIT Scheme (no keyword arguments), Bigloo (no R7RS, no multiple inheritance) and STklos (no unwind-protect, but there’s call/cc and friends).

So maybe the initial target is to port the Deuce data structures to a form that’s runnable on Stklos as a first pass.

Syntactic differences

Even so, I just found out that the define-class form in Stklos is subtly different, it requires a () around all the slots, which is not required in Dylan:

;; This is Stklos
(define-class <point> ()
  ((x :init-form 0 :getter get-x :setter set-x! :init-keyword :x)
   (y :init-form 0 :getter get-y :setter set-y! :init-keyword :y)))

This looks almost like Dylan code, but here’s the actual code:

;; This is Dylan
(define-class <point> ()
  (x init-value: 0 getter: get-x setter: set-x! init-keyword: x:)
  (y init-value: 0 getter: get-y setter: set-y! init-keyword: y:))

The support for keywords is also subtly different between implementations. This page is a survey of the different variations. Kawa and Dylan support what’s called DSSSL style keywords, but I actually like the paper Eli wrote on how it’s done in Racket. For the sake of compatibility, I might stick to DSSSL style for now.

In researching this topic, I came across this LtU discussion and a note from Andy.

Path forward

Here’s one path that might work:

  1. Port Deuce data structures to R7RS libraries and make the tests run in Stklos, let’s call this project Eddy.

  2. Go back to my KLOS attempt from 2015 and port TinyCLOS to Kawa, without tackling integration with Java classes.

  3. Work on Kiwi to build a real Dylan-like language on top of R7RS Scheme + a scope sets macro-expander, with native mirroring of Java classes into Kiwi’s CLOS classes.

If this does indeed pan out, then both Kawa+KLOS and Kiwi can be vehicles for running Eddy. The GUI code that calls into JavaFX would be different between Kawa and Kiwi, because Java integration will be different. The syntactic idiosyncrasies of Stklos can be updated to follow match Dylan when we move to running on (2), which of course will break on (1).

Kiwi tail call optimization

I have 4 or 5 failing test cases in my general-tco branch, I think they’re all pointing out the same bug.

I feel more motivated to port some Deuce data structures now, so I think I’ll finish that before coming back to Kiwi. Besides, looking at the Deuce code, it doesn’t look like tail-calls are used that often (however, I did see delimited control like unwind-protect and multiple values show up pretty early on)