<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged compilers</title>
<link>https://coderlegion.com/tag/compilers</link>
<description>Powered by Question2Answer</description>
<item>
<title>Writing a Programming Language &amp; Native x86-64 Compiler from Scratch in C: The Story of Yolish</title>
<link>https://coderlegion.com/28765/writing-a-programming-language-native-x86-64-compiler-from-scratch-in-the-story-of-yolish</link>
<description>&lt;p&gt;Every programmer has, at some point, looked at their favorite programming language and thought: &lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Why was it designed this way? How hard can it actually be to build one myself?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Most developers who explore language design stop at simple arithmetic evaluators or toy interpreters. But when I was building &lt;strong&gt;Exploidus OS&lt;/strong&gt;—a custom x86-64 reactive capability operating system—I ran into a fundamental architectural barrier:&lt;/p&gt;
&lt;p&gt;Standard systems languages (like C) have zero concept of operating-system capability tokens. In C, if you have a pointer, you can dereference it. If you have an address space, any line of code can call any syscall unless restricted by complex external sandboxes.&lt;/p&gt;
&lt;p&gt;I wanted a modern, expressive language that felt as ergonomic as Python or Rust, but was deeply &lt;strong&gt;capability-aware&lt;/strong&gt; at the syntax level—able to compile directly to bare-metal x86-64 binaries without pulling in gigabytes of LLVM dependencies.&lt;/p&gt;
&lt;p&gt;That ambition gave birth to &lt;strong&gt;Yolish&lt;/strong&gt;—a fast, expressive, capability-aware programming language with a tree-walking interpreter, a bytecode virtual machine, and a direct x86-64 native compiler.&lt;/p&gt;
&lt;p&gt;Here is how I designed Yolish, wrote its compiler from scratch in pure C, and what I learned building a complete language ecosystem.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-language-design-ergonomics-meets-systems-control&quot;&gt;1. Language Design: Ergonomics Meets Systems Control&lt;/h3&gt;
&lt;p&gt;When designing Yolish's syntax (&lt;code&gt;.y&lt;/code&gt;), I wanted code to read cleanly without syntactic noise, while enforcing defensive systems programming invariants.&lt;/p&gt;
&lt;h4 id=&quot;immutability-by-default&quot;&gt;Immutability by Default&lt;/h4&gt;
&lt;p&gt;Variables in Yolish default to immutable constants using &lt;code&gt;let&lt;/code&gt;, while mutable state must be explicitly declared using &lt;code&gt;var&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yolish&quot;&gt;let name  = &quot;Yolish&quot;   -- immutable constant
var count = 0          -- mutable state
count = count + 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;pattern-matching-with-ranges-amp-guards&quot;&gt;Pattern Matching with Ranges &amp;amp; Guards&lt;/h4&gt;
&lt;p&gt;Instead of archaic C-style &lt;code&gt;switch&lt;/code&gt; statements with fallthrough bugs, Yolish features expressive pattern matching:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yolish&quot;&gt;let grade = match score {
    90..100      =&amp;gt; &quot;A&quot;
    80..90       =&amp;gt; &quot;B&quot;
    n if n &amp;gt;= 60 =&amp;gt; &quot;C&quot;
    _            =&amp;gt; &quot;F&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;structs-and-impl-blocks&quot;&gt;Structs and &lt;code&gt;impl&lt;/code&gt; Blocks&lt;/h4&gt;
&lt;p&gt;Yolish rejects complex class hierarchies in favor of data-first structs and explicit method implementations:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yolish&quot;&gt;struct Circle { radius }

impl Circle {
    fn area(self) {
        return y.math.pi * self.radius * self.radius
    }
}

let c = Circle { radius: 5 }
y.println(c.area())
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-bridging-code-to-the-kernel-first-class-capabilities&quot;&gt;2. Bridging Code to the Kernel: First-Class Capabilities&lt;/h3&gt;
&lt;p&gt;Because Yolish is the official userspace language for Exploidus OS, security cannot be an afterthought. &lt;/p&gt;
&lt;p&gt;In Yolish, dangerous operations (network access, raw disk writes, peripheral I/O) are gated by &lt;strong&gt;declarative capability annotations&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yolish&quot;&gt;@cap(net.read, fs.write)
fn sync_data(url, filepath) {
    let payload = y.net.get(url)
    y.fs.write(filepath, payload)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When compiled for Exploidus OS, the Yolish compiler inspects these annotations and validates them against the process's cryptographic capability table. If an unprivileged function attempts to make an unauthorized syscall, the operation is blocked before execution even reaches kernel space.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-the-tri-engine-architecture-interpreter-bytecode-vm-and-native-compiler&quot;&gt;3. The Tri-Engine Architecture: Interpreter, Bytecode VM, and Native Compiler&lt;/h3&gt;
&lt;p&gt;Building a language engine involves tough tradeoffs. Tree-walking interpreters are easy to write but slow. Bytecode VMs are fast and portable. Native compilers deliver maximum speed but are deeply architecture-specific.&lt;/p&gt;
&lt;p&gt;Instead of choosing one, &lt;strong&gt;Yolish implements all three&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Source Code (.y)
       |
    [Lexer] -&amp;gt; Tokens
       |
   [Parser] -&amp;gt; Abstract Syntax Tree (AST)
       |
       +---&amp;gt; Tree-Walking Interpreter  (`ys file.y` - Instant startup)
       |
       +---&amp;gt; Bytecode Compiler &amp;amp; VM    (`ys vm file.y` - High speed execution)
       |
       +---&amp;gt; Direct x86-64 Machine Code (`ys -c file.y` - Standalone binaries)
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Interactive Interpreter (&lt;code&gt;ys file.y&lt;/code&gt;):&lt;/strong&gt; Evaluates the AST directly. Perfect for quick scripts, one-liners, and the interactive REPL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Bytecode VM (&lt;code&gt;ys vm file.y&lt;/code&gt;):&lt;/strong&gt; Compiles the AST into an optimized instruction stream executed by a custom register/stack-based virtual machine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Native x86-64 Compiler (&lt;code&gt;ys -c file.y&lt;/code&gt;):&lt;/strong&gt; Generates real machine code instructions (&lt;code&gt;MOV&lt;/code&gt;, &lt;code&gt;ADD&lt;/code&gt;, &lt;code&gt;CALL&lt;/code&gt;, &lt;code&gt;RET&lt;/code&gt;, SSE2 float operations) directly into executable binary containers.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-no-llvm-no-bloat-direct-multi-platform-binary-emission&quot;&gt;4. No LLVM, No Bloat: Direct Multi-Platform Binary Emission&lt;/h3&gt;
&lt;p&gt;Most modern compiler projects delegate code generation to LLVM. While LLVM is powerful, it is also a massive, multi-gigabyte dependency with slow compilation times.&lt;/p&gt;
&lt;p&gt;I wanted the Yolish toolchain (&lt;code&gt;ys&lt;/code&gt;) to be a single, self-contained C binary with zero external dependencies. You can clone the repo and compile the entire language toolchain with a single &lt;code&gt;make&lt;/code&gt; command using standard &lt;code&gt;gcc&lt;/code&gt; or &lt;code&gt;clang&lt;/code&gt; in seconds.&lt;/p&gt;
&lt;p&gt;To achieve this without LLVM, Yolish writes binary headers and machine code directly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linux ELF64:&lt;/strong&gt; Directly formats ELF headers, program headers (&lt;code&gt;PT_LOAD&lt;/code&gt;), &lt;code&gt;.text&lt;/code&gt; sections, and Linux syscall dispatchers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows PE32+:&lt;/strong&gt; Generates valid Portable Executable (PE32+) headers, image import directories, and embeds Windows application icons.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;macOS Mach-O:&lt;/strong&gt; Generates 64-bit Mach-O load commands (&lt;code&gt;LC_SEGMENT_64&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can cross-compile for any major operating system with a single CLI flag:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ys -c app.y --target linux    # Emits static Linux ELF64 binary
ys -c app.y --target windows  # Emits Windows PE32+ .exe
ys -c app.y --target macos    # Emits macOS Mach-O binary
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-runtime-architecture-mark-and-sweep-garbage-collection&quot;&gt;5. Runtime Architecture: Mark-and-Sweep Garbage Collection&lt;/h3&gt;
&lt;p&gt;A systems language with dynamic strings and closures needs safe, automatic memory reclamation.&lt;/p&gt;
&lt;p&gt;Yolish implements a custom &lt;strong&gt;Mark-and-Sweep Garbage Collector (GC)&lt;/strong&gt; written from scratch in C:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Root Scanning:&lt;/strong&gt; Traverses the active call frame stack, global environment variables, and the VM operand stack to identify all actively reachable pointers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mark Phase:&lt;/strong&gt; Recursively traverses heap-allocated objects (strings, dynamic arrays, closures, struct instances), setting the GC mark bit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sweep Phase:&lt;/strong&gt; Scans the global heap allocation pool. Any block whose mark bit is zero was unreachable; it is freed back to the system memory pool, while surviving objects have their mark bits cleared for the next cycle.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Developers have full programmatic introspection into memory usage via &lt;code&gt;gc.stats()&lt;/code&gt; and can trigger explicit collection via &lt;code&gt;gc.collect()&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;6-a-tooling-first-philosophy&quot;&gt;6. A Tooling-First Philosophy&lt;/h3&gt;
&lt;p&gt;A great programming language is more than just a syntax parser; it is an entire developer experience. &lt;/p&gt;
&lt;p&gt;Too many new languages fail because they require third-party formatters, linter plugins, and package wrappers before you can write a serious project. &lt;/p&gt;
&lt;p&gt;From day one, Yolish was designed with a &lt;strong&gt;tooling-first philosophy&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Built-in Test Runner (&lt;code&gt;ys test file.y&lt;/code&gt;):&lt;/strong&gt; Write native &lt;code&gt;test&lt;/code&gt; blocks alongside code and execute them without third-party frameworks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static Checker (&lt;code&gt;ys check file.y&lt;/code&gt;):&lt;/strong&gt; Performs static semantic analysis, flags undefined variables, and detects type mismatches before runtime.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code Formatter (&lt;code&gt;ys fmt file.y&lt;/code&gt;):&lt;/strong&gt; Enforces an opinionated, canonical code style across codebases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive REPL (&lt;code&gt;ys&lt;/code&gt;):&lt;/strong&gt; Instant feedback loop with color-highlighted evaluation.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;7-what-writing-a-compiler-in-c-teaches-you&quot;&gt;7. What Writing a Compiler in C Teaches You&lt;/h3&gt;
&lt;p&gt;Writing a programming language and compiler from scratch in pure C is one of the most humbling and rewarding journeys in software engineering:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Memory Discipline:&lt;/strong&gt; Managing AST nodes, symbol tables, and lexical scopes in C forces you to understand every single byte you allocate. Memory leaks in a compiler slow down compilation; memory corruption in code generation crashes the output binary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Magic of Abstraction:&lt;/strong&gt; When you write the code that translates a simple &lt;code&gt;if (x &amp;gt; 10)&lt;/code&gt; into a &lt;code&gt;CMP&lt;/code&gt; and &lt;code&gt;JLE&lt;/code&gt; assembly jump, you demystify how computers actually think. You realize that high-level abstractions are not magic; they are just structured transformations of intent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicity Over Complexity:&lt;/strong&gt; Features are easy to add to a grammar; keeping the language coherent, orthogonal, and bug-free across interpretation and native compilation is where the real engineering happens.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion-amp-open-source&quot;&gt;Conclusion &amp;amp; Open Source&lt;/h3&gt;
&lt;p&gt;Yolish started as a specialized language project for Exploidus OS, but has evolved into a versatile, cross-platform programming environment with its own native compiler, VM, and standard library.&lt;/p&gt;
&lt;p&gt;The entire project is 100% open-source under the MIT license:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/rahadbhuiya/Yolish&quot;&gt;https://github.com/rahadbhuiya/Yolish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supported Platforms:&lt;/strong&gt; Linux, Windows, macOS, and Exploidus OS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Download the binary, try out the REPL, write a script, and inspect the C compiler source!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have you ever thought about designing a programming language? What is the one feature you wish your daily language had? Let's discuss in the comments below!&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28765/writing-a-programming-language-native-x86-64-compiler-from-scratch-in-the-story-of-yolish</guid>
<pubDate>Sun, 27 Sep 2026 03:56:49 +0000</pubDate>
</item>
<item>
<title>I built a programming language because C++ almost killed my drone</title>
<link>https://coderlegion.com/22891/i-built-a-programming-language-because-c-almost-killed-my-drone</link>
<description>&lt;p&gt;I'm 17. Last year I was writing drone firmware in C++ and Python. One afternoon my ultrasonic sensor returned &lt;code&gt;null&lt;/code&gt; during a landing sequence. The code didn't check for it. The drone tried to divide by zero, the motor controller panicked, and my DJI Tello-sized quadcopter dropped from 3 meters onto concrete.&lt;/p&gt;
&lt;p&gt;That was a $400 lesson in why runtime errors in robotics aren't just bugs. They're physics problems.&lt;/p&gt;
&lt;p&gt;So I built a programming language.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-problem-nobody-talks-about&quot;&gt;The problem nobody talks about&lt;/h3&gt;
&lt;p&gt;When you're writing a web app and something crashes, you reload the page. When you're writing drone code and something crashes, the drone crashes. Into whatever's below it. Usually something expensive or fragile or alive.&lt;/p&gt;
&lt;p&gt;C++ and Python dominate robotics. Both assume you'll handle edge cases yourself. Sensor returns &lt;code&gt;null&lt;/code&gt;? That's your problem. Timing deadline missed? Good luck. No fallback path for when the lidar fails over water? Figure it out.&lt;/p&gt;
&lt;p&gt;ROS (Robot Operating System) helps with some of this, but it's an entire infrastructure layer. What I wanted was something simpler: a language where the compiler catches the stuff that kills robots before you ever compile it.&lt;/p&gt;
&lt;p&gt;Here's what I mean. In C++, you write:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;float distance = sensor.read();
float speed = target_distance / distance;
motor.set(speed);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;distance&lt;/code&gt; is 0, you get a division by zero. If &lt;code&gt;sensor.read()&lt;/code&gt; returns &lt;code&gt;NaN&lt;/code&gt;, you get &lt;code&gt;NaN&lt;/code&gt; propagation through your motor controller. The compiler doesn't care. It'll happily compile this and let your drone fall out of the sky.&lt;/p&gt;
&lt;p&gt;In Fabric (the language I built), you'd write:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;sensor distance: Sensor&amp;lt;f32, ±0.02&amp;gt;
actuator motor: Motor

loop {
    let speed = target_distance / distance
    motor.write(speed)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you try to use &lt;code&gt;distance&lt;/code&gt; without checking that the sensor returned a valid reading, the compiler throws an error. If &lt;code&gt;distance&lt;/code&gt; could be zero and you didn't add a fallback path, the compiler throws an error. If your sensor has an uncertainty bound of ±0.02 and you're doing math that could amplify that uncertainty past a safety threshold, the compiler throws an error.&lt;/p&gt;
&lt;p&gt;The compiler knows about physics. Not perfectly, but enough to catch the stuff that actually kills robots.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;how-it-works-under-the-hood&quot;&gt;How it works under the hood&lt;/h3&gt;
&lt;p&gt;I wrote the whole thing in Rust. About 4,500 lines across 8 crates. Here's the pipeline:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;.fab source → Lexer → Parser → AST → Type Checker → Fallback Graph → IPET Timing → CodeGen → .py / .c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each step catches a different category of mistakes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The type system&lt;/strong&gt; tracks sensor uncertainty as a first-class concept. When you declare &lt;code&gt;Sensor&amp;lt;f32, ±0.02&amp;gt;&lt;/code&gt;, that &lt;code&gt;±0.02&lt;/code&gt; isn't decoration. It propagates through every math operation. Add two sensors with ±0.02 uncertainty and the result has ±0.04. Multiply by a constant and the uncertainty scales accordingly. If the final result's uncertainty exceeds what's safe for your actuator, the compiler catches it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fallback graph&lt;/strong&gt; checks that every sensor has a plan B. Not just declared, but actually reachable. If your fallback function A calls fallback function B, and B calls A, that's a cycle. The compiler detects it. If sensor X has no fallback at all, the compiler refuses to build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IPET timing analysis&lt;/strong&gt; uses an Integer Linear Program to prove worst-case execution time at compile time. It builds a control flow graph, assigns cycle costs to each instruction (ARM Cortex-M4 model: ALU = 1 cycle, float division = 14 cycles, sensor read = 2 cycles), and solves for the maximum possible execution time across all code paths including loops.&lt;/p&gt;
&lt;p&gt;I didn't come up with this technique. It's from Li &amp;amp; Malik's 1994 paper on implicit path enumeration. But I implemented it in Rust using a pure-Rust ILP solver called &lt;code&gt;good_lp&lt;/code&gt; with the &lt;code&gt;microlp&lt;/code&gt; backend. No external solver dependency. No C FFI. Just Rust solving linear programs.&lt;/p&gt;
&lt;p&gt;The solver maximizes &lt;code&gt;sum(cost_i * x_i)&lt;/code&gt; subject to flow conservation constraints. If the solver fails (which happens on really complex control flow), the system falls back to a conservative estimate instead of crashing.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-two-target-code-generation&quot;&gt;The two-target code generation&lt;/h3&gt;
&lt;p&gt;Fabric compiles to two backends: Python for Webots simulation, and C for ARM Cortex-M hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Python output&lt;/strong&gt; generates a Webots controller class with sensor initialization, motor setup, fallback state tracking, and all the logic. You can test your drone code in simulation before touching hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C output&lt;/strong&gt; generates code that includes a &lt;code&gt;hal.h&lt;/code&gt; hardware abstraction layer. Static sensor handles, &lt;code&gt;#define TIMEOUT_MS&lt;/code&gt; for fallback deadlines, proper C types (&lt;code&gt;float&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;), and deadline enforcement using &lt;code&gt;hal_get_time_ms()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Same source file, two completely different targets. No &lt;code&gt;#ifdef&lt;/code&gt; in your code. No conditional compilation. The compiler handles the target-specific stuff.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-i-d-do-differently&quot;&gt;What I'd do differently&lt;/h3&gt;
&lt;p&gt;The parser is hand-rolled. About 700 lines of Pratt parser with recursive descent for statements. I started with chumsky (a Rust parser combinator library) but their API changed between versions and the documentation was sparse when I needed it most. So I wrote my own.&lt;/p&gt;
&lt;p&gt;It's fine. But it means every time I want to add a new syntax construct, I'm writing parser code by hand. A proper parser generator would've saved time in the long run, even with the initial investment.&lt;/p&gt;
&lt;p&gt;The loop bound estimation is a heuristic. If your loop body has 1-3 statements, the compiler assumes it runs 10 times. 4-6 statements? 5 times. 7+? 3 times. This is obviously wrong for real programs. Proper static bound analysis would make the IPET results much more accurate. It's on my list.&lt;/p&gt;
&lt;p&gt;The C output references a &lt;code&gt;clamp()&lt;/code&gt; function that it never defines. If you actually try to compile the generated C code on hardware, you'll get a linker error. I know about it. I just haven't fixed it yet.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-i-m-publishing-this&quot;&gt;Why I'm publishing this&lt;/h3&gt;
&lt;p&gt;I put all 8 crates on crates.io. The lexer, parser, type checker, everything. The repo is at github.com/subhansh-dev/fabric.&lt;/p&gt;
&lt;p&gt;Partly because I want other people to try it. If you're working on robotics or drones and you've been bitten by runtime errors, Fabric might save you some pain.&lt;/p&gt;
&lt;p&gt;Mostly because I think the idea matters more than my implementation. The safety-critical systems world has had formal methods and static analysis for decades. But it's all locked behind expensive tools and enterprise licenses. I wanted to build something that a 17-year-old with a Raspberry Pi could use.&lt;/p&gt;
&lt;p&gt;Is my implementation perfect? No. The IPET loop bounds are guesses. The C backend doesn't handle drone swarms. The match expression codegen references some variables it doesn't always generate. I know about all of these. They're bugs, not features, and I'll fix them.&lt;/p&gt;
&lt;p&gt;But the core idea is sound: compile-time safety for robotics shouldn't require a $50,000 license for Simulink. Sometimes the right answer to &quot;how do we prevent this bug&quot; isn't &quot;write better tests&quot; or &quot;add more runtime checks.&quot; Sometimes it's &quot;make the compiler say no.&quot;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-s-next&quot;&gt;What's next&lt;/h3&gt;
&lt;p&gt;I'm working on adding hardware-in-the-loop testing support. The idea is that Fabric could instrument your actual hardware and compare runtime sensor readings against the compile-time uncertainty bounds. If reality diverges from what the compiler predicted, you get a warning before your next flight.&lt;/p&gt;
&lt;p&gt;Also working on proper static loop bound analysis. The current heuristic is fine for demos but useless for real deployments. I'm looking at abstract interpretation techniques to actually prove bounds instead of guessing.&lt;/p&gt;
&lt;p&gt;If any of this sounds interesting, check out the repo. Open an issue. Try it on your own robot. Break it and tell me how.&lt;/p&gt;
&lt;p&gt;That's how this gets better.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Fabric is MIT licensed. The crates are published on crates.io. The docs are in the README because I'm 17 and haven't written proper docs yet.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;gh repo link :- &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/subhansh-dev/fabric&quot;&gt;https://github.com/subhansh-dev/fabric&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22891/i-built-a-programming-language-because-c-almost-killed-my-drone</guid>
<pubDate>Fri, 17 Jul 2026 14:10:22 +0000</pubDate>
</item>
<item>
<title>Gloria JIT v4.4.0 — Bare-Metal Control, Memory Primitives, and Structured Flow</title>
<link>https://coderlegion.com/19452/gloria-jit-v4-4-0-bare-metal-control-memory-primitives-and-structured-flow</link>
<description>&lt;h3 id=&quot;what-is-gloria-jit-&quot;&gt;What is Gloria JIT?&lt;/h3&gt;
&lt;p&gt;Gloria JIT is a low-level programming language and compiler that is part of the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/forgezero-cli/forgezero&quot;&gt;ForgeZero&lt;/a&gt; ecosystem. It is written in Go and compiles source code directly to x86-64 machine code — no LLVM, no GCC, no Clang in the middle.&lt;/p&gt;
&lt;p&gt;The goal is straightforward: give the programmer direct, unmediated control over the machine. No intermediate representation handed off to a third-party backend. No optimizer making decisions you didn't ask for. The compiler emits raw bytes, and those bytes run.&lt;/p&gt;
&lt;p&gt;This makes Gloria JIT an interesting project for anyone curious about how compilers actually work, or for developers who want to explore bare-metal programming without the abstraction layers that most toolchains introduce.&lt;/p&gt;
&lt;p&gt;v4.4.0 expands the language significantly, adding structured control flow, direct memory and I/O access, and a bare-metal output path for VGA framebuffer writing.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;while-loops-structured-control-flow&quot;&gt;&lt;code&gt;while&lt;/code&gt; Loops — Structured Control Flow&lt;/h3&gt;
&lt;p&gt;Before this release, repeated execution required manual branching. v4.4.0 adds proper &lt;code&gt;while&lt;/code&gt; loops.&lt;/p&gt;
&lt;p&gt;A loop runs as long as its condition is non-zero. Inside the loop body you can use standard assignment and mutation operators (&lt;code&gt;=&lt;/code&gt;, &lt;code&gt;+=&lt;/code&gt;, &lt;code&gt;-=&lt;/code&gt;), and built-in calls are permitted as well. This is a meaningful step toward the kind of control flow you'd expect from a general-purpose language.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;memory-primitives-peek-and-poke&quot;&gt;Memory Primitives — &lt;code&gt;peek&lt;/code&gt; and &lt;code&gt;poke&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Two new built-in functions expose direct memory access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;peek(address)&lt;/code&gt; — reads a 16-bit value from the given address&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poke(address, value)&lt;/code&gt; — writes a 16-bit value to the given address&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both accept either immediate values or runtime variables as arguments.&lt;/p&gt;
&lt;p&gt;This is the kind of primitive that exists in very few high-level languages, but is essential for bare-metal work — writing to hardware registers, inspecting memory-mapped I/O, or building your own allocator from scratch. Handle with care.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;x86-64-port-i-o&quot;&gt;x86-64 Port I/O&lt;/h3&gt;
&lt;p&gt;For environments that use port-mapped I/O (common in older PC hardware and embedded x86 systems), two new built-ins are available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;in8(port)&lt;/code&gt; — reads a single byte from the given I/O port (zero-extended)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;out8(port, value)&lt;/code&gt; — writes a byte to the given I/O port&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This enables direct hardware interaction at a level that most programming languages simply do not expose.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;vga-framebuffer-output&quot;&gt;VGA Framebuffer Output&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;print(string)&lt;/code&gt; now supports a bare-metal execution path that writes directly to the VGA text buffer at memory address &lt;code&gt;0xB8000&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For context: on x86 PCs, this address is where text-mode video memory lives. Writing bytes there places characters directly on screen — no operating system, no drivers, no system calls involved. This is how early PC software (and modern bootloaders) produce output.&lt;/p&gt;
&lt;p&gt;Details of the implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Default text color is green (&lt;code&gt;0x0A&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Register &lt;code&gt;R15&lt;/code&gt; is reserved as a cursor offset and is preserved across calls&lt;/li&gt;
&lt;li&gt;Escape sequences &lt;code&gt;\n&lt;/code&gt; and &lt;code&gt;\t&lt;/code&gt; are resolved at compile time into the appropriate control characters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To support testing without real hardware, two utilities are included: &lt;code&gt;patchVGA()&lt;/code&gt; swaps the real framebuffer address for a heap-allocated buffer, and &lt;code&gt;dumpVGA()&lt;/code&gt; renders that buffer to stdout via a direct syscall, with zero heap allocations.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;register-constants&quot;&gt;Register Constants&lt;/h3&gt;
&lt;p&gt;To reduce ambiguity in the backend IR and make generated code easier to reason about, named constants have been introduced for all general-purpose x86-64 registers:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;regRAX(0), regRCX(1), regRDX(2), regRBX(3),
regRSP(4), regRBP(5), regRSI(6), regRDI(7),
regR8(8) ... regR15(15)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;internal-changes&quot;&gt;Internal Changes&lt;/h3&gt;
&lt;p&gt;A few backend improvements shipped alongside the language features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;emitLowLevelPrint&lt;/code&gt; now accepts a &lt;code&gt;kernelMode&lt;/code&gt; flag to switch between syscall-based output and direct VGA writes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;emitPushReg&lt;/code&gt; and &lt;code&gt;emitPopReg&lt;/code&gt; now cover the full register set including R8–R15&lt;/li&gt;
&lt;li&gt;New operations: &lt;code&gt;emitMovMemToReg64&lt;/code&gt;, &lt;code&gt;emitMovRegToMem64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parseStringLiteral&lt;/code&gt; handles escape sequences at compile time rather than at runtime&lt;/li&gt;
&lt;li&gt;&lt;code&gt;emitBareMetalPrint&lt;/code&gt; introduced for the VGA output path&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;where-this-is-heading&quot;&gt;Where This Is Heading&lt;/h3&gt;
&lt;p&gt;With v4.4.0, Gloria JIT operates in two modes simultaneously: as a userspace compiler with kernel-aware syscall output, and as a bare-metal code generator capable of running without an operating system underneath it.&lt;/p&gt;
&lt;p&gt;The next focus areas are optimization passes and IR stability. If you're interested in how compilers work from the ground up — or in low-level x86 programming without giving up a proper language — this is worth following.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Gloria JIT is part of the ForgeZero project. Follow along on [AlexVoste](&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/forgezero-cli/forgezero&quot;&gt;https://github.com/forgezero-cli/forgezero&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/19452/gloria-jit-v4-4-0-bare-metal-control-memory-primitives-and-structured-flow</guid>
<pubDate>Mon, 01 Jun 2026 22:29:15 +0000</pubDate>
</item>
</channel>
</rss>