Chicken Cairo update

I’ve updated chicken-cairo to keep up with a number of changes in the Cairo API. I also shifted it to darcs — GNU/Arch is just too much of a martinet for me.

$ darcs get http://eighty-twenty.org/~mikeb/Darcs/chicken-cairo

I came across an odd problem using Chicken Scheme while I was trying out my updates: I used records to wrap foreign pointers, so I could check types and provide record printers; however, it seems that these pointers are moved around (during garbage collection), meaning that they are trashed in-between getting them from a C function invocation and using them. Using tagged pointers instead of records appears to avoid this problem. I don’t understand very well why this is so, yet.

The code contains annotations, where useful and I’ve remembered, as to what’s changed in the Cairo API.

ThiNG repository available

I’ve been hesitant to make my code publicly available, since it’s embarrassingly messy, but a couple of people have indicated they’re interested in taking a closer look, so here it is:

$ git clone https://gitlab.com/tonyg/smalltalk-tng

The code is mostly written using Chicken (with my chicken-sdl bindings and a version of my packrat parsing library), and is laid out as follows:

./doc
Contains notes on design and implementation, mostly fairly out-of-date, but containing the odd interesting thought. There are also some discarded experiments in concrete syntax here.
./experiments
Contains syntax experiments, and some spike-solutions exploring ideas I'm considering for inclusion, such as STM and partial evaluation.
./lib
Contains third-party library code: at the moment, just a patched version of Dorai Sitaram's pregexp library.
./r1

A first ThiNG spike implementation, borrowing ideas heavily from Slate. The dispatch algorithm is a Scheme reimplementation of Slate's original common-lisp dispatch algorithm (the code is structurally almost identical). The main difference between the two languages is that the only available mutable state is through MVars, and that every subexpression is evaluated in parallel. Have a look at boot.thing to get a feel for the language. (Note in particular the differences between #map: and #mapInOrder:.)

This implementation got as far as having image-based persistence, network I/O, a socket-based REPL, and an interface to the SDL graphics output and UI event input frameworks before I decided I'd learnt enough from it and moved on to the next iteration.

./r2
This was a small step on the way to r3.
./r3
This is the spike I'm currently working on (that I mentioned the other day). At the moment, it's a parser and a simple evaluator. Both are broken right this minute, as I'm working on some quite fundamental changes to the syntax of the language.

From TLA to Darcs

I’ve finally gotten around to moving many of our TLA archives over to Darcs. I simply sealed the TLA versions and imported the sealed snapshot into Darcs, without transferring the history.

The main public projects I’ve darcsified are chicken-sdl and gyre (which is the tool we use to publish this site).

Second ThiNG spike

Over the weekend I built a second experimental implementation1 of ThiNG (older articles: 1, 2), a simple normal-order pattern-matching-based evaluator with a parser built out of packrat parsing combinators and my hacked-on version of Dorai Sitaram’s pregexp library.

I’ve chosen to view functions and records/objects exactly the same way: as pattern-matching message-dispatchers. Here are a few expressions, to give some feel for the language:

"This is a comment, just as in Smalltalk."

[x: x]              "This is the identity function."
[x: x] 123          "This is the identity function applied to the literal integer 123."

"This function takes a 2-tuple, and returns the tuple with its elements swapped."
[[x, y]: [y, x]]

"This is a sketch of a mapping function."
define map [
  (f Nil)           : Nil
  (f [Hd: h Tl: t]) : [Hd: f h Tl: map f t]
]

Note that objects ([Key: value Key: value ...]) are the same as functions ([Pattern: expression Pattern: expression ...]) since (1) the language is lazy, and (2) atoms (keys) are just special-cases of patterns.

I noticed an interesting thing while I was implementing pattern matching. Consider the pattern [Hd: h Tl: t]. The idea is that it should match an object that can receive Hd or Tl as arguments, and bind the variables h and t respectively to the results of applying the object to those arguments. That means that when function/object syntax occurs in value context, it is interpreted as [pattern: value pattern: value ...], but (and this is the interesting bit) in pattern context, it is interpreted as [value: pattern value: pattern ...].

When a pattern [X: v] is being matched against some function, perhaps [X: 1 Y: 2], we see:

    [[X: v]: v] [X: 1 Y: 2]
--> let v = ([X: 1 Y: 2] X) in v
--> let v = 1 in v
--> 1

A slightly more complex example:

    [[[X: 123]: [v, w]]: v] [[X: n]: [n * 2, n * 3]]
--> let [v, w] = ([[X: n]: [n * 2, n * 3]] [X: 123]) in v
--> let [v, w] = [123 * 2, 123 * 3] in v
--> 123 * 2
--> 246

Variable references on the left-hand-side of a colon in value context are binding occurrences, and on the right-hand-side in value context are referencing occurrences; but in pattern context this is reversed, with variables on the left-hand-side of a colon being references and on the right-hand-side being binders. An interesting question about the scope of variable references inside patterns arises: what should their scope be, considering that functions/objects do not have a defined ordering on their pattern-matching clauses?


  1. The first experimental implementation was pretty much a pure-functional dialect of Slate, with ML-style reference cells (sparsely used). The system grew to the point where it could support an SDL interface and multiple socket-based tty consoles, and then I decided I’d learnt enough and it was time to start again. 

