Frontend
Halis: The Side Project That Became My Life's Largest Ambition
Hieu Louis DEV Community
3 views
I never intended to build a programming language.
It began as an idle thought, a question I could not shake during a quiet evening. I had spent enough time writing software to feel the friction that every developer knows: the constant negotiation between performance and safety, between control and convenience, between trusting the programmer and trusting the runtime. I started wondering what a language would look like if it simply refused to accept those compromises. Not as a theoretical exercise, but as a real system that a person could actually run.
What started as a random experiment slowly became something far larger. It became the most ambitious project I have ever undertaken.
That project is called Halis.
What is Halis?
Halis is a compiled, self-hosting systems programming language where safety is the default state, not an afterthought. The compiler, called hlc, is written entirely in Halis itself. Two compilation passes produce byte-identical output, a fact that is verified by the bootstrap chain on every build.
The language is still under active development and has not been publicly announced until now. But the repository is open, the code is available, and the work speaks for itself.
This is not a toy language built for a weekend hackathon. This is a serious attempt to answer a serious question: can a systems language be built so that safety is not a feature, not a checklist, but the very foundation everything else is built upon?
How It Started
I did not have a grand plan. I did not have funding, a team, or a deadline. I had a question that refused to leave me alone.
The more I thought about it, the more I realized that most languages treat safety as something you can add later. You can enable warnings. You can run static analysis. You can adopt best practices. But the language itself does not stop you from writing unsafe code. It allows the mistakes to exist and then asks you to find them yourself.
I wanted something different. I wanted a language where the compiler says no. Where dangerous patterns are rejected before they ever become bugs. Where the default state is safety, not risk.
So I started building. At first, it was pure curiosity. Could I write a lexer? A parser? A type checker? Each small success made the next step seem possible. But somewhere along the way, the curiosity turned into conviction. The experiment turned into a mission. And the mission turned into the largest undertaking of my life.
Why I Kept Going
Most systems languages force a false choice: raw speed with the risk of memory bugs, or protection with runtime overhead you cannot always afford. Halis rejects that trade-off outright. Safety and performance are not opposites. A language should not ask its users to sacrifice one to gain the other.
That belief is not a marketing slogan. It is enforced by the compiler at the deepest possible level. Halis implements seven core guarantees that every program must respect, not because a style guide recommends them, but because the compiler refuses to build anything that violates them.
Seven Core Guarantees
1. I/O is a Declared Effect
In most languages, any function can silently read a file, write to disk, or print to the screen. You cannot know what a function does just by looking at its signature.
In Halis, if a function wants to perform I/O, it must declare it. If a function calls another function that performs I/O, even indirectly through five layers of calls, and that outer function does not declare the effect, compilation fails.
A function without a uses clause is guaranteed pure. It cannot touch the outside world. It cannot surprise you. What you see in the type signature is exactly what you get.
2. Every Operation is Checked
Integer overflow, divide-by-zero, out-of-bounds array access, invalid string indexing. In most systems languages, these are sources of undefined behavior. They are the bugs that turn into security vulnerabilities.
In Halis, they halt safely. There is no switch to disable these checks. There is no escape hatch that turns off safety in the name of performance. The checks stay on, always.
3. No Null, No Uninitialised Variables, No Hidden Globals
These three things are responsible for an enormous fraction of real-world bugs. They are not allowed to exist in Halis.
Everything is explicit. Everything can be audited. You never have to wonder whether a value might be missing, because the type system makes missing values explicit and forces you to handle them.
4. Memory Safety Without Garbage Collection
Use-after-move is a compile error. clone() deep-copies every owned type. The generated runtime uses reference counting with exact free at scope exit.
This is verified in CI with a memory-stress program that runs with a flat RSS under a 256 MB address-space limit. The memory footprint does not grow. It stays flat. That is the kind of proof I care about.
5. Fine-Grained Effects and Capabilities
The single IO effect is split into eight capabilities: IO, Fs, Clock, Args, Exit, Net, Rand, Proc, and Conc. Each is individually declared and statically verified through the entire call graph.
A function that only needs to read the system clock cannot secretly open a network connection. A function that needs to read command-line arguments cannot silently spawn a process. The compiler knows what every function is allowed to do, and it enforces that boundary.
6. Taint Tracking
The built-in generic type tainted[T] wraps any value as potentially attacker-controlled. The compiler statically rejects passing a tainted value to any sink, including print, println, write_file, read_file, file_exists, exit, net_lookup, and proc_exec.
You must sanitize first using the standard library helpers like sanitize_html, sanitize_path, sanitize_sql_identifier, or sanitize_command. If you need to bypass it, there is an explicit taint_unwrap() escape hatch. But it is explicit. It is visible. It cannot happen by accident.
7. Data-Race Freedom by Construction
The Send rule set and the ownership-boundary rule mean sharing a variable with a task outside a channel is a compile error. The type system rejects every data race at compile time.
Concurrency is hard enough without having to worry about two threads silently corrupting the same memory. Halis makes that entire class of bugs impossible.
Self-Hosting: Proof, Not Promise
The compiler source is written in Halis. The Stage-0 seed, written in Python, produces the first native compiler. That compiler then recompiles its own source.
The output of pass one and pass two are compared, and they must be identical, byte for byte. If they are not, the bootstrap fails.
This is how the language grows in itself. It is not bootstrapped by accident. It is bootstrapped by design.
Every time I run the bootstrap and see that diff of zero bytes, I am reminded why this matters. It is not enough to claim that a language is self-hosting. You have to prove it, every single time.
Formal Verification
One of the things I am most proud of is the verification layer. Halis supports formal verification through requires and ensures contracts. The hlprove tool generates proof reports and interfaces with the z3 SMT solver to verify properties about your code. The hlmodel tool performs finite-state model checking.
This is not a toy. These are serious tools for proving that your code does what you say it does, before you ever run it.
In a world where software failures can cost millions of dollars or human lives, this matters more than we like to admit.
Looking Ahead to v1.0-pre
As Halis moves toward v1.0-pre, I am preparing two significant changes that I believe will make the project far more accessible to the community.
First, I will be adding comprehensive documentation. Right now, much of the language's design and behavior lives in the source code, the specification, and my own notes. That is not good enough for a language that I want others to read, understand, and eventually contribute to. By the time v1.0-pre arrives, I intend to have clear, structured documentation covering the language syntax, the core guarantees, the standard library, the tooling, and the security model.
The goal is simple: someone new to Halis should be able to sit down, read the documentation from start to finish, and understand exactly what the language is, how it works, and why it was built this way. No guessing. No digging through commit history. Just clear, honest documentation.
Second, I will be breaking up the large source files into smaller, more focused modules. The compiler currently lives in a relatively small number of large files, which is natural for an early-stage project where the priority was getting the bootstrap working. But as the language grows and more people begin to look at the code, that structure becomes a barrier. Large files are harder to navigate, harder to review, and harder to contribute to.
By the time v1.0-pre is ready, I want the codebase to be split into logical, manageable pieces that make it easier for a new contributor to find what they need, understand how it fits into the whole, and make a meaningful change without being overwhelmed.
These two changes share the same underlying goal: to make Halis not just a language that works, but a project that people can genuinely participate in. A language is not just a compiler. It is a community of people who share a set of ideas about how software should be built. That community cannot grow if the barrier to entry is too high. Documentation and code structure are how we lower that barrier.
Current Status
Halis is at version v0.47.0-alpha. The test suite includes over seven hundred tests covering interpreter execution, native compilation, differential output, and bootstrap determinism. Bootstrap is deterministic. The language is stable enough to be studied, tested, and challenged, but it is not yet production-ready.
I expect v1.0-pre to arrive in 2027, with v1.0 LTS following in 2029.
Those dates are not deadlines. They are commitments.
Why This Matters to Me
I did not build this to chase a trend. I did not build this to add another line to my resume. I built this because I believe the next generation of systems programming needs stronger foundations, and because I wanted to prove that a serious language can be built from first principles with discipline and patience.
This project has demanded years of careful thought, and it will demand many more. There were nights when nothing worked and the bootstrap failed and I questioned whether it was all worth it. But every time I came back, because the question that started this journey still matters to me.
Can we build a language where safety is not an afterthought?
I believe the answer is yes. Halis is my proof.
Repository
The repository is open. The specification is available. The security model is written down. The code is there to be read, compiled, tested, and criticized.
GitHub: github.com/mhieuhonda/halis-lang
Everything is there. The SPEC. The SECURITY file. The compiler source. The standard library. The examples. The test suite.
Read it. Build it. Challenge it.
Final Words
I am not asking you to use Halis in production today. I am asking you to look at it with honest eyes and see whether the foundation is sound. I am asking you to consider whether a language built this way, with safety as the default, with proof as the standard, with discipline as the method, is worth paying attention to.
I believe it is. I believe it deeply.
What started as a random thought has become the largest undertaking of my life. And I am only getting started.
Read original: https://dev.to/hieulouis/halis-the-side-project-that-became-my-lifes-largest-ambition-524b
← Previous
Engineering RAG Pipelines That Survive a HIPAA Compliance Audit
Next →
Claims, Not Facts: Building an Auditable Multi-Author Record for a House
Related
Your Flutter 404 Page Is Probably Crashing, and Your Server Is Probably Lying About It
Frontend
0
DEV Community
how I make my templates easy to reskin (probably overthought this)
Frontend
1
Dev.to (EN Zone)
StyleX won CSS-in-JS because AI agents can read it
Frontend
2
DEV Community
Why I Built a Lightweight Utility Styling Library for React Native (And How It Solves StyleSheet Fatigue)
Frontend
2
DEV Community
Comments0
No comments yet — be the first