Weeknotes 2025 W46: It’s terminal
Quick bits:
-
I would like to own a vernier caliper. I don’t have one. I don’t need one. But it would be nice to just have one, you know?
-
There is a special place in hell for people who stop right at the top of an escalator. Did I mention this before? I sure have shoved multiple offenders because of not having a choice.
Shower thoughts:
- It’s bad luck to call it “McDonald’s” — I always call it “the Scottish restaurant.”
It occurred to me that the lowercase letters a and g on the Berlin S-Bahn digital signage are mirror versions of each other:
XXXX XXX
X X X
XXXX XXXX
X X X
XXX XXXX
XXX XXXX
X X X
XXXX XXXX
X X X
XXXX XXX
Duolingo has been getting weird lately. I’m doing Spanish on there, and the last few days, I’ve gotten sentences like the following:
- The horse closed all the doors.
- The cats closed the windows.
- The cats watched horror movies all night.
- Yesterday, the birds cleaned the floor.
- The horse opened the fridge and did not close it.
- The dog learned three languages.
- The horses learned German.
- The cats opened a restaurant last month.
- The dog cooked a very good dish.
I don’t mind the occasional odd sentence, but it’s now so bizarre that it is hard to translate such Spanish sentences to English because I keep second-guessing whether it really means what I think it means.
Learning a new language involves inferring meaning from the context, but if the sentences are about fat pigs writing letters in French, then that becomes really quite difficult.
Duolingo is perhaps not a great way to learn languages.
This week, I have been struggling with a specific Zig problem: crashes would cause the process to freeze, not printing anything and not exiting.
To reproduce, I created this source file, blah.zig:
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const ptr = try allocator.create(u32);
allocator.destroy(ptr);
allocator.destroy(ptr);
}
I then built an executable (with zig build-exe blah.zig) and executed it (with ./blah), which just… hangs:
% ./blah
To be clear: that second allocator.destroy(ptr) is intentionally wrong. That line frees an allocation that has already been freed. Still, it at least shouldn’t hang.
What is expected is something like the following:
% ./blah
Segmentation fault at address 0x104fc1428
[snip]/debug_allocator.zig:875:23: 0x104ebebec in free (blah)
if (bucket.canary != config.canary) @panic("Invalid free");
^
[snip]/Allocator.zig:147:25: 0x104ebd747 in destroy__anon_19268 (blah)
return a.vtable.free(a.ptr, memory, alignment, ret_addr);
^
[snip]/blah.zig:10:22: 0x104ebd4b3 in main (blah)
allocator.destroy(ptr);
^
[snip]/start.zig:627:37: 0x104ebd9c3 in main (blah)
const result = root.main() catch |err| {
^
???:?:?: 0x184df2b97 in ??? (???)
???:?:?: 0x0 in ??? (???)
fish: Job 1, './blah' terminated by signal SIGABRT (Abort)
You might be asking yourself now: how did I manage to get that backtrace if Zig hangs instead of terminating? Well, as it turns out, running the executable only hangs when executed in a Zed terminal, but not when executed in ghostty.
It turns out this is not even a problem with Zig. In fact, even the exit 1 command makes the Zed terminal hang:
% exit 1
So I filed Zed issue #42414.
I hope Zed recovers.
I hope it’s not… terminal.
I’ve shifted my focus back from my static-site generator to Deng. One thing that certainly has been missing is error reporting for the VM. It was already present for the compiler (including the tokenizer and parser), but that was easy. Error reporting for the VM is not nearly as simple.
The way I’ve solved this is to make compiler emit a byte array that contains not just the bytecode, but also:
-
a source map, which stores the byte range in the template input for each instruction — a
(u32, u32, u32)triple of instruction index and token range -
the original template itself
This byte array starts with a header that contains the lengths of the bytecode and the source map, so that all three parts (bytecode + source map + template) can be extracted. While this encoding is a little space-inefficient, it does work well enough.
Mapping instructions to tokens is unfortunately not easy. Here is one of those runtime error messages:
6:20: Found `null` value, which is not printable
<title>{{ page.title }}</title>
^^
The write instruction is emitted when the compiler sees the }} token. That instruction takes the topmost value off the VM stack and writes it to the output stream.
What I really want, though, is an indication of the entire expression that caused the error — page.title in this case, not the }} token:
<title>{{ page.title }}</title>
^^^^^^^^^^
I don’t yet know how to achieve this. Further research and experimentation is needed to improve these error messages.
At the recommendation of E——, I started using Herb for syntax highlighting and linting my HTML+ERB files.
It works just fine with Nanoc, though I had to rename the .erb layouts to have the .html.erb extension. Not a single change needed in the Rules
I am facing Herb issue #854, however, which makes a few of my layouts unparseable. Hopefully that’ll get fixed soon.
Thanks for Herb, though, I learned about the autocomplete attribute, and adjusted all the input fields — not that there are that many — accordingly. Hurray for convenience!
Entertainment:
-
After a month-and-a-half-ish break, we’ve resumed our Blades in the Dark campaign. Holidays and illness meant that we had to pause it for quite a while.
-
Slow progress in Warhammer 40,000: Rogue Trader.2 It’s not easy!
I am so used to games auto-saving, and this game just doesn’t have many auto-save spots. Many times I have gotten myself into an unsurmountable problem that requires me to load an older save that… well, is from long ago.
Toots and skeets:
-
Adrian Sampson asked how you pronounce
atoi(3)and I will find it very hard from now on to not pronounce it “uh-twa.” /a twa/.
Links:
-
Death of the Author: An Alan Wake Series Retrospective (Noah Caldwell-Gervais)
-
I Want You to Understand Chicago (aphyr)
-
Anatomy Of A Legacy Sequel (Patrick H. Willems)
-
Daft Punk - Steam Machine: iykyk
-
Trimalchio in Newburyport: Timothy Dexter’s A Pickle for the Knowing Ones (1848): I adore the pettiness of including a page full of punctuation in a book without punctuation. Perfect.
-
Where's Putin? How The Kremlin Hides His Location With Three Nearly Identical Offices: Spooky!
-
World still on track for catastrophic 2.6C temperature rise, report finds: Quote: “the end of agriculture in the UK and across Europe.”
-
Stones In Coffee: An Ill-Advised Investigation (James Hoffmann)
Tech links:
-
Language design notes (Ray Toal): Fun stuff! Now I want to create more programming languages. More. More!!!
-
When Your Hash Becomes a String: Hunting Ruby's Million-to-One Memory Bug
-
In Praise of dhh (Filipa Mendonça-Vieira): The title is satirical, in case you’re wondering.
-
perkeep v0.12: Surprised to see another release! This project went into maintenance mode. I’m not using it, but I like the concept. (I’d probably use it if it were stable.)
-
The world is something that we make (Thomas Rumbold)
-
Version Control External Content Referenced in Your Blog (lgug2z): Yes!