The things we do

I started this afternoon wanting to get some hacking done on our Jukebox code, which is written using MzScheme’s web-server, but I’ve been pretty thoroughly distracted: first by the notion of using postgresql instead of flat-files for the Jukebox database, leading to my earlier scheme-pg post, and then by the desire to move the 8020 site over to darcs from tla, which led to exploring a chain of recursive dependencies. The arch2darcs program requires the missingh library, which in turn needs Cabal; so I decided the path of least resistance was upgrading to ghc 6.4.1, which seems to involve building from source when working on MacOS X. The build somehow caused make to spin endlessly (or at least it was giving no visible signs of progress), and I’ve given up on the whole line of investigation and am going back to the relative safety of working on the Jukebox itself.

So back to the Jukebox: over the last three weeks I’ve had an opportunity to teach myself basic JavaScript and AJAX techniques. Paul’s new Jukebox code uses nevow’s “livepage.py” features, which make a great substrate for a good Jukebox user-interface, with queue- and volume-updates broadcast to connected clients, and I’m thinking of adapting the existing Jukebox to do something similar using my new JavaScript skills.

scheme-pg port to MacOS X, MzScheme v299.400

I’ve just finished taking scheme-pg version 0.4.0, which is intended for MzScheme version 299.30, and updating it (1) so that it builds on MacOS X, thanks to Geoffrey Knauth’s patches (slightly edited to undo some kind of whitespace mangling probably introduced by the HTML mailing-list archiver); and (2) so that it builds with MzScheme v299.400. The only change to the Scheme code is in sql.ss — MzScheme v299.400 seems to have sprouted versions of string-upcase, string-titlecase, and string-downcase that conflict with SRFI-13’s versions of the same procedures.

My revised scheme-pg package is available at http://www.eighty-twenty.org/~tonyg/Darcs/scheme-pg/. That’s both a browseable snapshot, and a darcs repository that you can retrieve with

darcs get http://www.eighty-twenty.org/~tonyg/Darcs/scheme-pg/

Mac Powerbook 12" repaired, finally!

After an appallingly long delay (longer than two months!), during which I fretted about the difficulty of fixing my broken laptop (but also learned to ride a motorcycle in my vastly expanded free time), I finally caved in and found a local repair shop (warning: link will resize your window) who would take the case. They did a great job of soldering a new (ad-hoc) connector to the motherboard for me. The power button worked fine when the machine was returned to me.

Unfortunately, I’d broken the keyboard’s ribbon-connector when I’d been taking the thing to pieces and putting it back together again, and the repair outfit had done the best they could with the broken cable I’d left them. Only about a third of the keys were working, so I called up the repair shop and ordered a new keyboard, which arrived the next business day. After all my experience taking the damned thing to pieces, I now rate myself at such a basic job as PowerBook keyboard replacement, so I opted to do it myself, and after an embarrassing false start, having forgotten to remove the remnants of the old broken connector from the socket on the motherboard, the new keyboard is installed and working perfectly.

Um, we now return you to your regularly scheduled 8020.

Mac Powerbook 12" hard-disk surgery

On Sunday I replaced the hard disk in my powerbook, according to the instructions here. Everything went well up to

Pull them out very carefully, as there are very thin cables on the connectors.

It turns out that there are very thin cables on the connectors. Now, I had the good fortune not to break any of these thin cables. What I did end up doing was accidentally removing the entire power connector socket from the motherboard. This was far, far easier than it should have been:

  1. The solder holding the socket to the motherboard was bad, and the socket was very loose to begin with; and

  2. The plug inserted into the socket was jammed tight. No force on Earth was going to separate that plug from its socket. (After it was thoroughly removed from the mainboard, I figured there was no point in being delicate, so took a couple of pairs of pliers to it to try to get the plug and socket separated. No luck. It may as well be glued shut!)

In desperation I googled around trying to find something to avoid consigning the whole machine to the tip. I found this, a more professional (and slightly more accurate) version of the same hard-disk replacement instructions. Note particularly the warning on this page,

The cables you’re about to remove are very fragile - do not pull directly on the wires. Instead, try to pry up the connector directly, using your fingernails or a small flathead screwdriver if necessary.

Yeah, no kidding.

So, now I have a Powerbook, with a brand-new working disk, that I can’t switch on — at least not while the keyboard is connected. Shorting the traces on the motherboard with a screwdriver caused it to power up, boot correctly, and happily wait for a login from the non-connected keyboard, but I don’t really want to try my luck by turning it on and then reconnecting the keyboard while it’s running (and never switching it off again). Neither are my soldering skills good enough to attempt soldering a new connector onto the (very small) traces on the circuitboard. I guess my options are either find a soldering expert, or discover some way of switching the machine on without using the power button.

In hindsight, what I should have done (and this could be added as a hint to the two how-to pages I linked to above) is to cut the power wires to avoid having to pull out the plug in the first place. Once the hard-disk was replaced, it would have been a simple thing to solder the wires together again, or to add a simple in-line jumper to allow future removals of the top panel.