A New R6RS Scheme Compiler

Written by Göran Weinholt

Some readers already know this and a few have suspected. I’ve been working on a new R6RS Scheme compiler for a while. Now I have released it as free software. Read on to learn the many wonderful drawbacks of this niche compiler.

I will start with what many will find to be the largest drawback, so that those of you who don’t want it can close this tab right away and never look back (but don’t close the tab!). The compiler is licensed under the GNU Affero General Public License, version 3 or later. I chose this license, not only to promote chaos and disorder, but also because of where I see technology and society heading.

With that out of the way, here are some questionable facts about Loko Scheme:

  • You can download it from the Loko Scheme web site.

  • It is written in R6RS Scheme and a wafer thin amount of assembly. Once it has been bootstrapped it can self-compile. There is no C code in the compiler or the runtime.

  • It generates code for the AMD64 instruction set.

  • It has a few optimization passes, such as Fixing Letrec (reloaded), the inliner cp0 (also used in Chez Scheme and Ikarus Scheme) and a low-level instruction level optimizer. Some code runs really fast, but most code runs just okay.

  • It outputs statically compiled binaries only, although there is also an interpreter.

  • The binaries are simultaneously Linux ELF binaries and multiboot binaries for bare hardware.

  • The Linux port of Loko starts in just 3 ms on my machine.

  • It has concurrency based on Concurrent ML with an API surface mostly nicked from fibers for Guile. I/O is non-blocking by default. If you’re familiar with Golang then this part will feel familiar.

  • Most SRFIs from chez-srfi are supported and there’s an early POSIX library for the Linux port based on the current SRFI 170 draft.

Why Loko

Why not? If you can live with the license (which really isn’t as bad as you might think), then Loko is definitely for you. If one looks at how the GPL has worked out for Linux, I think it will be okay. Linux’s license doesn’t extend to user space and I want that aspect to work the same for Loko.

My original use case for Loko Scheme is experimental operating system development. Forget about all legacy software and build your own kernel, with blackjack and hookers, so to speak. Due to the nature of that kind of work, I think it will necessarily be useful for more things.

Suppose that you can compile a Scheme program on your machine and have a guarantee that it will work on all other Linux AMD64 systems. No confusion with glibc vs musl vs whatever. You also have access to non-blocking I/O, a concurrency library and direct syscalls. What can you build with that?

There’s a directory in the Loko repository with the following samples, which might give you an idea of where Loko is today:

  • bga-graphics - this is a simple program that uses the linear framebuffer of the Bochs graphics adapter (available in QEMU), reads a 3D model and renders it on the screen.
  • etherdump - simple driver for an RTL8139 networking chip combined with a text-mode based Ethernet frame dumper.
  • hello - it’s just Hello World as a library, that runs on Linux or on bare hardware (printing to the serial port)
  • lspci - scans the devices on the PCI bus, prints the register locations, IRQs and option ROM sizes, and uses the PCI ID database to print the name of the devices and the vendors
  • web-server - this Linux program sets up a concurrent web server that responds with a static payload. Pretty simplistic code, but not too far away from a working web server. Handles maybe 15k requests per second.

Future direction

In the future I think there will be ports to more kernels, probably NetBSD and FreeBSD, and more instruction sets. I’d like to try to port it to AArch64 myself unless someone gets there before me.

But before that, I will work on more operating system stuff. There’s an experimental USB stack. I’ve got some code that reads a file from a FAT file system on a USB stick, but it’s very slow in its current manifestation. I just recently added a buddy allocator and fibers and just haven’t had time to write more drivers.

Kernel programming with Loko is not as difficult as regular kernel programming. The concurrency model of kernel code is the same as the one for user programs. There is no need to care about writing special code safe for interrupt contexts. If you’re a Scheme programmer then you can probably already do kernel programming with Loko; you just don’t know it yet.

I also want to have user space support in Loko. This would mean you could have a kernel in Scheme that can run regular Unix-like programs. (It’s not a pipe dream either, it’s actually pretty straightforward). This would let you design your own syscall interface for programs. Loko doesn’t really care about what those syscalls do and doesn’t have any opinions about file systems, networking and drivers. If you preferred how file systems worked in TOPS-20, ITS or VMS, then you could make it work that way.

Do not cling to the past. Download Loko and start experimenting today!

Further reading

  • Loko Scheme’s web site has links to downloads and so on.
  • Faster Dynamic Type Checks describes how Loko gets hardware-assisted type checks, so that e.g. a safe car or cdr is a single instruction.
  • Design Your Low-Bit Tagging with Z3Py describes how Loko’s value tagging system is designed (the git repository has the proof code).
  • Akku.scm is the Scheme package manager required when building Loko Scheme. This will also allow for R7RS support in the future. It would already be working, but CI tests for akku-r7rs are currently failing for Loko.