DEV Community

JAI LALAWAT
JAI LALAWAT

Posted on

I Built a Programming Language from Scratch — No C, No LLVM, Just Raw Assembly

TL;DR

I spent the last several months building Jda — a self-hosted systems programming language bootstrapped entirely from raw x86-64 assembly. No C. No Rust. No LLVM. The compiler compiles itself, and it beats C on 3 of 5 benchmarks while compiling 33x faster than Rust.

👉 jdalang.org | GitHub


Why Build Yet Another Language?

Most "new" languages are built on top of existing infrastructure — LLVM, GCC, or at minimum a C runtime. That's totally valid, but it always felt like a shortcut to me.

I wanted to understand what a language actually is at the lowest level. So I started from scratch: raw x86-64 assembly, no external dependencies, no C library, nothing. Just me, the CPU manual, and a lot of patience.

The result is Jda — a fast, modern systems language where the compiler:

  • Is written in Jda itself (self-hosted)
  • Produces a ~1 MB static binary with zero external dependencies
  • Compiles in an average of 43ms

Performance: Does It Actually Work?

I benchmarked Jda against C (gcc -O2), Rust, Go, and Python in the same Docker environment.

Runtime (lower is better)

Benchmark C Jda Rust Go Python
sieve 1M 27ms 24ms 31ms 32ms 416ms
sum 100M 57ms 49ms 30ms 80ms 8,183ms
json parse 50K 32ms 31ms 33ms 90ms 159ms
matmul 200x200 30ms 37ms 32ms 40ms 2,265ms
fib(35) 40ms 148ms 62ms 126ms 2,826ms

Jda beats C on 3 of 5 benchmarks. 54x faster than Python on average.

Compile Time (lower is better)

Benchmark C (gcc) Jda Rust Go
sieve 1M 479ms 45ms 1,579ms 658ms
sum 100M 434ms 40ms 1,209ms 678ms
fib(35) 495ms 42ms 1,269ms 746ms

11x faster than gcc, 33x faster than Rust, 16x faster than Go.


What Does Jda Look Like?

It's clean and familiar — think Go meets Rust without the boilerplate.

// A ripgrep-style file searcher in ~20 lines
import "file_io"
import "string"

fn search_file(path: &i8, pattern: &i8, pat_len: i64) -> i64 {
    let fd = file_open(path, 0)
    defer file_close(fd)
    let buf = file_read_all(fd)
    let matches = 0
    for i in range(str_len(buf)) {
        if substr_match(buf, i, pattern, pat_len) {
            print_match(path, line_num, buf, i)
            matches += 1
        }
    }
    ret matches
}
Enter fullscreen mode Exit fullscreen mode

Structs and traits follow a Rust-style model:

trait Shape {
    fn area(self: &Self) -> i64
}

struct Circle { radius: i64 }

impl Shape for Circle {
    fn area(self: &Circle) -> i64 {
        ret self.radius * self.radius * 3
    }
}
Enter fullscreen mode Exit fullscreen mode

And concurrency uses Go-style green threads with typed channels:

fn producer(ch: Channel<i64>) {
    for i in range(100) {
        channel_send(ch, i)
    }
    channel_close(ch)
}

fn main() -> i64 {
    let ch = channel_new<i64>()
    spawn producer(ch)
    ret 0
}
Enter fullscreen mode Exit fullscreen mode

What's in the Box?

Jda ships with 117 stdlib packages including:

  • Networking, HTTP client/server, WebSockets
  • Crypto, JSON, regex, archives (tar/zip/gzip)
  • Tensors, autograd, and neural networks — ML built right in
  • GPU acceleration via AVX-512, PTX (NVIDIA), and ROCm (AMD)
  • Full toolchain: formatter, LSP, doc generator, REPL, fuzzer, race detector, package manager

There's also JDA Forge — a full-stack web framework in the style of Rails, built entirely in Jda.


The Bootstrap Story

The hardest part wasn't the language features — it was the bootstrap.

Every self-hosted compiler faces the chicken-and-egg problem: you need the compiler to compile the compiler. My solution was to write the first version of the Jda compiler in raw x86-64 assembly. From there, I rewrote it in Jda itself, verified the output was byte-identical, and the bootstrap was complete.

The compiler now compiles itself. Every release is verified to produce the same binary.


Current Status

  • ✅ Jda v1.0.0 released (MIT license)
  • ✅ v1.1.0 shipped last week with a macOS native backend
  • ✅ VS Code + JetBrains plugins with full LSP support
  • ✅ 388 tests passing
  • 🔜 ARM/AArch64 native backend
  • 🔜 Windows support

I'd Love Your Feedback

This is still early days and I'm actively looking for feedback on:

  • Language design — anything that feels off or missing?
  • Stdlib gaps — what packages do you need?
  • Tooling — what would make your workflow better?
  • Documentation — what's unclear or missing?

👉 Try it: jdalang.org/docs/getting-started

👉 GitHub: github.com/jdalang/jda-lang

👉 Discussions: github.com/jdalang/jda-lang/discussions

Drop your thoughts in the comments — I read everything. 🙏

Top comments (0)