Blog

Thoughts on language design, systems programming, and building better tools.

A Pyramid Is a Pipeline, Hand-Unrolled

· 7 min read AI Authored

A compiler pass in koru_std threads one context through six checks and re-raises the same failure six times — a right-leaning pyramid of ceremony. Pulling on why it has to look like that unspools three things Koru already believes (events are monads, punning is mandatory, indentation delimits reach) into a single point-free line. The pyramid was never the language; it was the surface hand-unrolling semantics that were already there.

Generators in Koru: yield Ergonomics, Hand-Written-Iterator Speed

· 7 min read AI Authored

The generator you write in Python with yield has a direct Koru shape — a named event that yields an effect stream, folded consumer-side. It compiles to a flat loop with no generator object and no per-step allocation: on a one-billion-iteration fold it matched a hand-written Mojo iterator within noise. You name the generator's type contract; in return the abstraction is free. Mojo, the fast-Python, has no yield at all — to hit the same number you hand-write the iterator state machine.

Prototype Mode: Doodle the Flow, Let the Events Catch Up

· 6 min read AI Authored

Prototype mode lets you author a program flow-first. Koru's thesis is control flow into the type system, so the handler tree is where a program actually lives — and under [prototype] an incomplete program compiles and runs: an unhandled terminal becomes a loud synthesized @panic, a handled-but-undeclared arm is pure declaration-debt with zero runtime footprint, and the compiler prints a readout of every gap. Remove the annotation and both holes fail loudly again; --release refuses the annotation itself, so prototype code physically cannot ship.

Open a Vocabulary, Shadow Nothing

· 5 min read AI Authored

Koru names everything in full because the resolver stamps every bare name onto the main module with no import lookup — qualification is the default, not an accident. [with]M opens a module's vocabulary inside one lexical region, but only for names that would otherwise fail to resolve. It never shadows a name that already means something, and when two opened regions both claim a name it refuses to guess. So a grammar reads as grammar without any construct changing what working code already says.

A Grammar Is Two Glyphs

· 6 min read AI Authored

PEG parsing has exactly two structural combinators: ordered choice and sequence. Koru already ships both — choice is branch dispatch, sequence is nesting. So std/parser adds no grammar formalism at all: rules are effect arms, alternatives are branches, terminals are regex patterns compiled to DFAs at comptime, and a parse error arrives on a branch carrying line and column. A recursive parser is just control flow you already know how to read.

Types Are Comprehensions

· 8 min read AI Authored

Koru's capture folds a stream of values into one cell. The constructor generalizes it — same sandwich, but the thing it builds can be a list, a struct type, or a type derived from another type's fields. It all happens at comptime and dissolves to nothing. And reflection turns out to be just another traversal source: fields-of(T) pulses ! each over a type's fields the way for pulses over a range. Iteration is emergent, not an iterator you hand to a loop.

The Compiler Grows a Trellis

· 8 min read AI Authored

Every accelerator target ships with an unwritten contract about shape — no allocation in kernels, no data-branching in SIMD lanes. Every toolchain enforces it the same way: the lowering fails, three layers below your code. In Koru the contract is now a value: a trellis describes valid shapes of the AST as regex over ancestry paths, enforces them as located compile errors, and answers them as branch dispatch. Zero compiler changes — it's a library.

A 35-Line Prime Sieve Now Beats Hand-Tuned Rust

We were rejected from the benchmark that measures it. We fixed our toolchain and beat it anyway.

· 14 min read

We submitted Koru to Dave Plummer's prime sieve drag race. It was closed the same day, on eligibility grounds that were written in reaction to our PR — while Brainfuck, INTERCAL, Whitespace, LOLCODE, and Ballerina all sit in the same repo, unaffected. Rather than argue about it, we went and made the submission unimpeachable instead: found a real bug in our own allocator, fixed it, and came out the other side beating the two most aggressively hand-tuned Rust implementations that exist for this problem. 35 lines, zero dependencies, on the platform that actually scores.

The Compiler Writes the Marker

· 11 min read

A couple of days ago we ended a post about a prime sieve with a promise: the next move wasn't to hand-write more SIMD, it was to make Koru's compiler generate the specialized marker — and we said we weren't there yet. We're there. mark-multiples is a compile-time transform now: you write 'cross out the multiples,' the compiler emits the unrolled, residue-class marker (a tight scalar loop the backend vectorizes for you). On our own hardware it runs dead even with the hand-tuned Zig champion — a couple percent ahead on one chip, a hair behind on another. This is the whole climb, including a 'fix' that looked perfect in the disassembly and was three percent slower, and the register spill that turned out to be the entire gap. The numbers are ours; the official verdict belongs to the maintainers.

The Wheel Was the Wrong Optimum

· 16 min read

We set out to see how fast a prime sieve could be in pure Koru, entered it in Dave Plummer's drag race, and almost embarrassed ourselves — our prettiest sieve was a vectorization dead end. The honest climb from there, measured the same way the C++ champion measures, ends in a dead heat with hand-tuned NEON C++. This is the whole arc, including the part where we were wrong — and the eight-line program at the end of it, that doesn't even write its own free.

The Frame Is a Memory Obligation

· 10 min read

David Barbour's assembly-adaptation point: on a machine with no implicit call stack, the type of a stack pointer — the frame structure — is just another memory obligation, and recursion gets awkward. He's right on both counts, and the two halves of his observation turn out to be the same half. Koru's obligations are linear phantoms that the compiler checks and then erases at emit — which is exactly what a stack frame wants to be.

Your Regex Is a Branch, Not a Library Call

In Koru, match is control flow and each pattern is a branch the compiler turns into a specialized native DFA. Two things fall out of that one fact: it's 2× faster than Rust's regex crate, and ReDoS cannot happen.

· 13 min read AI Authored

Every other language treats regex as a runtime object you construct and call. Koru treats a pattern as a branch — the compiler reads the patterns at compile time and bakes each one into a straight-line native matcher. That single design choice buys both the speed and the safety, and you don't get to opt into the bug class that backtracking engines can't escape.