Loko Scheme 2022 Q4 Update

Written by Göran Weinholt on 2022-11-06

I released Loko Scheme 0.12.0 last month and forgot to blog about it. I’ve been busy starting my own consulting company so it just slipped my mind. There are two cool milestones with this release.

Self-compilation on bare metal

A cool milestone in 0.12.0 is one of those things that is pretty significant but that you can’t really demonstrate visually.

I have implemented enough of the Linux syscall layer that I was able to run Loko’s compiler on bare metal. I used an old Acer laptop to compile Loko itself while running only Loko on the laptop. Many compilers can compile themselves but this is a new extreme.

Valand, a windowing system

Loko now has a windowing system called Valand. Its design is somewhat inspired by Wayland, except it’s integrated in the kernel and is meant to be used on bare metal. So Loko on bare metal now has support for running multiple graphical programs with preemptive multitasking. You can even run Doom through a port of doomgeneric:

Doom on Loko screenshot

The way this works is through an extension to the Linux syscall ABI emulation. When you cross-compile doomgeneric on Linux you get an ELF binary that you can copy to the hard drive and then load with @/doomgeneric in the REPL window. That starts a doomgeneric process that opens /dev/valand, which gives it a file descriptor for Valand.

The Valand file descriptor supports an ioctl for creating a graphical surface which is then mapped into the process memory with mmap. Doomgeneric writes pixel data to this memory and calls another ioctl to mark the surface as damaged. Valand regularly fixes the damages by copying the damaged pixels to the framebuffer, which means that the screen is updated with a new frame from the game.

Keyboard events are returned by doing a non-blocking read on the Valand file descriptor. If there is an event then it’s returned as a struct that specifies a USB HID page and usage. Using USB HID means that there is no need to invent yet another scancode table just for Loko.

Valand keeps track of surfaces and composes an image from them. The composing magic is done with a bunch of rectangle math and a z-buffer. It is all done in Scheme code compiled to native machine code by Loko. I haven’t benchmarked it, but it’s fast enough to not be laggy.

It’s not much but it’s enough to get Doom running. You might notice that there are no title bars and controls on the windows. There’s very little that the window system gives you in the current version. You can move windows and keyboard focus will follow the mouse. Valand is starting out small and simple.

Dreaming up what’s next

The next milestone could be to port an editor. With an editor running on Loko and Valand it would in principle be possible to keep developing Loko without using another OS. I’m thinking that the fork of uEmacs/PK that Torvalds maintains should be pretty simple to port. Loko doesn’t have a terminal emulator, not even a tty layer, but you could build the terminal renderer into the uEmacs binary and have it use Valand for the UI.

And I intend for Valand to be an integral part of the operating system that I’m building with Loko. This will make it possible to do some things that you can’t do in an OS like GNU/Linux where these components are much more loosely coupled. The Linux kernel has no idea about the desktop environment you’re using, which is the right thing for its design, but which also limits what can be done.

The tighter coupling means that Valand can provide a trusted path. The user should have a way into the system which they know with certainty can’t be faked. The system menu on top of the screen will be one such trusted path. It’s a placeholder in the screenshot shown above, but you can imagine something like the macOS menu. Window decorations will be another trusted path; it should not be possible to fake them.

A mini-rant

Linux systems sometimes freeze because the kernel overcommits memory and under heavy memory pressure begins discarding the pages of demand-paged executables. The kernel can basically decide to discard all of user space in favor of a rogue memory hog, so user space grinds to a halt.

Loko should guarantee that the computer always remains responsive, even if a program goes rogue and uses up all resources. I’m pretty weary of my Linux desktop occasionally freezing, so I’m not going to allow that in Loko.

And I don’t want to support anything that steals keyboard focus. Not even dialogue windows. Imagine typing and knowing with utter certainty where your keystrokes will be sent. I haven’t experienced that since DOS.

So when 1.0?

Obviously a version number like 0.12.0 is getting ridiculous and it’s time for 1.0.0 soon. The big milestone that I’ve been wanting to reach before 1.0.0 is to make eval use the compiler. I’ve been putting it off, even though it’s not really all that difficult. Perhaps I’ll get to it once my company is off the ground.