Software I've written
I write software, both for a living and as a hobby. I started with BBC Basic more than
30 years ago and have never really stopped. You can see some things I'm working on
over at my Github page, or you can read on for a
description of some of the more interesting things I've worked on during my spare time.
FlowBetween is a SVG animation tool I'm currently building. It's implemented in Rust and
is intended to eventually provide a unique way to edit vector graphics and animations.
It also demonstrates some interesting ways to design UI applications, running either
stand-alone or in the browser.
Zoom is a Z-Machine interpreter I wrote, originally as a piece of demonstration code
for my final year project at University. I later used it as a project for learning X11
code and Cocoa on OS X. I love interactive fiction as a genre, so I put a lot of effort
into this project.
I wrote the Mac OS IDE for Inform 7, though I'm no longer the maintainer. This was an
interesting project to do: it began life as a half-finished project that just ran the
Inform 6 compiler which happened to be just the starting point needed when Graham
Nelson was beginning the Inform 7 project. I glued a text editor and Zoom into it and
it became a recognizable IDE.
A library for manipulating Bezier curves in Rust.
A library providing an alternative approach to asynchronous operations in Rust. It differs
from the usual methods using threads or thread pools and mutexes by providing a design that
schedules operations on data (the traditional way could be considered to be scheduling data
on threads instead).
Desync's approach replaces both threads and mutexes with a single type with just two methods:
sync to perform an operation synchronously and
desync to perform an operation in the
background. This eliminates the usual hassle with starting threads and scheduling operations
on them, as well as making the flow of data through the application much easier to see from
desync provides some interoperability with the
futures library, with methods to
create asynchronous futures and pipe streams through data wrapped in the
A parser generator: interesting because it takes a unique approach to generalizing the
The traditional method is to deal with conflicts by attempting all the
possible matches, either simultaneously (GLR) or by backtracking. This has a few issues:
in languages that are really ambiguous the worst case performance is exponential; the
end result is essentially indeterminate and needs further processing to be used.
TameParse instead takes the approach of making it so that matches can be made conditional
based on the lookahead. That is, it adds a specifier that says 'follow this match only
if the lookahead matches this context-free pattern'. This can be made to act like a
backtracking parser (but it's much easier to choose which match is chosen in the
final result), but because the lookahead and the final match don't need to match the
same language fragment it becomes possible to disambiguate many context-sensitive features
of modern languages (for example, the cast operator in C or C#).
A further innovation is the concept of 'weak' keywords, which are only distinguished from
other lexical tokens in contexts where the parser actually has different behaviour for them.
(The async keyword in C# is an example: it's an identifier in non-async contexts, something
which is very hard to deal with in traditional parsers but which TameParse makes effortless)
Data-driven binding library for Swift. I suppose it would be called 'reactive' these days
but when I were a lad we just called this stuff 'data-driven'. The trick with this library
is that it makes it possible to write truly data-driven code where most modern reactive
library (it's also the paradigm behind spreadsheets and parametric CAD packages)
For example, with SwiftRebound you can write a Cocoa view that tracks the mouse just by
implementing a draw method that draws a circle at the current mouse position. SwiftRebound
will note that the drawing depends on the mouse position and will cause a redraw whenever
it changes. Here's
the full code for exactly that case. SwiftRebound comes with a toolset for building new
reactive methods from traditional event-driven UI code.