Hi HN! I’m Abhirama, and I started Jaithon in 2023 when I was in 8th grade to teach myself how to code in C. Jaithon 1 was really bad, it was all in one file and it was completely an interpreter and it was extremely slow with bugs everywhere. Recently, I have came back to this project with the goal of making the perfect programming language that is not only fast, but it has the optimal syntax & features out of every programming language.
Jaithon has Python features such as comprehensions, f-strings and first-class functions with declared fields, explicit visibility, traits and checked type annotations, along with syntax choices from lua, Java, bash, c++, go, and rust.
The compiler separates lexing, parsing, type checking and bytecode generation. The VM has 107 opcodes along with a JIT compiler to speed stuff up, polymorphic inline caches and a garbage collector.
Jaithon is nearly completely bootstrapped, with the lexer, parser, and bytecode generation built completely within Jaithon itself. The syntax of jaithon code is also easily customizable.
It would mean a lot if you star the project on my GH as I am trying to reach 15 stars soon :) anyways, lmk if you have any feedback. Currently Jaithon is between Java and C++ for speed (a more detailed benchmark exists within the project by running make benchmark) and I am in the process of optimizing the VM.
I highly recommend you to rethink error handling. No way to know if function throws exceptions, no way to know what kind of exceptions. This is a minefield.
AbhiramaVS I think your choice to use exceptions is fine, it matches closely with Java / Python your inspirations. The "show me every error" crowd loves to harp on this issue, but the truth is, its a tradeoff like all others.
Exceptions provide flexibility in error handling, and most code just forwards and you end up in the same situation anyway. Something like this (go style):
if result, err := do_thing(); err != nil {
log.errorf("Got an error! %v", err);
return err;
}
Or the rust equivalent isn't super useful, the code is just outputting an inferior form of stack tracing and debugging.
Honestly unless the code at the immediate site of the error can handle the issue, or perhaps one level higher, having precise error information (usually obscured by some generic Error class anyway) isn't very helpful, and ends up propagating up to a high level where the whole thing is terminated / cleaned up anyway, which is what exceptions provide automatically.
Also, only catching the things that you can deal with and know about is useful in the sense it keeps code flexible (e.g. you don't handle a DiskFull exception because the only thing you can do with it is throw anyway, and if you had a DiskFull error returned, you would just return it up the stack / panic). As new unhandled errors emerge, you just throw them up the stack, the same way error code would, except errors just require you to explicitly manage the machinery everywhere, requiring rigid, over-specified, fragile code in many cases.
I do see the argument for explicit errors especially in system programming, realtime / perf-critical, kernels, etc. But this language doesn't appear to be targeted at that, and uses GC. So having exceptions seems like a valid design choice to me. Using them also frees you a bit since you can pass around functions, captured references, threads, etc. in a bytecode + GC lang without worrying to much about the error states and memory ownership.
I'm pretty sure I have exactly what you are talking about. error handeling was one of the things that I wanted to get right with jaithon, and I made my system similar to like rust.
error[E0301]: cannot assign to immutable binding `x`
--> examples/demo.jai:7:5
|
5 | let x = 1
| - `x` declared immutable here
...
7 | x = 2
| ^^^^^ assignment to immutable binding
|
help: change the declaration to `var x = 1`
^^ That was shown from the Readme, more extensive examples are in documentation!
Is this what you were refering to or something else, I completely agree that erorr handeling is very important.
I think jyx was talking about the throw/try/catch mechanism[0] used for error handling, in contrast to error handling in e.g. Rust, where the idiomatic way of handling an error is to return a Result enum, containing either a success value or an error type. The latter allows callers to know that a function can error, and what kind of error it can return. Exception-based error handling, on the other hand, means you cannot tell by way of the type system whether or what errors a function can throw.
macos is fully supported (gpu for apple silicon is written with obj C and coco, and the JIT is made for macos) and linux also works without GPU or GUI features. windows isnt supported lol though if you knew what you were doing it wouldnt be hard to port to windows (i personally dont have a windows machine to test/develop for)
This language keeps the best parts of Python while discarding the bad. I clicked the link apprehensively, but I have to agree that this syntax is spot-on (for me, at least). So many new languages miss the mark.
Thank you so much!! That was completley my intention and the reason why I was building it, and im really glad you liked it! To be quite frank, the syntax is more similar to rust compared to python in a couple of ways, but python is what inspired me to build the language.
The syntax is just a combination of my personal preferences :) seems like we share a bunch in common!
Neat, looks more like Rust than Java or Python on the surface though. That’s good in general.
Also am slightly dismayed that new langs are copying the f-string, which was chosen only because Python had no more Ascii punctuation chars left for such a feature. Would much recommend shell-style quote syntax instead, perhaps omitting $.
Yes! Originally jaithon was made when i only knew python and java lol so thats why I chose the name. Recently I made major overhauls to the syntax in perferance to more rust coded sytnax [ cus i really like rust :) ]. Could you elaborate on shell-style syntax? personally I like fstrings and pythons convention, however im open to hear other reasons
Nice! This is what I keep telling everyone: LLMs let you build stuff you may not have the time/energy to before. You still need to do the last 10% yourself though. Tying up all the loose ends.
Syntax is a personal choice. Can always be changed. Architectural choices are difficult to manage later on.
The VM seems to be a stack VM. I have my own python replacement project (https://news.ycombinator.com/item?id=48090665) that I am developing privately for now. LLM-assisted ofc. Started with a bytecode VM and then switched over to a register one. The biggest break from regular language systems was the decision to move to an Erlang-style preemptive scheduler.
I completely agree! I started Jaithon before mainstream LLMs existed and for a while Jaithon was free of AI generated code and my personal stance on AI generated code was rather negative. Recently though, my stance has grown far more positive towards AI. While LLMs are undeniably the future it remains crucial that you completely understand the code being generated, and are also in control of the architecture in place. I have tried to adhere to both of these principals while coding :) and it is an unequivocal fact that AI made me atleast 10x more productive. Granted this is a bad measure but still a measure of such: in the last 2 days I have made the same number of commits as I have to Jaithon in the last 3 years.
Also, I was curious why you swapped over to a register based VM, could you give more clarity on that and the benifits/negatives? currently im using some sort of bytecode vm, though its not like im married to the idea of a bytecode vm.
Also (dont mean this as any sort of advertisement or anything like that) would you mind starring the repo? trying to hit 15 stars :D dont feel forced or anything like that.
There are pros and cons to both approaches. I moved from stack to register because I was writing the code gen backend from scratch in any case and preferred to have a register representation instead of converting from stack to register (which has to happen one way or another). Also mildly helpful with control flow analysis during bytecode generation and verification phases.
>> I was curious why you swapped over to a register based VM
Not the OP but there are real performance benefits, I've been poking at a wasm VM and it has two jit backends where one is pure copy-and-patch while the other caches the locals in registers using the function args + copy-and-patch and there is a significant performance gain just from that alone. A push/pop from a stack is fairly expensive while the register caching keeps things in the CPU's happy place. The smallest gain was ~2x over the interpreter on memory bound tasks while the largest was ~20x on math heave kernels. Admittedly, the interpreter isn't the fastest thing ever as its one and only goal is conformance with the spec to use for differential testing but the difference between the the two jit levels are somewhere in the neighborhood of 1.5-5x depending what the code is up to.
The three biggest performance gains, from the random benchmarks, are quality of the bytecode out of the compiler, the jit itself and register caching from what I can tell from the fancy chart I had Claude make and a good squint. Tail-calling would be somewhere on that list too but I can't measure that as all the opcode do the tail-calls between each other as that's just how it was all put together, the code the interpreter runs is the same code the copy-and-patch jit stitches together as they are both generated from the same DSL. Which is also the biggest cost with the register caching as the code template file grew from tens of kilobytes for the 407(?) wasm opcodes to ~3MB for all the specialized ones to pass the locals in eight args but that's really just a binary size thing, the stitched together functions just pick and chose the ones they need.
Long winded way to say CPUs like when you keep things in registers, I suppose...
More like rust than both of those tbh. When i first made jaithon i named it as such cus back then for one the syntax was vastly different and for two I only knew python and java lol. more recently I changed the syntax to be more similar to rust and js etc.
Jaithon wasn't necessarily based on a particular language or multiple languages even per say, its just my preferences from all the languages ive coded in the past :)
Unfortunately I did not do this :( I think a couple people pointed out but .jai already exists on github (I did not know about this when I first made it lol) and for the readme and stuff I did it via python for the syntax highlighitng lol.
Maybe one day I can plead with the github gods to accommodate for jaithon :)
> I would not consider myself a "vibecoder", or jaithon as "ai slop"
> Additionally, around 80% of the raw code in this repository was produced with agentic coding tools
Not to be a party pooper, but even if the author wouldn't themselves describe it as "slop," the term still applies. It isn't really a "collaboration" if the vast majority of the implementation was carried out by one (non-human) party.
AI Slop is more of a convention than an actual definition. There is no standard definition (from what I know) that is widly accepted for the definition of AI slop: some people might say any use of AI is slop or others might have a more liberal opinion (like me) where if AI is properly used and generates good results, it is not considered slop.
In my personal opinion (you are 100% free to disagree as this is just an opinion and not fact) the 'hard' part of programing is coming up with the proper architecture, and ensuring the codebase is maintainable and is able to be built on top of. Additionally, the word slop in my opinion signals that the product is terrible. In my opinion, the product of Jaithon is not terrible (like some AI generated code is) and as I have not only been highly transparent with the use of AI and also used it with an appropriate maner with limits, by my definitions of it, this is not considered slop.
Additionally, the vast majority of the CODE was carried out by AI, not the implementation. Architecture & language automota were actually created in 2022-2023 while I was in 8th grade. AI was only used rather recently to speedrun development.
Hope this serves as further clarification by what my readme and my words ment.
Yes! I agree. I wish github made this a standard or something like that, I personally just did the best I could with disclosure. Thanks for the kind words!
I know we need to stay positive for these show HN things because Dang said so. But how valuable are these when anyone can churn out one of these things with AI. I get how it's valuable to show off work, but it's also like looking at a play list of AI music.
I recomend you take a shot and try. Originally, I built Jaithon pre chatgpt (2022-2023) and in doing so I read a couple of books my dad owned about language automta and architecture. I stopped working on jaithon not because I couldnt code or anything, but more so because it took so long to actually push something that I would rather just work on a different project. idk maybe im just ADHD but thats just how it went for me.
Anyways, back to your question, the architecture of jaithon is probably the most complex thing, and AI (atleast now) cant do this reliably. Syntax as well is something that is very abstract that AI isnt good at choosing. there is a lot more behind the scenes than simply oneshoting a prompt with opus and expecting it to work (spoiler it wont work well at all.)
Even though people that don't work in tech can now build a lot of stuff I think most wouldn't even know where to begin with stuff like this.
Heck, I work in a web development/design agency with people who code in JS/TS all day and they still couldn't tell you the difference between interpreted and compiled code. Why? Because it's simply not relevant to their daily work.
Jaithon has Python features such as comprehensions, f-strings and first-class functions with declared fields, explicit visibility, traits and checked type annotations, along with syntax choices from lua, Java, bash, c++, go, and rust.
The compiler separates lexing, parsing, type checking and bytecode generation. The VM has 107 opcodes along with a JIT compiler to speed stuff up, polymorphic inline caches and a garbage collector.
Jaithon is nearly completely bootstrapped, with the lexer, parser, and bytecode generation built completely within Jaithon itself. The syntax of jaithon code is also easily customizable.
You can build and run it with:
git clone https://github.com/abhiramasonny/jaithon cd jaithon make ./jaithon examples/hello.jai
It would mean a lot if you star the project on my GH as I am trying to reach 15 stars soon :) anyways, lmk if you have any feedback. Currently Jaithon is between Java and C++ for speed (a more detailed benchmark exists within the project by running make benchmark) and I am in the process of optimizing the VM.
Would love to hear yalls thoughts!
- Abhi (abhiramasonny.com)
I have no reason whatsoever to use this, but it's a cool project!
Exceptions provide flexibility in error handling, and most code just forwards and you end up in the same situation anyway. Something like this (go style):
if result, err := do_thing(); err != nil { log.errorf("Got an error! %v", err); return err; }
Or the rust equivalent isn't super useful, the code is just outputting an inferior form of stack tracing and debugging.
Honestly unless the code at the immediate site of the error can handle the issue, or perhaps one level higher, having precise error information (usually obscured by some generic Error class anyway) isn't very helpful, and ends up propagating up to a high level where the whole thing is terminated / cleaned up anyway, which is what exceptions provide automatically.
Also, only catching the things that you can deal with and know about is useful in the sense it keeps code flexible (e.g. you don't handle a DiskFull exception because the only thing you can do with it is throw anyway, and if you had a DiskFull error returned, you would just return it up the stack / panic). As new unhandled errors emerge, you just throw them up the stack, the same way error code would, except errors just require you to explicitly manage the machinery everywhere, requiring rigid, over-specified, fragile code in many cases.
I do see the argument for explicit errors especially in system programming, realtime / perf-critical, kernels, etc. But this language doesn't appear to be targeted at that, and uses GC. So having exceptions seems like a valid design choice to me. Using them also frees you a bit since you can pass around functions, captured references, threads, etc. in a bytecode + GC lang without worrying to much about the error states and memory ownership.
error[E0301]: cannot assign to immutable binding `x` --> examples/demo.jai:7:5 | 5 | let x = 1 | - `x` declared immutable here ... 7 | x = 2 | ^^^^^ assignment to immutable binding | help: change the declaration to `var x = 1`
^^ That was shown from the Readme, more extensive examples are in documentation!
Is this what you were refering to or something else, I completely agree that erorr handeling is very important.
[0]: https://github.com/abhiramasonny/jaithon/blob/main/LANGUAGE....
The syntax is just a combination of my personal preferences :) seems like we share a bunch in common!
Also am slightly dismayed that new langs are copying the f-string, which was chosen only because Python had no more Ascii punctuation chars left for such a feature. Would much recommend shell-style quote syntax instead, perhaps omitting $.
Syntax is a personal choice. Can always be changed. Architectural choices are difficult to manage later on.
The VM seems to be a stack VM. I have my own python replacement project (https://news.ycombinator.com/item?id=48090665) that I am developing privately for now. LLM-assisted ofc. Started with a bytecode VM and then switched over to a register one. The biggest break from regular language systems was the decision to move to an Erlang-style preemptive scheduler.
Also, I was curious why you swapped over to a register based VM, could you give more clarity on that and the benifits/negatives? currently im using some sort of bytecode vm, though its not like im married to the idea of a bytecode vm.
Also (dont mean this as any sort of advertisement or anything like that) would you mind starring the repo? trying to hit 15 stars :D dont feel forced or anything like that.
Not the OP but there are real performance benefits, I've been poking at a wasm VM and it has two jit backends where one is pure copy-and-patch while the other caches the locals in registers using the function args + copy-and-patch and there is a significant performance gain just from that alone. A push/pop from a stack is fairly expensive while the register caching keeps things in the CPU's happy place. The smallest gain was ~2x over the interpreter on memory bound tasks while the largest was ~20x on math heave kernels. Admittedly, the interpreter isn't the fastest thing ever as its one and only goal is conformance with the spec to use for differential testing but the difference between the the two jit levels are somewhere in the neighborhood of 1.5-5x depending what the code is up to.
The three biggest performance gains, from the random benchmarks, are quality of the bytecode out of the compiler, the jit itself and register caching from what I can tell from the fancy chart I had Claude make and a good squint. Tail-calling would be somewhere on that list too but I can't measure that as all the opcode do the tail-calls between each other as that's just how it was all put together, the code the interpreter runs is the same code the copy-and-patch jit stitches together as they are both generated from the same DSL. Which is also the biggest cost with the register caching as the code template file grew from tens of kilobytes for the 407(?) wasm opcodes to ~3MB for all the specialized ones to pass the locals in eight args but that's really just a binary size thing, the stitched together functions just pick and chose the ones they need.
Long winded way to say CPUs like when you keep things in registers, I suppose...
Jaithon wasn't necessarily based on a particular language or multiple languages even per say, its just my preferences from all the languages ive coded in the past :)
Maybe one day I can plead with the github gods to accommodate for jaithon :)
https://github.com/github-linguist/linguist/pull/5688
> Additionally, around 80% of the raw code in this repository was produced with agentic coding tools
Not to be a party pooper, but even if the author wouldn't themselves describe it as "slop," the term still applies. It isn't really a "collaboration" if the vast majority of the implementation was carried out by one (non-human) party.
In my personal opinion (you are 100% free to disagree as this is just an opinion and not fact) the 'hard' part of programing is coming up with the proper architecture, and ensuring the codebase is maintainable and is able to be built on top of. Additionally, the word slop in my opinion signals that the product is terrible. In my opinion, the product of Jaithon is not terrible (like some AI generated code is) and as I have not only been highly transparent with the use of AI and also used it with an appropriate maner with limits, by my definitions of it, this is not considered slop.
Additionally, the vast majority of the CODE was carried out by AI, not the implementation. Architecture & language automota were actually created in 2022-2023 while I was in 8th grade. AI was only used rather recently to speedrun development.
Hope this serves as further clarification by what my readme and my words ment.
At the point where you add a license, add an AI usage section to your readme. This is a perfect example.
How would the human ever know that, though?
Good job tho! amazing prompting.
Anyways, back to your question, the architecture of jaithon is probably the most complex thing, and AI (atleast now) cant do this reliably. Syntax as well is something that is very abstract that AI isnt good at choosing. there is a lot more behind the scenes than simply oneshoting a prompt with opus and expecting it to work (spoiler it wont work well at all.)
Would love to see you try to do this with pure AI
"Most people on HN", yes, probably.
Even though people that don't work in tech can now build a lot of stuff I think most wouldn't even know where to begin with stuff like this.
Heck, I work in a web development/design agency with people who code in JS/TS all day and they still couldn't tell you the difference between interpreted and compiled code. Why? Because it's simply not relevant to their daily work.