Software

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

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

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.

Inform

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.

flo_curves

A library for manipulating Bezier curves in Rust.

desync

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 the code.

Finally, desync provides some interoperability with the futures library, with methods to create asynchronous futures and pipe streams through data wrapped in the Desync type.

TameParse

A parser generator: interesting because it takes a unique approach to generalizing the LALR algorithm.

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)

SwiftRebound

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 libraries have an event-driven approach instead. This is similar to the Knockout javascript 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.