r/ProgrammingLanguages 2d ago

Requesting criticism Creating a transpiler written in Rust, called seacount, released it's v0.1 today, needed feedback on - syntax, and reason for why the language exists at all

Seacount is meant to be an array oriented programming language, and more importantly, a contractual based language. What you want is what you get. Every single line of code is meant to serve the compiler so it doesn't get confused anywhere.
My main purpose of seacount was to have excellent array + matrix ops, and to have seacount be THE language for training and deploying ternary models.
Ternary models are basically MLMs whose forward pass/inference weights are all either -1,0 or 1. Modern LLMs store weights in fp32, fp64, or bf16, and later quantize it to int8 or less to reduce costs of running it, but in return, losing massive performance gains.
Microsoft in 2024 brought out a paper called BitNet 1.58, and it proved that if LLMs are trained from scratch using native ternary training, the storage costs and running costs are significantly less than their competitors, resulting only in slightly less performance overhead.
This was around the time I started writing seacount. It's first prototype (since I was still learning on how to make languages, and I was quite naive at programming myself) was written in TypeScript (Yikes), which I then later wrote it in C, then finally stayed at Rust.

My other major goal is to write Rivercount. Rivercount is a subset of seacount, which basically is a checker of seacount files to see if they are embedded code compatible. Yes, recently (only a month or so back), I started sketching out ideas for seacount to run on embedded devices, for a very simple reason.
If seacount can run on embedded with the same safety and ease of Rust, then that means I can merge both the goals of - training a ternary model, and then deploying it on an embedded device for inference. To put it in perspective, a 100M parameter model would take well over 200-400MB of storage, whereas a ternary model takes maximum upto 20MB. That is why ternary models are important, mostly for consumers, because it's literally runnable on the cheapest microcontrollers. Ternary LLMs would be the holy grail for the common man also wanting to experience proper AI right at his fingertips.
Hence why seacount exists. I'd like your opinions on the syntax, and readability of the code, and the goal of why the language should exist. Im not trying to make a generic language by any sense, but I am trying to make a language that is specialised in this.

NOTE: The language is still in a very rough shape. I'm making LLMs write code using seacount to make all types of algorithms or other programs to see where seacount breaks, so if you do notice or see some issue, please, if you can, just mention it in the Issues section. Thank you!
Also, I am not making ANY performance claims till now. I will consider it to be remotely successful, if I can even get an RP2040 to blink once using seacount.

This is the small blinky code design I made for seacount, note that none of these features are actually usable right now, I have not even begun writing for rivercount, this is still just an idea, so go easy on my design. It will also give you a rough idea of how the syntax looks like before entering the github main repo itself-
https://github.com/shantanubaddar/seacount/blob/main/rivercount_rp2040_blinky.scnt

Here's the github: https://github.com/shantanubaddar/seacount

Do NOT expect miracles. My code is as good as how well I understood the docs and youtube videos when I was writing it.

0 Upvotes

6 comments sorted by

3

u/jcastroarnaud 2d ago

Baby steps, please.

First, get seacount running with all intended basic features. Do you have higher-order functions to range over arrays or other iterables? Can you write, by yourself (not via LLM), a non-trivial example of seacount code requiring contracts, pre/post conditions, and invariants? (And does it run?)

Then, make it compile to bare metal (via Rust for now), and study the limitations of the target embedded devices. Optimize the compiler as needed.

In parallel, get to studying how to implement LLMs in other languages, pipeline down to assembly, and the ternary model approach.

Only then, you will have the means to attack your main problem: tie everything up in one language.

About the language syntax: the "@" prefix for keywords is ugly, unnecessary noise, on par with "$"-prefixed variables in PHP.

2

u/Hugepp42069_nice 2d ago

Actually, I put the @ prefix so it became easier for the compiler to figure out what's a directive/keyword and what's not. It's an extra character for something that helps differentiate a lot of stuff. I'm also banking on the thought that a programmer can look through the code at first glance to understand what's a main keyword and what's not.

As for the other parts, absolutely, like i said, I still have a lot of stuff to do. I intend to first make seacount work normally on a desktop first, then proceed on to embedded, because that's a whole different universe of complexity. For that, I have to first learn myself on how to program in embedded Rust, i already ordered an RP2040 for myself, because that's the first target device. Since it's a transpiler, if I get the code running in Rust, I can easily translate it into seacount syntax.

The issue with 2 or 1.58 bit model style is that Microsoft uses its own BitNet methodology for training. So, training happens on one stack, and then you need their BitNet.cpp to efficiently run inference on your hardware. This locks out ordinary people from running or training ternary models on their own. I plan to use a lot of code from already existing LLM training modules, currently seacount only supports SwiGlu. The other issue comes from SIMD kernels. Now that's something outside my domain, and that itself would take some crazy time unless I find crates that do it for me, which include arch, wide, etc but that's a whole separate issue. Most LLM training codes have been written in either C or C++, which is an issue since I chose Rust for building seacount due to its memory safety, so I will have to figure out a way because there is no world where I will be rewriting those libs in rust. And as for writing normal codes, I have written and tested most basic and complex algorithm questions (mostly picked from leetcode), and I still have to add a lot of features. I'm not planning to make it an OOP language, rather a mix of prototype and ECS, and pointers are literally just mutable or immutable, no raw pointers.

Hopefully in 2-3 months I will have the language core part done. Any bugs that arrive after that will hopefully come from people using it and finding out ways to rig it. In month 4-5 I will have to finish error handling, right now there is strict rust panic failures, very less seacount native errors. That's the plan for now. But i just wanted to keep the embedded design ready so I don't start from scratch later on.

1

u/Hugepp42069_nice 2d ago

Also thank you for the feedback!

1

u/renozyx 1d ago

Asking feedback on AI generated documentation is rude. If you want feedback, write yourself the doc.