Building Confidence in Luma: From Errors to Insight

crowned.phoenixcrowned.phoenix
3 min read

One of the big goals of Luma has always been to feel like a developer-friendly language: expressive when you write code, predictable when you run it, and helpful when something goes wrong. Over the past weeks, we’ve been putting a lot of effort into that last part — making sure that when Luma programs fail, they fail with clarity.

From Go errors to Luma errors

Luma compiles down to Go, but raw Go errors were never good enough. They pointed to the generated code, not the Luma file you were working in. Debugging meant reading Go stack traces and mentally mapping them back to your Luma code — frustrating and confusing.

We’ve solved that by teaching the Luma compiler to carry source positions (line, column, file) all the way through. Every token, every AST node, every generated line of Go now knows exactly which piece of Luma it came from. And when Go sees those //line directives, its own compiler and runtime report Luma line numbers directly.

Now, if you mistype a variable, the error isn’t “undefined: _tmp123” in main.go — it’s a clear “undefined variable” at main.luma:5. If your program crashes at runtime, the stack trace points right back to the Luma line where it happened.

Why this matters

This might sound like plumbing, but it’s actually a huge milestone. It means Luma isn’t just compiling, it’s starting to feel like a real language: one that respects the developer’s perspective. You write Luma, you see Luma errors, you debug in Luma. The Go layer becomes invisible — as it should be.

What else we tackled

  • We expanded Luma’s logical operators (&&, ||, !) so conditions feel natural and safe.

  • We improved operator precedence, so a == 1 && b == 2 now does what you expect — no surprises in grouping.

  • We added proper support for optional types in comparisons, so you can safely check things like x > 2 even if x might be nil.

  • We created a clear plan (and tooling) for core runtime functions — the built-in helpers that Luma ships with — and standardized how they’re stored and injected.

  • And we built out tests that intentionally cause errors and crashes, just to verify that the compiler points back to the right Luma lines.

Looking ahead

The foundation is strong. Luma is now not only compiling to efficient Go, but also guiding developers when something goes wrong. That’s the hallmark of a language you can actually build with.

Next up, we’ll be polishing the developer experience even further — improving the playground, stabilizing the core library, and exploring richer debugging features. But for now, we’re celebrating a big step forward: Luma is no longer just code that runs, it’s code that tells you what went wrong, where, and why.

0
Subscribe to my newsletter

Read articles from crowned.phoenix directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

crowned.phoenix
crowned.phoenix