I studied engineering because I like to know how things work. Nowadays you hear "study it, you'll have a good career." At my time it was "study it, it's the future." Nobody was thinking about money and web development was at the beginning. I wanted to study audio engineering since I was playing guitar a lot at the time. My brother convinced me last second to enroll into IT as a backup that became the main option pretty soon.
This passion about understanding the HOW was a massive driver. In the audio field I wanted to know how amplifiers work and how I could obtain a certain sound. In IT, no matter the topic, I needed to go deeper. I need to understand algorithms. I need to fully understand how a web server works. Why a system needs a certain part.
As a first Linux distribution I installed Gentoo with a uni colleague of mine. He was more experienced and enthusiastic about Linux and I was fascinated by the fact that Gentoo compiles all the packages with the legendary emerge. That I need to compile the kernel and know my hardware pretty well. Considering that it was 2006 the community was already amazing. The Gentoo documentation was the best around and it was translated in several languages already (at the time having the doc in Italian for me was a big plus). I loved the experience of that installation. It took me 1 week probably to have a usable machine. That was only one example.
Those years saw also the birth of Rails. How does the configuration work? How is this magic put together? What is a Rack server and all the middleware? Years later I re-did the same deep dive with Spring. I understand now that this need of mine to understand kept me away from some more abstract and complex concepts and algorithms. I was never a fast or particularly talented "coder" because if I don't understand the why and how immediately my brain will start grinding gears. Complex algorithms, ML stuff, and so on have always been tough for me. I know the concepts but cannot implement them confidently.
The will of understanding is still there. And that's why I want to go through the process of writing my own JVM-compatible programming language. It came to me like a random thought and the more I was thinking about it the more I remembered I was always fascinated by the concept. Some years ago a friend advised me to read "Ruby Under the Hood" by Pat Shaughnessy an amazing book going through every language feature. That book is a great inspiration for this project and I hope that I can manage to have some results. Another big inspiration is the amazing JRuby project by the great and powerful Charles Oliver Nutter. I will use AI to help me with explanations of the concepts but I will try to code on my own.
Finding My Language's Identity
So here I am, starting this journey with the same curiosity that made me compile kernels in 2006. What kind of language do I actually want to create? The JVM already hosts dozens of languages. Kotlin brought null safety and conciseness. Scala merged functional and object-oriented paradigms. Clojure brought Lisp to the JVM. So what gap am I trying to fill with my language let's call it “rix“?
I needed to examine what I personally find frustrating in existing languages. Java's verbosity? Python's performance characteristics? JavaScript's... well, JavaScript-ness? After some reflection, I realized I wanted something that felt approachable like Ruby but could leverage the JVM's mature ecosystem and performance characteristics. Not revolutionary evolutionary.
The core question became: Should rix lean functional, object-oriented, or try to be everything to everyone? I've seen languages try to do everything and end up with confusing mental models. But I've also seen overly opinionated languages that feel restrictive. My answer: start with a functional lean but don't lock myself into a corner. Hybrid by design, functional by default.
Syntax Philosophy: What Feels Right to My Brain?
Here's where my need to understand everything deeply kicked in. I could go full Lisp with parentheses everywhere, or create something entirely novel. But why make developers learn completely new patterns when there are already elegant solutions?
Looking at Ruby's method definition syntax:
def greet(name)
"Hello, #{name}"
end
This feels right to me. No type annotations cluttering simple functions. No semicolons. The def/end blocks are clear without being verbose. It's what I reach for when sketching ideas on paper.
But wait does this work on the JVM? Ruby's dynamic nature seems at odds with Java's static typing. Here's where I had to dig deeper into how JRuby actually works, just like I did with Rails and Spring years ago. Turns out, you can absolutely start dynamic and add types later. The JVM's Object type can hold anything, and invokedynamic can handle method dispatch.
The Type System Dilemma
This led me to a crucial decision point that reminded me of my Gentoo days do I compile everything from source (static types from day one) or use a package manager approach (gradual typing)?
Option A: Static from the start
def add(x: Int, y: Int): Int
x + y
end
Option B: Dynamic with optional types
def add(x, y) # Start here
x + y
end
# Later evolution:
def add(x: Int, y: Int): Int # Add when needed
x + y
end
I chose Option B. Why? Because I want to use this language while building it, just like I wanted a working desktop while learning Gentoo. Static typing is great, but it adds complexity to the compiler that I'm not ready to tackle in week one. Start simple, evolve incrementally. My brain needs to understand each layer before moving to the next.
The Mutability Question
Functional languages love immutability, but let's be honest about basic programming. My brain started grinding gears on this one:
counter = 0
# How do I increment this if everything's immutable?
I found myself wrestling with purity versus practicality. Purely functional approaches are elegant but can be cognitive overhead for straightforward algorithms. And if I don't understand something immediately, I get stuck.
My compromise: mutable variables, immutable data structures by default.
# Variables can be reassigned (practical)
counter = 0
counter = counter + 1
# But lists don't mutate in place (functional flavor)
numbers = [1, 2, 3]
more_numbers = numbers.append(4) # numbers unchanged
This gives me the best of both worlds: familiar control flow with functional data handling. I can understand and implement this without my brain grinding gears.
Implementation Strategy: Learning by Building
Now for the meta-question: How do I actually build this thing? This is where my engineering background kicks in.
Parser Generation vs Hand-Written: I could write a recursive descent parser by hand for maximum control, but honestly? I want to iterate quickly on syntax, just like I needed that emerge command to quickly try different package configurations. ANTLR lets me modify grammar files and regenerate parsers instantly. Perfect for experimentation and learning.
Bytecode Generation: The ASM library gives me direct control over JVM bytecode without javac's overhead. More work upfront, but I'll understand exactly what my language generates. This is the equivalent of compiling my own kernel more effort, but total understanding.
Build System: Maven for now. Boring but reliable. Like choosing a stable Linux distribution after spending a week with Gentoo.
What “rix” Looks Like (v0.1)
After all this analysis, here's where I landed for the initial version:
# Simple function definition
def greet(name)
"Hello, " + name
end
# Variables and basic types
age = 25
active = true
numbers = [1, 2, 3, 4]
# Control flow as expressions
status = if age >= 18
"adult"
else
"minor"
end
# Function calls
message = greet("World")
puts(message)
Clean, readable, familiar. Nothing groundbreaking, but a solid foundation to build on. Every piece of this I can understand and implement without getting lost in complexity.
Next Steps
With the basic syntax decided, it's time to make this real. That means diving into ANTLR grammar files and getting "Hello, World" to actually compile and run on the JVM. The journey from idea to working interpreter starts now, driven by the same curiosity that made me want to understand how amplifiers work and why Rails was so magical.
Articles I enjoyed this week
Decoupling Your Monolithic Application: A Practical Guide for Software Engineers - Marcos F. Lobo 🗻🧭
How 3 raw visuals teach you REST APIs, Linux Filesystems and SSO Instantly! - Sketech | Unfiltered Dev Notes



