3 days of refactoring, over 140,000 lines of code touched. All ~2500+ tests still passing. I'm going to sleep! Another all-nighter. Talk about a fun Friday night! :) I frickin love this stuff so much! It's like having an ARMY. A LITERAL ARMY OF PHD's. You can raise mountains in minutes it feels like. That's been my experience. You all may call it slop, but I think spec driven development is great. I just think that if you have to write documentation to explain the code, then either your language syntax isn't precise and easy enough to understand, or you are doing something convoluted and potentially stupid. It's a language surface problem. The languages of the past were constrained by human limitations. In the past you'd be out of your mind trying to write a crazy multi-pass compiler and doing all the tips and tricks to make something fast because a human had to maintain it. If you formally specify the constraints of something, design tests that codify those constraints, and then develop code that passes those tests without cheating or changing them, then these new technologies rapidly gain something that gets much closer to determinism.
I think for me the key thing has been treating the tests like I'd treat my foundation. When something is wrong, or I need to design something, it starts with a spec that tries to solve the domain problems, which turns into a plan for tests that will fail when we run them now, but should pass when we have completed the implementation. You may miss edge cases, but when you identify them, you fix them for good by adding tests for them.
One of the tricky parts is creating a good test harness. You have to have a great harness and I need to go through and improve mine!
Anyways, I'm exhausted folks, pizza is all gone and the mountain dew ran out. Time for me to snooze.
Really enjoyed reading this. Stuff like this is what inspires me to keep pursuing logos language and theorem prover. Things on the roadmap next include stuff like adding first-class inline ASM support. Adding great SPMD and auto-vectorization pipelines, and exploring making verifiable private computation a language primitive when you make things private. If interested, read about some of the planned upcoming enhancements here. :) https://github.com/Brahmastra-Labs/logicaffeine/issues
Hello, author here! The license is BSL 1.1 based on the MariaDB license, the source transitions to MIT on December 24th 2029. We're a small bootstrapped team, and I was worried if I went full on FOSS from the get-go a big player might resell it with a easy one click button to deploy things like the playground and such that's coming soon and I'd struggle to feed myself while maintaining a potentially growing project while others reaped the fruits of the labor. I've seen that kind of thing happen a lot in recent years. I also am aware somebody could code-launder things, but personally I'd take that as a compliment, if somebody truly wants to copy my programming language and such, then I'd be glad to have inspired someone haha! We're tiny, bootstrapped, and nobody has ever heard of us so that kind of attention alone would be awesome!
It's free for individuals, orgs with < 25 people, educators, students, and non-profits, and I'm currently still working through monetization but I'm thinking of taking two paths, one being payment to get the Z3 verification feature that lets you mathematically verify that the code won't panic at runtime. The other being payment to use the tokenizer that will be built with this. If you look here you can see the lexicon to get a better idea how the english compile pipeline works. https://github.com/Brahmastra-Labs/logicaffeine/blob/main/as...
This also makes the language highly configurable as you can change any of the key-words to better suit your brain if you so chose.
Current LLM's biggest bottlenecks in my personal opinion would be the tokenizers and the way they get their info. Imagine if you got fed in random chunks of tokens the way they do. If you could create an AST of the english and use that to tokenize things instead... well at least I have some hair-brained theories here I want to test out. Standard LLM tokenizers are statistical and they chop words into chunks based on frequency, often breaking semantic units. This lexer could perform morphological normalization on the fly, an LLM spends millions of parameters to learn that the word "The" usually precedes a noun, but this parser knows that deterministically. This could be used to break things into clauses rather than arbitrary windows. Even just as a tool for compaction and goal tracking and rule following this could be super useful is my theory. A semantic tokenizer could potentially feed an LLM all parse trees to teach it ambiguity.
There is a test suite of over 1500 passing tests. I do utilize Claude, but I try really hard to prevent it from becoming slop. Development follows a strict RED/GREEN TDD cycle, where the feature gets specced out first, the plan and spec gets refined and tests get designed, then the tests get written and then implementation occurs. It is somewhat true that I can't make as many promises about the code regarding untested behavior, but I can make promises regarding the things that have been tested. The test suite is wired directly into CI. I guess it is fair that some people will feel any code written with the assistance of an LLM is slop, but everyone is still working out their workflows and personally you can find mine here: https://github.com/Brahmastra-Labs/logicaffeine/blob/main/Tr...
TLDR of it would be:
1. Don't Vibe-Code
2. One-shot things in a loop and if you fail use git stash.
3. Spend 95% of the time cleaning the project and writing specifications, spend 5% of the time implementing.
4. Create a generate-docs.sh script that dumps your entire project into a single markdown file.
5. Summon a council of experts and have them roleplay.
6. Use the council to create a specification for the thing you are working on.
7. Iterate and refine the specification until it is pristine.
8. Only begin to code when the specification is ready. Use TDD with red/green tests.
I'm always learning though, so please if you've got suggestions on better ways share them!
Yes, absolutely! I definitely want to look into this, although it's not the top of the current roadmap.
To me, the first step is going to be to really work through and trying to get this right. Do user studies. Watch people write code in this. Watch people with lots of experience, and people with none get tossed into a project written in the LOGOS and told nothing.
Once the language surface is more solid and not as likely to go through major changes, I want to focus our efforts in that direction.
Don't take this the wrong way, but my understanding was that you're vibe coding it?
If that's the case I'd do this from day 1, your parser should be a 1 to 1 mapping of some text to code, this you can easily and rigourously test, then if you want to, you can do other stuff on top
Oh, I'm glad this got picked up! I posted it on New Years day and wasn't sure if it was going to be!
As a bit of background on myself and my goals/targets with this.
I started my career as an embedded software developer writing uCos-III for an RTOS working on medical devices for Cardinal Health where I primarily worked on enteral feeding pumps. From there, I spent a couple years in fintech, before trying my hand at my first startup where I co-founded a company in the quick commerce space. (Think similar to Doordash Dashmarts). When that fell apart I took a job at Hasura where I wrote GraphQL to SQL transpilers and other neat things for about 18 months. I've worked across a few different domains and the motivation behind writing this language is that I am preparing to teach my 13 year old brother how to code and wanted something I could get low level with him on, without losing him altogether.
This is a dual-purpose language and has a dual-AST, and the things I'm currently working on... having switched gears towards spending a couple days on the Logical side of things are adding an actual prover to the Logical AST. I'm getting ready to add a derivation tree struct and incorporate the ability to use a solver to do things like Modus Ponens, Universal Instantiation, etc. I also want to upgrade the engine to be able to reason about numbers and recursion similar to Lean with inductive types.
This is an early access product, it is free for students, educators, non-profits, orgs with < 25 people, and individuals.
It would make my day if I could get some rigorous HN style discussions, and even the critiques!! The feedback and discussions are invaluable and will help shape the direction of this effort.
What a lovely surprise doing my daily HN check before bed and seeing this post. :)
EDIT: I will read and respond to comments when I get up in the morning, feel free to ask questions! Or make suggestions.
These features seem considerably more interesting than the "English to Rust" feature. These data structures and the concurrency stuff seems pretty neat.
I yield to the kernel to allow other threads that do some kind of background work to run. Do I want my application's async tasks to yield every 10ms? I assume that is what is being meant here.
Configurability: We absolutely plan to make the 10ms yield interval configurable (or opt-out) in the runtime settings. It is currently a default safety rail to prevent async starvation, not a hard constraint.
Concurrency Options: It is important to note that LOGOS has three distinct execution primitives, and this yield logic doesn't apply to all of them:
Simultaneously: (Parallel CPU): This compiles to rayon::join or dedicated std::threads. It does not use the cooperative yield check, allowing full blocking CPU usage on separate cores.
Attempt all: (Async Join) & Launch a task: (Green Threads): These compile to tokio async tasks. The cooperative yield is specifically here to prevent a single heavy async task from blocking the shared reactor loop.
So if you need raw, uninterrupted CPU cycles, you would use Simultaneously, and you wouldn't be forced to yield.
with cooperative scheduling, yes. This is indeed something missing from the Rust async ecosystem, tasks are meant to be IO-bound and if they become CPU-bound accidentally they will starve other tasks (async-std tried to fix this, but had some backlash due to overhead IIRC). Go actually puts a yield on every loop body (or used to), to prevent starvation. A 10ms thing will have negligible impact
Also: yielding to the kernel is very costly. Yielding to another task in your own thread is practically free in comparison
Well whatever mental health struggles I am enduring, it is certainly Hasura’s fault. More specifically, Tanmai’s fault. But I’m sure he’ll run the company into the ground without any help needed before too long.
It’s a horrible thing man. Did you not hear the story? I was told I was getting promoted and moved onto a new team at the offsite, then when I went into my performance review expecting the promotion and suddenly I was fired. You know how things go at Hasura… everyone just disappears sooner or later.
You know how it goes… Tanmai decides he doesn’t like someone, so he just kicks them out the door, no matter how hard they work or how much it might hurt his company.
Idk man, I would get out if I were you.
I literally turned down the severance because of just how messed up what they did was, so I could speak about it publicly in places like this.
Check out Logos lang, would love to chat sometime. love that you chose Haskell!
reply