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:
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
/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. Update 2023-02-05: I just learned that uEmacs has a non-free license. I will find something else.
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.
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.