Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Axis – A systems programming language with Python syntax (github.com/agdnoob)
14 points by AGDNoob 21 days ago | hide | past | favorite | 26 comments


I built AXIS as a learning project in compiler design. It compiles directly to x86-64 machine code without LLVM, has zero runtime dependencies (no libc, direct syscalls), and uses Python-like syntax. Currently Linux-only, ~1500 lines of Python. All test programs compile and run. The one-line installer works: curl -fsSL https://raw.githubusercontent.com/AGDNoob/axis-lang/main/ins... | bash It's very early (beta), but I'd love feedback on the design and approach!


It's neat to see an attempt at writing a compiler in Python without using a compiler toolkit and without writing it in Haskell. But also, I think you're running past some of the hard problems without solving them.

For example, your while-loops here

https://github.com/AGDNoob/axis-lang/blob/main/code_generato...

look like they might not be able to nest, since they assume the condition is always in eax and the loop doesn't push it down. So you'll need some kind of register allocation, which is a terrible pain in x86.

Also, I think it's worth coming up with an opinion about what other system programming languages are missing. And do the minimum work to provide that as a proof of concept, rather than trying to build a competitor to Zig right out of the gate. For example, maybe you have a perspective on a datastructure that should be a first class citizen, or maybe you've discovered the next best construct since async. Having that kind of vision might help focus the effort.


Thanks, that's fair criticism. You're right about the while-loop thing, that code was very naive and did break with nesting. I actually ran into exactly the pain you described and ended up fixing it the hard way. It was one of the moments where I realized how quickly you start fighting the architecture instead of working on the language itself. About the bigger point: I agree with you, and that's kind of the direction I'm drifting towards now. I'm not really interested in competing with Zig feature-for-feature. What I'm more interested in is whether there's a different mental model for system programming that feels simpler. I originally planned to add pointers, but they gave me massive headaches. That was exactly the point where "low-level" and "simple" started to completely collide in my brain. The more I tried to make pointers feel clean, the more complex everything became. So the current idea I'm exploring is: what if you could write system-level code without having to think in memory addresses at all, but still keep things explicit and predictable? More like thinking in values and state changes, instead of locations in memory. That's still very much an experiment, but that's the "missing opinion" I'm trying to test

Where is the "python syntax"?


I suspect that was in the initial prompt that was used to generate this and the LLM decided Rust syntax was preferable.


Yes, it looks almost exactly like Rust. Expectations violation! :)


Yeah that's fair. It's got "fn main()", types like "i32", and uses braces. More Rust-like than Python to be honest. The "Python-like" part is mostly wishful thinking about readability. Should've just called it "minimalist systems language" or something


I was hoping for no {}, just indentation, but ...


Indent-based syntax is relatively simple to parse. You basically need two pieces of state: are you in indent-sensitive mode (not inside a literal, not inside a parenthesized expression), and what indentation did the previous line have. Then you can easily issue INDENT and DEDENT tokens, which work exactly like "{" and "}". The actual Python parser does issue these tokens.

Actually Haskell has both indent-based and curlies-based syntax, and curlies freely replace indentation, and vice versa (but only as pairs).


> You basically need two pieces of state

That’s enough for INDENT, but for DEDENT you also need a stack of previous indentation levels. That’s how, when the amount of indentation decreases, you know how many DEDENTs to emit.

The requirement for a stack means that Python’s lexical grammar is not regular.


Yeah braces made the parser way simpler for a first attempt. Significant whitespace is on the maybe-list but honestly seems scary to implement correctly


I feel like Python-style indentation should be much easier to parse intuitively (preprocess the line, count leading levels of indentation) than by fully committing to formal theory. Not theoretically optimal and not "single-pass" but is that really the bottleneck?


Yeah, that’s fair. Conceptually it’s not that hard if you’re willing to do a proper preprocess pass and generate INDENT and DEDENT tokens. For this first version I mostly optimized for not shooting myself in the foot, braces gave me very explicit block boundaries, simpler error handling, and a much easier time while bringing up the compiler and codegen. Significant whitespace is definitely interesting long term, but for a v0 learning project I wanted something boring and robust first. Once the core stabilizes, revisiting indentation based blocks would make a lot more sense


Fair enough.

Might I suggest that now is a good time to try and make a concrete wish-list of syntax features you'd like to see, and start drafting examples of how you'd like the code to look?


embrace the brace, dude


It's my belief that the author has almost entirely used an LLM to put this together. Tailor engagement accordingly.


It's definitely odd that someone who allegedly wrote a complete compiler in Python would describe something that is obviously Rust syntax as Python-like.


I totally agree. "Python-like" was a bad choice of words on my part. I meant it more in terms of learning curve and explicitness, not the surface syntax. Structurally its more like C/Rust and I should have said that from the start


Could you tell us, did you, or did you not, use "AI" in creating this project?


Yes, I used AI during development. I treated it as an assistant for explanations, brainstorming, and occasional small code snippets. The language design, compiler architecture, semantics, and the majority of the implementation were written and decided by me


I doubt an LLM would have written this:

       # Parameter in Stack-Slots laden (für MVP: nur Register-Args)
        # Semantic Analyzer markiert Params mit is_param=True
        # Wir müssen jetzt die first 6 Args aus Registern laden
        # TODO: Implementiere Parameter-Handling
        # for now: Params bleiben in Registern (keine lokalen Vars mit gleichem Namen)

Also I love that I can understand all of this comment without actually understanding German.


How do you know this? It looks more like some kid’s homework


> 4. No Magic – No hidden allocations, no garbage collector, no virtual machine

I assume also "5. No stdlib"? Will it be even able to print("Hello world") not by doing a direct write() syscall?


Right now there’s intentionally no stdlib, so yes, printing would ultimately boil down to a direct write syscall. The idea is that the core language stays as thin as possible and anything higher level lives on top of that, either as compiler intrinsics or a very small stdlib later. For the MVP I wanted to make the boundary explicit instead of pretending there’s no syscall underneath. So “Hello world” will work, but in a very boring, low level way at first


It looks like yet another C-like language with same problems C has, notably memory-safety.


The author's said it's "a learning project in compiler design", so I guess solving problems of C wasn't one its goals.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: