"That looks really neat! The automatic analysis and use of multiple data stacks and resizable fields takes it from "lots of work can be done this way" to "basically everything can be".
The relative references and built in binary structure validation also enable direct memory mapping of data structures and immediate use of network data. "Parsing" file and network data is often 100x slower than it needs to be." - John Carmack
The Twitter/X link doesn't show the full thread without a login. It also doesn't tell you that something is missing, so I guess it's normal for people to think they're seeing everything.
Such a cool idea! I've been toying around making a few libraries to force languages to do that direct io zero-read mapping to data structures. Ofcourse this looks way better and infinity less hacky, but it is a fun and trippy experience to find someone working in the same direction as you independently.
Most of my current Goose projects are games, not surprisingly, but I have some language/tooling ideas as well.
As for Amiga E, I am very proud of having made it way back when obviously, but it doesn't stack up against my more modern languages (Goose and Lobster), so I think I'll leave it be :)
What happens if the memory is freed in a different order to allocation? Does the language disallow that? Or does it get allowed but mean the stack can't shrink?
You noted AI creating a large amount of this code base with yourself directing it. Do you have a process that keeps you sane while doing this over such a large codebase?(especially for a brand new concept and implementation) [Obviously congrats and can't wait to read through to have deeper questions!]
> Nested data stays inline. A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it. A record that is 160 bytes and an allocation in C++ is 29 bytes and none in Goose.
It means that to do variable sized things like vectors and strings, C++ often ends up having to allocate their contents dynamically. Which results in data structures with lots of 64-bit pointers over multiple allocations.
Even Rust's "enum" feature, which can store different sized things all in the same space, does that at the cost of the smallest variant being just as big as the biggest.
Goose can do all of that not only inline (no pointers), but with variable size, meaning small items take less space. It's like a serialized data representation, but iterable. It makes for big space savings vs these languages.
As far as I can tell, you're essentially creating a new stack for every dynamically-sized variable (because otherwise nothing would be able to grow by bump allocation without moving). But this means you're creating a separate virtual memory allocation for each of these objects, which (I presume?) then rounds the size up to the OS's minimum page size (4KiB or similar).
Doesn't that waste a lot of space? Or is there something I'm missing?
Also it would seem to force every allocation to go through the OS kernel to allocate unless there's some trick to avoid that.
Only top level growable arrays get their own "stack", if you create an array of arrays it only uses one stack.
How you deal with the inner stack growing depends, ideally they don't grow (construction only), or you can make them fixed size, or with a capacity, or in the worst case, as a pool. The language has facilities for all of these.
I think what you might be missing is that you can also do a sort of livenes analysis to determine how many dynamically-sized variables are "awake" at the same time at most. Then you only need to create as many stacks as that number, because you can reuse the stacks of "sleeping" variables (since the "awake" variables are guaranteed to be freed once their block goes out of scope, and threads don't share any memory so no data race worries regarding those stacks).
For example, suppose we have a function with a growable array that calls another function (without passing said array) that also uses a growable array as some temporary scratch space. Then the first function's array isn't being used when the second is sleeping, so the inner function's array could safely share the stack because it will all be freed with a single pointer restore once the second function exits.
Now, I actually don't know how the compiler works but as I understand it does things similar to my example to optimize the number of stacks needed.
At the end of the day trees are still stored linearly in memory. Think of it as an array, with each node an element of the array, and indexes used rather than pointers.
Plenty of trees only ever grow. And that's the normal type of array in Goose. However you can also have arrays that can grow and shrink, if you have a tree that is constantly in flux.
There are examples in the tutorial, including a circular linked list.
You can just store all them items of the list/tree/whatever on the stack, growing it as needed, or you can add an addition "freelist" for a particular stack, so you can re-use items.
All it's doing is allocating address space. And 64 bits means you have an astronomical amount of that. It only needs to become actual memory when you use it. A page at a time.
> All it's doing is allocating address space. And 64 bits means you have an astronomical amount of that.
No, you can typically only assume 48 bits of virtual address space; the kernel takes half of it, so really only 47 bits. Newer CPUs provide 57 bits (e.g., Zen 4) or 52 bits (certain ARM64 models). And that's provided that the kernel plays ball; apparently some Android configurations only support 39 bits of user virtual address space.
I wish it was more clear about the memory layout of nested variable sized data structures. As far as I can work out the max capacity is decided at construction time which makes the whole thing a lot less intriguing.
You can also just do that in C++. I do that as part of my messaging usually, so that the objects are trivially relocatable and reinterpret-castable. It only works so long as you combine a set of canonical types, but that can be verified or converted using C++26 reflection.
I have both what I call inline sequences, and out-of-line ones (store an offset to the object itself rather than pointers).
I made all my sizes and offset 32-bit, but I suppose they could have been 16-bit.
I think they have slightly different places on the "speed vs ease of use" pareto frontier.
With Goose, the core design favors speed over everything else. Though not only was I able to make that safe, it is fairly pleasant to use. But it remains a low level systems language that requires you to think hard about data organization.
Lobster is a waaay more high level language made to be pleasant to use first, fast second. Surprisingly though, it can get pretty close in speed to C++/Rust nowadays too, but still a lot slower than Goose.
> Threads that share nothing. A worker is compiled as a separate program with its own memory, and flat values cross typed queues as a memcpy. Data races, locks, atomics and memory orderings do not exist in the language.
how to perform this copy without atomics?
do the workers run as threads or processes?
also you claim it's faster than rust and c++. but for certain kinds of software it's certainly (and substantially) slower, right?
The copy is made by the runtime, which obviously does use atomics underneath, but you don't ever use these yourself.
The workers are threads. The separate memory is the concurrency model, but it's still single process, multiple threads.
The "faster than" is on average, and both in my own benchmarks and independent benchmarks you can find examples of algorithms where it is slower, but they tend to be the exception. "substantially" slower I haven't found yet.
> It evaluates 27 programming languages across 50 real-world-inspired tasks using 5 metrics: runtime, runtime score, memory usage, compile time, and expressiveness.
> The "faster than" is on average, and both in my own benchmarks and independent benchmarks you can find examples of algorithms where it is slower, but they tend to be the exception. "substantially" slower I haven't found yet.
Well message passing with literal memcpys (rather than, say, just a shared buffer, like is common in Rust) is very expensive when the messages are huge. Of course as the message size increases, the Rust program will become faster than the Goose one (and if it doesn't, you should look into your benchmarks)
Being more specific, it means that for each message, we are writing on memory twice - one to build our own buffer with the message, and another to make a copy to another worker. Writing twice has an overhead, specially when messages don't fit in the cache - you just need benchmarks with sufficiently large messages to demonstrate it.
Beyond that, there are some algorithms that can be made much faster when written with atomics rather than message passing. (Also there are algorithms that will get faster if you use locks). It's just a matter of finding such examples, and writing a Rust code that will use atomics, compared to a Goose program that uses messages between workers because Goose doesn't expose atomics to the user.
So if you didn't find such examples, it's because you didn't specifically write benchmarks with those scenarios in mind (or, I mean, didn't told your LLM to write this).
That is: if the Rust program and the Goose program do the same thing in the same way, then it's reasonable that Goose is faster on average. But Goose is limited because it doesn't let you do some things, but Rust does, so to compare the languages you need to find those cases where the Goose limitations end up making the software slower
Sure, those cases could bite. I think all my benchmarks (and external benchmarks) are mostly single threaded.
Note that all this supposed copying overhead also has an upside: once the synchronisation has happened, every thread can now run at maximum speed doing single threaded memory allocation with no locking of any kind.
In C++, malloc/new in multithreaded programs needs to essentially go thru a mutex and can make allocation even more expensive than it already is. I am not sure if Rust does the same.
Since in Goose "allocation" is just a pointer bump, we cannot make that multi-threaded, hence the threading model followed from that.
And like a lot in Goose, you have to write your program to fit the language a bit. If you expect to do concurrency on top of a huge graph of constantly changing data that all threads must have immediate access to, it is probably not the language for you. But there are plenty of concurrency models that fit and are blazingly fast.
I've named many of my past languages with animal names, e.g. Lobster.
Goose just popped into my head as cool sounding at the time.
It has no special meaning.
I would throw the entire docs out and write it from scratch in your own words. I get that we live in an era where the machine writes most/all of the code, and I can accept that. What I need, to even consider using and extending this project, is some understanding of what part of the design is yours and what part is accident by Claude. I can't get that from reading Claudese.
We as a society have to cut this low effort commenting out. The documentation is perfectly comprehensible. What action would you take differently if a given feature were implemented by Claude, or a human?
If you've ever been tasked with coming up to speed on a system mostly documented with AI writing, you'll quickly realise how hard it is to trust anything you are reading. Even if the Claude documentation is 100% accurate, you'll never shake the worry that some crucial fact you founded your understanding on was wrong. It's a fast recipe for psychosis.
That's without even mentioning that AI writing can often state the what but not the why. That human perspective is usually the most valuable knowledge to get across in writing.
There’s no reason to trust a human any more than an LLM for this. Humans are not 100% accurate and very capable of making crucial factual errors in documentation. Ask me how I know.
There’s a _very_ good reason. Humans have a much richer mental mental model of the codebase, design decisions, external factors, etc.
Of course Humans can make errors when translating that to English. But if you’ve read any amount of Claudish it should be obvious that interpolating the code to documentation with an LLM typically produces a significantly worse result in almost every way. Except for superficially “sounding” correct.
That’s just not true especially when the author designed the language with the LLM like he says in the end (the AI is very good at forcing you to be specific and make decisions on ambiguous terms): all decisions can be included in the repository in a way the computer can follow and understand, which is a pattern called specification graphs. You can just document things in the docs as well if you want a more basic method.
If you are claiming this language is worse in every way than others that were made by humans alone, could you be specific?? What are the bad things you’ve found? What part of the docs are incorrect? Or are you just commenting without having looked at any of that?
That is not necessarily true if the codebase is written by AI unless the human chose to be involved. That was also not necessarily true before AI either. Human skill level is wildly variable
Above all, I think I like human docs because then I not only know someone has a deep understanding of it, but also that someone can actually be queried about it. With Claude, there is always the accountability problem. If something seems off, do I even have someone other than Claude that understand it all and who is accountable ?
It's probably possible to prompt an LLM into writing well, but most LLM writing that I've seen is poorly structured (e.g., the paragraphs in this post feel like strings of punchy marketing phrases), and the LLMs are too good at sounding like they're saying a lot while saying very little.
Plus, if a human puts the effort into writing something, that signals to me that it's worth something, because human time is much more scarce than LLM time.
I recently saw a language posted that caught my interest. I went into the docs and read the page "How X compares to Y", and Y is my favorite language
Within the first couple of paragraphs and bullets it made a completely false claim that is the opposite of how the language operates, something any person that knows the essentials of it would know. Language Y was listed in the front page as an inspiration (and I don't doubt them) but clearly they either did not read the docs the LLM wrote or did not use the language for long enough to know it has zero structural typing
at that point i just ask an ai questions about how the system works and hope the reasons for particular decisions can be reverse engineered from git history/pr comments etc.
I find your comment much much lower effort than GP you took a snip at. It's true that more ppl may align in your thinking, but dissing the other side's concern as low effort does not belong in hn.
It was not well documented. The significance of using "data stacks that the compiler assigns statically" was NOT clear until I backed out of the page and started reading the HN comments here.
Comprehensibility does not equal correctness or fitness. As if that wasn't enough, or perhaps in most related manner, an LLM/AI cannot be held responsible for what it produces, by nature, especially considering the fact that a _human_ claims all of it as their own work, or at least take responsibility. Meaning that when a parable of documentation is discovered to be bogus, you can't pin it on AI, you go to the human and ask them why the documentation is wrong, and it's not a good look.
For a programming language? It's subpar and you know it.
See this for a language docs site by a small-ish team, but a significant effort was put into making it nice to read: https://tour.gleam.run/everything/
The version of the documentation which I would very much like to see would be a Literate Programming version where all the code is explained from the ground up.
There is! As of now, if you sort by recently updated, my literate programming project is the first result :P (link in profile if anyone reads this later)
In the interest of full disclosure, my own project is in there as well (but nowhere near the top and it's a kind of obscure topic, so not likely to ever get there).
Once a week, I tell Antigravity (3.8-flash) to rewrite every code comment and documentation that was changed in the past week. Neither GPT nor Claude can write like a human.
If you use it often enough, it becomes quite easy to tell. For one, when using it through the chat interface, it always congratulates me on my amazing insight in the first paragraph or at least has a very forthcoming tone. It also has a fetish for numbered lists whenever attempting to make a point, which usually contain 3 items, sometimes 2. It's also quite good at making relatively unhelpful ASCII diagrams on a semi-frequent basis.
That said, I do genuinely enjoy brainstorming with it, and these quirks are not really a hindrance. If anything, the sentiment in the first paragraph is quite useful to quickly get an insight about where I stand with my thoughts, relative to the available knowledge that Gemini has access to.
>>I get that we live in an era where the machine writes most/all of the code
Only on the Internet is this true, not in real life. I cannot and do not trust any of these things to do a proper job because they have not in any situation succeeded in any job I've given them. And no company I deal with claims otherwise
Right I feel like they just got to a point where they can reliably write individual functions with direction. Every time I've tried to use them consistently I feel like I just end up spinning wheels from them doing things that mostly work until it crashes and burns or just has straight up missing things or half truths. Skill issue or not it doesn't work for me.
Still glad I basically never have to debug a build issue or memory error again though
If the Code is bad, you can tell it to fix it to match your expectations —only at the edges, are you going to have to spell it out.
Lack of documentation used to be a running joke.
The goose_spec.txt in 2019 would be "goose is like c and rust only with syntax like array{;}[] btw it uses a small amount of stacks instead of malloc."0 10klocs.
Now, we make sure the AI leaves documentation so it can figure out what it was doing earlier.
A local model a few generations and many weights behind newest Claude can implement my novel algorithms and write the documentation I wouldn't.
Yes, many times it does dumb CS for kindergarten mistakes but it only has to work towards the optimum every once in a while.
Sadly there seems to be no point in arguing online though.
- You need to have a mental model to grow an idea
- When a pattern is known you can use a library!
- When a pattern is not known AI will make stuff up
No matter how "good" coding with an AI will become there is no way you get around learning, having someone understand what's going on and take responsibility.
I'm fine with formal checking and fuzzing or getting hints where a bug might come from - but these are iterations on tools we used before like a debugger, strict types, functional programming and well fuzzing.
I tried to have an AI iterate on a step i don't fully understand yet and i always regretted it. Highly interconnected projects will grind to a halt until you do learn.
You can check with people doing highly specced software in the medical domain that even with very good specs there is ambiguity in natural language thus it can never be the source of reliable and manageable software.
However - i read about some smart guys in the 40s or so encountering the need for a formal language to tell a computer what to do with 0 ambiguity and i think they called it a "programming language"
> I tried to have an AI iterate on a step i don't fully understand yet and i always regretted it.
I had to accept this one too even for pretty simple things. I had an LLM wire up a neovim connection handler for me without bothering to read the libraries docs or neovims RPC spec and I completely regretted it. You would thing such a small piece would be fine but I couldn't work on it and had to rip it out and rewrite it, and reading the AIs reference code actually got me more confused than anything.
I've found the sweet spot for me is just writing code and promoting an AI whenever I have a question or if I'm not sure the code will do what I think. When I hit a point and I groan about doing something, if it's small and I understand what needs to happen already I will ask the LLM I've been prompting already to do it. Usually by that point it's already gotten enough context from the back and forth on my questions or me explaining assumptions it got wrong when reviewing my code.
The tools have a learning curve. You can get extreme amounts of value out of them but you have to learn how to use them. Many tools are this way.
It might make sense to learn now, before everyone expects that you be an expert with this tool in order to do your job. On the other hand perhaps they will be easier to learn if you wait.
There is an incredible amount of nuance to be had in using LLMs and we reached the stage, probably only in the last few weeks where all the pieces have fallen into place such that if you are skilled at using the LLMs just about all of the previous problems with them can now be easily mitigated. If you learn how. There is a lot to learn.
openai has retracted many of their lean proofs for the big drop of supposed novel mathematical solns. if frontier ai screws it up , how does this inconsistency manifest in weaker models?
I wouldn't say that's true at all. My critical reasoning skills have improved immensely as I have learned how to find the flaws in the LLM's logic, and I am much better at code review in general than I was when I first started letting agents write code.
It really is like working with an over-eager employee. They just also happen to be a pathological liar.
> Since 2023, everything learned in Year X was 99% useless in year X+1.
Personally I disagree with this. I've been using LLMs the last few years and learning a lot about techniques for getting value out of them. Even though they weren't very good for a while they seemed worth learning to me because the rate of improvement was so fast. We've now reached a point where if you know how to use them right you can get lots of value out of them.
I really don't mean to be rude here but consider perhaps the reason why you're having trouble seeing why they're valuable is because you haven't used them enough in the last few years or kept up with the developments closely enough. Maybe I'm wrong. But consider it's possible you are too.
> This has also been said every other month since 2023.
I'm sure others have said that but my perspective has been that the models are not quite good enough yet, for a while but that the trajectory is so crazy that it made sense to make the bet and invest lots of time into learning how to use them on the assumption that they would soon be good.
Even now I would say they have a long way to go. What is hard but possible today will be easy tomorrow. But quite a lot is now possible with the right techniques. Crazy things.
I remember using LLMs a couple of years ago, back when there was no mention of "AI" in our country whatsoever. Not that much mention of it online either (much less widespread). I felt like I was holding a magic wand nobody else knew existed. :P
This product is proof that you apparently either don't know how to use AI, haven't used it within the last 3 months, or don't know what you're talking about.
I just wrote a clean plugin in Rust. I don't know rust. It took work to avoid, remove, and replace slop, avoid spurious and pointless tests, etc. It wasn't "fire and forget". but it wrote the code, the code has been made clean, integrates well with existing project structure and does what it's supposed to. I spent a day or two on it, but had I attempted to write it from scratch, even knowing rust, it easily would have taken me longer.
Considering that I don't know rust at all, it's awesome.
Eh, I think the tutorial is pretty readable? It's concise enough.
With the tutorial, the summary also makes more sense. I have not read the other parts yet, but so far I like what I see.
All is in pretty good taste, and I like what I've seen so far. I do not care if the author himself came up with the idea, or if AI came up with it and the author approved.
I do not understand why you "have to" know this to make use of it. You can judge ideas independently of where they came from (and you should).
> You can judge ideas independently of where they came from (and you should).
You can but in practice nobody does this because they don't have time. For example, once you have investigated ideas from a crank a couple of times - you don't do it again. Life is too short.
Couldn’t make it more than a few sentences in before the bile started to build up in the back of my throat and I had to back out. It’s shocking to me that people knowingly post unedited Claude-slop drivel and are seemingly unashamed about it. In 2026, it seems the main role of technical humans should be to act as a barrier between our agents’ output and other humans.
Probably kernel code, or cases where allocation randomization is important. Seems like with goose you may end up executing more deterministically (but still it can randomize where these N data stacks start), but because it's single threaded workers (in essence), all data construction would follow the same pattern, hence an attacker (something snooping your memory) would know easier where things would be.
It does not currently offer automatic AOS -> SOA transform, you'd have to do that yourself. I did look into it, but doing it automatically is not a great fit with how Goose tracks arrays. Maybe can be reconsidered at some point.
Way off topic, but I enjoyed Amiga E. And, I reckon you're one of a handful of people I would take seriously when they say, "I made a new programming language."
Given we are getting to the point where coding agents write most of the code, what motivates you to create a new programming language? Follow up: do you build these languages keeping humans in mind, or are these meant to be used by AI agents?
I've been making languages all my life, and I made this one because I had a really strong design in mind that I think should exist.
Whether it would make sense in this AI world was not a consideration.
The syntax and semantics were mostly designed for humans. That said, using it optimally asks a lot of the human, and in turns out the better LLMs don't break a sweat using it, so maybe it accidentally hits the spot. Goose with LLM can give you lots of speed without the effort.
In some weird way it is a great time to make new languages, because the downside of convincing humans to learn it is gone. Anyone that has a project that needs to be fast can decide to use Goose for it at very little cost.
Thanks for your response. I have been wanting to dip my toe in the space of language building for a while, but keep getting discouraged by the advances of coding agents. Love your reason for building this!
> I made this one because I had a really strong design in mind that I think should exist.
Good question, not sure without testing. Likely it will still give the error. It could elide it, but I am not sure how useful that is.
Optimized builds go thru the local C compiler, so they are limited by the speed of that. Dev/test build can use the built-in libtcc JIT which is super fast.
I have my own language I'm working on in private and it's nice to see other people coming to the same conclusion on region based memory. I was heavily influenced 7 years ago from learning from HandmadeHero and the community around it, and so I made that memory model one of my goals from the start, and it is indeed possible to get very fast programming with it when you make it your default, and when you make the language able to statically analyze it more.
That is about where our similarities end, though, since I'm doing quite a lot of other stuff in the midst as well (much heavier type stuff, fully incremental, retargetable, reflection, integer range tracking, blah blah blah), and the more goals you have, the complexity blows up exponentially. I do think that the region based memory part alone is worthwhile to have as a language feature, so I applaud your pragmatism. I like your syntax for returning through call stacks, too.
There are other languages that do this, though. Did you look into any of the others? Or ones like Odin which give you the configurable bump allocators and scratch space as well? Mainly I'm curious about your opinions of prior art.
anyway, hope this project goes well! the secret of the arena allocator seems to be out now to the mainstream. I think this is also a strength of array programming languages in the tradition of APL/J/K/Q.
As this project develops, I'll get to benefit from your public crowd sourced testing and design before having to publicize mine :P
I will take a better look at Goose some time later when it's not late at night.
Just wanted to drop by and thank you for creating Treesheets. I haven't given its more advanced features the use they deserve, but I love it as a note-taking application for anything that complexity-wise sits between a short outline in a plain text file and a ton of Markdown in something more advanced like Obsidian. And for, of course, any tabular data.
The extra "than" in front of "safe Rust" is superfluous and reads like an error, as if there's a comparative adjective missing ahead of it. I don't see any situation where "and than" should ever appear in any non-contrived English sentence.
So what? He's not a native English speaker, and my interpretation is clearly correct, which the GP has acknowledged.
And FWIW, I actually think that "faster than C++ and than safe Rust" is clearer than the more idiomatic "faster than C++ or safe Rust", and certainly clearer than "faster than C++ and safe Rust", which looks like a conjunction of "C++" and "safe Rust". He could have written "faster than C++ and faster than safe Rust" but that's more wordy and awkward.
Enough of this pointless and irrelevant pedantics ... I won't respond further.
P.S. Just to be complete, here's an AI slop response:
You are completely right, and that is exactly why the author likely structured it that way.
In technical writing, "Faster than A and B" can be highly ambiguous. A reader could easily interpret it in two unintended ways:
• The Sum Interpretation: Faster than the speed of C++ and safe Rust combined (which makes no sense logically, but fits the literal grammar).
• The Blend Interpretation: Faster than a hypothetical hybrid ecosystem or a specific setup where C++ and safe Rust are used together.
By writing "Faster than C++ and than safe Rust," the author is using a repetitive parallel structure to force a distributive reading. It explicitly separates the two entities, making it clear that the language is:
1. Faster than C++
2. Faster than safe Rust
So while it sounds unnatural to a casual reader, it was a deliberate choice to ensure mathematical and logical precision over poetic style.
After reading this comment a little more deeply, I've come to believe your views on methods of written communication are subtly, fundamentally wrong in a way which generally causes more harm than good.
If a sentence has multiple "valid" interpretations, then it doesn't matter what the "correct" interpretation is. If someone says that a sentence is confusing or hard to read, you 100% must believe them and fix it. Dismissing concerns about clarity and ambiguity as merely "pedantic" is one reason why people fail to develop written communication skills. I have been burned many, many times in my career by making charitable assumptions about another engineer's ambiguous language, only to realize much later, after significant cost has been paid, that they had a completely different (and often wrong) idea.
Teaching people to be better writers is a hill I will gladly die on. I don't care if you defend your point or not, just read my comment and try to understand why someone would care deeply about this sort of thing.
It's because in Goose* you write `x > a && x > b`, not `x > (a & b)`. :)
*And really in most if not all, Raku excluded**, languages.
**In Raku junctions can be specified with infix ops, i.e. a | b, a & b, a ^ b, equivalent to list ops any(...), all(...), one(...) respectively, and can define a custom one for none(...).
Oh wow this takes me back. We had very poor internet connectivity when I was growing up, so my brother and I played Sauerbraten and a handful of other games exhaustively with a crossover cable strung between our rooms.
Looking at the repo it seems like the N stacks generated by the compiler are placed at least 2gb apart in virtual memory, have you run into any cases where that has been overflowed during runtime? The compiler cannot know which of the stacks are going to be used more than others and in a large complex program with many stacks any one of them could fail. I imagine this being an issue depends on target application - if you know you are building a game that you know the exact size of your levels / entity counts beforehand you know this is fine but if you were doing data processing / parsing potentially malicious user input it may be a problem.
I'm also interested how the memory locality works. Here you have the bases of your stacks at a series of very sparse virtual memory intervals which will be mapped by the page table to some physical memory addresses, does having them be so sparse cause any issues?
There are some unique ideas here - lifetimes on references to growable+shrinkable stacks, "balancing" stacks in recursive functions - and I'm glad you were able to use coding agents to actually materialize them.
No, not yet.
You can also change that amount if you want, just 2GB is a pretty optimal default.
I am not sure what issues could be caused by the sparsity. Like you say, all that matters is that in physical memory, we are only using what is actually in use.
Is replacing rust a goal? If so I'm in! Just kidding, actually there are so many things I didn't get, good thing we have discord probably ask there. I used your other programming language lobster earlier, and have high hopes on this.
FTR: Go does not remove the semicolons. To the contrary, the lexer inserts them where the Go language grammar requires them. (Which avoids the parsing gotchas as you correctly pointed out.)
C++ code that does what Goose does is a soup of pointer manipulation, casts and byte stuffing. You could write that, but Goose proves it to be safe at compile time, with simple readable code. The moment you write "reasonable" code in C++, it is actually a lot slower than Goose.
But then why isn't Goose a library or framework within C++, or a macro in Rust or something else? Why does it need to be a language?
Also, to be transparent in your benchmarks you should compare against idiomatic safe code, and optimized code. It's trivial to throw your benchmark examples into an LLM and tell it to optimize them to parity with Goose. It's more trustworthy to show other languages can achieve the same performance, Goose isn't doing anything special there. What it is doing is doing the same with better safety guarantees, which I think is headline result not the speed itself.
But it's not infeasible as a preprocessor or macro though, since you're outputting C anyway. You could even output C++ or Rust.
> As for the benchmarks, that's exactly what I do
What I mean is the story of those benchmarks is incomplete, you're missing a column for optimized Rust. This is what I get on my M1 if I ask the LLM to write more performant (still safe) solutions to a couple benchmarks, I'm sure your LLM can do the same:
| Benchmark | vs original Rust | vs optimized safe Rust | Memory vs original Rust | Memory vs optimized safe Rust |
|---|---:|---:|---:|---:|
| `sexp` (flagship workload) | 1.00× | 0.95× | 2.22× | 1.60× |
| `records` | 1.52× | 0.54× | 4.77× | 2.58× |
| `graph` | 1.24× | 0.75× | 1.00× | 1.00× |
I think for the Benchmarks Game entry specifically, for the expert solutions you should use submissions to the game for both C++ and Rust instead of LLM generated code. After all, those are legitimate expert-implemented solutions to the benchmark, so it's nice to not have to lean on an LLM there. That would also give you something to optimize towards.
I seem to remember the ML guys went down this route. I believe they called it regions.
From what little I read in the literature I seem to recall that there were enough programs with quite a bit more memory usage that they decided this approach was a dead end.
Goose is pretty cool. The idea is that you don’t need to make representable all programs: a language for a restricted purpose is ok. As long as you can statically specify the number of growable memory regions, you can use Goose. However, since there’s no garbage collection, you’ll probably need to be careful about memory use while a program is running. Ie: the stacks can get too big if you keep growing them, even as old data is not used any more.
Still, for a large number of programs - like data-oriented applications - it’s probably a good fit. It might work ok with entity-component game systems as long as you reuse old memory…
Why not build in a very simple garbage collector - for example a ref counter - and default to it when you can't prove stack tricks are suficient at compile time? This guarantees all programs can be represented and it removes range anxiety for anyone trying a new language.
Seems any compiled language with automatic memory can make use of the techniques to obtain speed ups.
Almost all languages rely on reallocation when a growable array grows, which means you can't store pointers to elements, as they get invalidated upon a reallocation.
In Goose, things grow in-place only, since they have a large amount of address space reserved.
"Threads that share nothing. A worker is compiled as a separate program with its own memory, and flat values cross typed queues as a memcpy. Data races, locks, atomics and memory orderings do not exist in the language."
I hate when I see a new programming language, get my hopes up and it turns out to be AI slop again.
There might be some decent design ideas there but if you can't be arsed to write them down in your own words but instead make me read AI generated slop I am out.
Mandatory initialization, strong typing, context free grammar, lots of good basics. If you get the C++ header converter to work so you can use most C++ libraries I could see this as a great C++ replacement.
For Windows, these N data stacks would probably just RESERVE the address space, and as it grows COMMIT it, right?
I guess there would be some penalty to be paid here for smaller pages, but being mostly contigous might also help some.
That to be said, such language seems to require 64-bit virtual address space in order to function reasonably, right?
Also a .dll written in it might not be the best suited, for example if loaded in the middle of fragmented virtual address space it may need to find itself hard to allocate N contigious data stacks (do they absolutely have to be contiguous, what if they are simply ropes or deques or connected chunks ... obviously if some data structure requires to be contigous that would be a problem, but maybe this can be expressed somehow.... or maybe I'm overthinking here).
Yup that's how it works. Goose runs great on Windows.
Yes, it be very tight to make work on 32-bit.
DLLs definitely possible, most Goose programs only use a fraction of the 64-bit address space.
How would this work in wasm land? It's a bit badly put question, because this leaves out a lot of context - wasm - where, how, what implementation, but from my simple understanding most of the wasm is 32-bit running in a browser. For this to work, it'll need true virtual 64-bit (or 48-bit) address space. The host, being the browser, or something else, may provide it, but....
If the host needs to load several of these .wasm, compiled with goose, then it'll have to run them in separate (browser) instances too (or maybe that's how wasm works by default - not sure).
It just got me thinking - the languge is prepared to translate into javascript workers, because it's really single threaded by nature with communication between threads (or put in the dart languages term "isolates"), which makes them perfect for the browser, now the only question is the memory layout.
Sadly these memories are accessed thru a constant in the load/store instructions, and Goose would need this to be dynamic (since you can have code that processes pointers coming from multiple different stacks).
To run well, it doesn't just need wasm64 (which I worked on btw!) but it also needs the wasm64 memory to not commit until touched, or have a feature that allows Goose to do that. That and larger total memory. I pushed for that a while ago but I don't think it is possible today.
God the AI slop writing is horrible. Please just write the docs yourself, as others have stated, I can’t trust this at all. The “the one idea” made me cringe so hard I almost fell out of my seat. Every time I make something that’s exactly what Claude writes for the starting page.
Great work on Goose, a while load of practical thought went into it.
I’d love to see 1st class lightweight ‘processes’ and typed comms like CSP. These light processes would be cheap to spawn in thousands, with synchronous comms. So it’s possible to quickly use arbitrary networks rather than OS thread worker pools with queues. Maybe like:
fn producer(out: chan<i32>) {
for i in 10 {
send(out, i);
}
}
fn consumer(inp: chan<i32>) {
for i in 10 {
print(recv(inp));
}
}
242 comments
[ 8.6 ms ] story [ 206 ms ] threadThe relative references and built in binary structure validation also enable direct memory mapping of data structures and immediate use of network data. "Parsing" file and network data is often 100x slower than it needs to be." - John Carmack
So why bother posting this twitter link, rather than continuing the discussion directly on it
I could follow the link and read the thread and I don't have an X account.
You can also check out the language's website by googling "goose programming language", which should lead you to: https://aardappel.github.io/goose/index.html
What X shows me: https://celsoazevedo.com/files/2026/x.webp
With a login/nitter: https://celsoazevedo.com/files/2026/nitter.webp
(And why isn't it Amiga E?)
As for Amiga E, I am very proud of having made it way back when obviously, but it doesn't stack up against my more modern languages (Goose and Lobster), so I think I'll leave it be :)
How are you deciding how many stacks to use?
Do you know if Goose is the first time something like this has been done?
I'm wondering what kind of architectural corners this forces the programmer into ... have you found any so far?
> Nested data stays inline. A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it. A record that is 160 bytes and an allocation in C++ is 29 bytes and none in Goose.
I’m having trouble parsing that last sentence.
So, I read it as, "C++ uses 160 bytes and an allocation, when Goose requires 29 bytes and no allocation".
Even Rust's "enum" feature, which can store different sized things all in the same space, does that at the cost of the smallest variant being just as big as the biggest.
Goose can do all of that not only inline (no pointers), but with variable size, meaning small items take less space. It's like a serialized data representation, but iterable. It makes for big space savings vs these languages.
Doesn't that waste a lot of space? Or is there something I'm missing?
Also it would seem to force every allocation to go through the OS kernel to allocate unless there's some trick to avoid that.
How you deal with the inner stack growing depends, ideally they don't grow (construction only), or you can make them fixed size, or with a capacity, or in the worst case, as a pool. The language has facilities for all of these.
For example, suppose we have a function with a growable array that calls another function (without passing said array) that also uses a growable array as some temporary scratch space. Then the first function's array isn't being used when the second is sleeping, so the inner function's array could safely share the stack because it will all be freed with a single pointer restore once the second function exits.
Now, I actually don't know how the compiler works but as I understand it does things similar to my example to optimize the number of stacks needed.
Plenty of trees only ever grow. And that's the normal type of array in Goose. However you can also have arrays that can grow and shrink, if you have a tree that is constantly in flux.
Either way it'll be one stack for an entire tree.
You can just store all them items of the list/tree/whatever on the stack, growing it as needed, or you can add an addition "freelist" for a particular stack, so you can re-use items.
No, you can typically only assume 48 bits of virtual address space; the kernel takes half of it, so really only 47 bits. Newer CPUs provide 57 bits (e.g., Zen 4) or 52 bits (certain ARM64 models). And that's provided that the kernel plays ball; apparently some Android configurations only support 39 bits of user virtual address space.
I have both what I call inline sequences, and out-of-line ones (store an offset to the object itself rather than pointers).
I made all my sizes and offset 32-bit, but I suppose they could have been 16-bit.
With Goose, the core design favors speed over everything else. Though not only was I able to make that safe, it is fairly pleasant to use. But it remains a low level systems language that requires you to think hard about data organization.
Lobster is a waaay more high level language made to be pleasant to use first, fast second. Surprisingly though, it can get pretty close in speed to C++/Rust nowadays too, but still a lot slower than Goose.
how to perform this copy without atomics?
do the workers run as threads or processes?
also you claim it's faster than rust and c++. but for certain kinds of software it's certainly (and substantially) slower, right?
The workers are threads. The separate memory is the concurrency model, but it's still single process, multiple threads.
The "faster than" is on average, and both in my own benchmarks and independent benchmarks you can find examples of algorithms where it is slower, but they tend to be the exception. "substantially" slower I haven't found yet.
https://kostya.github.io/LangArena/#/top_tab
Well message passing with literal memcpys (rather than, say, just a shared buffer, like is common in Rust) is very expensive when the messages are huge. Of course as the message size increases, the Rust program will become faster than the Goose one (and if it doesn't, you should look into your benchmarks)
Being more specific, it means that for each message, we are writing on memory twice - one to build our own buffer with the message, and another to make a copy to another worker. Writing twice has an overhead, specially when messages don't fit in the cache - you just need benchmarks with sufficiently large messages to demonstrate it.
Beyond that, there are some algorithms that can be made much faster when written with atomics rather than message passing. (Also there are algorithms that will get faster if you use locks). It's just a matter of finding such examples, and writing a Rust code that will use atomics, compared to a Goose program that uses messages between workers because Goose doesn't expose atomics to the user.
So if you didn't find such examples, it's because you didn't specifically write benchmarks with those scenarios in mind (or, I mean, didn't told your LLM to write this).
That is: if the Rust program and the Goose program do the same thing in the same way, then it's reasonable that Goose is faster on average. But Goose is limited because it doesn't let you do some things, but Rust does, so to compare the languages you need to find those cases where the Goose limitations end up making the software slower
Note that all this supposed copying overhead also has an upside: once the synchronisation has happened, every thread can now run at maximum speed doing single threaded memory allocation with no locking of any kind.
In C++, malloc/new in multithreaded programs needs to essentially go thru a mutex and can make allocation even more expensive than it already is. I am not sure if Rust does the same.
Since in Goose "allocation" is just a pointer bump, we cannot make that multi-threaded, hence the threading model followed from that.
And like a lot in Goose, you have to write your program to fit the language a bit. If you expect to do concurrency on top of a huge graph of constantly changing data that all threads must have immediate access to, it is probably not the language for you. But there are plenty of concurrency models that fit and are blazingly fast.
That's without even mentioning that AI writing can often state the what but not the why. That human perspective is usually the most valuable knowledge to get across in writing.
Of course Humans can make errors when translating that to English. But if you’ve read any amount of Claudish it should be obvious that interpolating the code to documentation with an LLM typically produces a significantly worse result in almost every way. Except for superficially “sounding” correct.
If you believe you are making something worth other people's time, you should ALSO believe you are making something worthy of your own time.
would you fly in an airplane if the software was written mostly by Claude?
If an engineer who mostly used Claude left the company, can his replacement understand his mental model, given that he himself doesn't ?
Plus, if a human puts the effort into writing something, that signals to me that it's worth something, because human time is much more scarce than LLM time.
Within the first couple of paragraphs and bullets it made a completely false claim that is the opposite of how the language operates, something any person that knows the essentials of it would know. Language Y was listed in the front page as an inspiration (and I don't doubt them) but clearly they either did not read the docs the LLM wrote or did not use the language for long enough to know it has zero structural typing
For a programming language? It's subpar and you know it.
See this for a language docs site by a small-ish team, but a significant effort was put into making it nice to read: https://tour.gleam.run/everything/
That's, like, a stunningly low bar for documentation. "The vehicle is perfectly capable of performing motion, why are you complaining?"
Apparently, this can actually assist the LLM:
https://silly.business/blog/we-should-revisit-literate-progr...
as discussed here previously:
https://news.ycombinator.com/item?id=47300747
I'd love to experiment with this myself.
https://www.goodreads.com/review/list/21394355-william-adams...
Note that ICC, a C compiler, is one:
https://www.goodreads.com/book/show/522102.Retargetable_C_Co...
Note that one can look through projects tagged as Literate Programming by using the topics view:
https://github.com/topics/literate-programming
might be there's something useful there.
There is! As of now, if you sort by recently updated, my literate programming project is the first result :P (link in profile if anyone reads this later)
That said, I do genuinely enjoy brainstorming with it, and these quirks are not really a hindrance. If anything, the sentiment in the first paragraph is quite useful to quickly get an insight about where I stand with my thoughts, relative to the available knowledge that Gemini has access to.
Only on the Internet is this true, not in real life. I cannot and do not trust any of these things to do a proper job because they have not in any situation succeeded in any job I've given them. And no company I deal with claims otherwise
Still glad I basically never have to debug a build issue or memory error again though
Lack of documentation used to be a running joke.
The goose_spec.txt in 2019 would be "goose is like c and rust only with syntax like array{;}[] btw it uses a small amount of stacks instead of malloc."0 10klocs.
Now, we make sure the AI leaves documentation so it can figure out what it was doing earlier.
A local model a few generations and many weights behind newest Claude can implement my novel algorithms and write the documentation I wouldn't.
Yes, many times it does dumb CS for kindergarten mistakes but it only has to work towards the optimum every once in a while.
- You need to have a mental model to grow an idea
- When a pattern is known you can use a library!
- When a pattern is not known AI will make stuff up
No matter how "good" coding with an AI will become there is no way you get around learning, having someone understand what's going on and take responsibility.
I'm fine with formal checking and fuzzing or getting hints where a bug might come from - but these are iterations on tools we used before like a debugger, strict types, functional programming and well fuzzing.
I tried to have an AI iterate on a step i don't fully understand yet and i always regretted it. Highly interconnected projects will grind to a halt until you do learn.
You can check with people doing highly specced software in the medical domain that even with very good specs there is ambiguity in natural language thus it can never be the source of reliable and manageable software.
However - i read about some smart guys in the 40s or so encountering the need for a formal language to tell a computer what to do with 0 ambiguity and i think they called it a "programming language"
I had to accept this one too even for pretty simple things. I had an LLM wire up a neovim connection handler for me without bothering to read the libraries docs or neovims RPC spec and I completely regretted it. You would thing such a small piece would be fine but I couldn't work on it and had to rip it out and rewrite it, and reading the AIs reference code actually got me more confused than anything.
I've found the sweet spot for me is just writing code and promoting an AI whenever I have a question or if I'm not sure the code will do what I think. When I hit a point and I groan about doing something, if it's small and I understand what needs to happen already I will ask the LLM I've been prompting already to do it. Usually by that point it's already gotten enough context from the back and forth on my questions or me explaining assumptions it got wrong when reviewing my code.
It might make sense to learn now, before everyone expects that you be an expert with this tool in order to do your job. On the other hand perhaps they will be easier to learn if you wait.
There is an incredible amount of nuance to be had in using LLMs and we reached the stage, probably only in the last few weeks where all the pieces have fallen into place such that if you are skilled at using the LLMs just about all of the previous problems with them can now be easily mitigated. If you learn how. There is a lot to learn.
https://github.com/bendlang/bend
"we reached the stage, probably only in the last few weeks where ..." This has also been said every other month since 2023.
It really is like working with an over-eager employee. They just also happen to be a pathological liar.
Personally I disagree with this. I've been using LLMs the last few years and learning a lot about techniques for getting value out of them. Even though they weren't very good for a while they seemed worth learning to me because the rate of improvement was so fast. We've now reached a point where if you know how to use them right you can get lots of value out of them.
I really don't mean to be rude here but consider perhaps the reason why you're having trouble seeing why they're valuable is because you haven't used them enough in the last few years or kept up with the developments closely enough. Maybe I'm wrong. But consider it's possible you are too.
> This has also been said every other month since 2023.
I'm sure others have said that but my perspective has been that the models are not quite good enough yet, for a while but that the trajectory is so crazy that it made sense to make the bet and invest lots of time into learning how to use them on the assumption that they would soon be good.
Even now I would say they have a long way to go. What is hard but possible today will be easy tomorrow. But quite a lot is now possible with the right techniques. Crazy things.
Considering that I don't know rust at all, it's awesome.
With the tutorial, the summary also makes more sense. I have not read the other parts yet, but so far I like what I see.
All is in pretty good taste, and I like what I've seen so far. I do not care if the author himself came up with the idea, or if AI came up with it and the author approved.
I do not understand why you "have to" know this to make use of it. You can judge ideas independently of where they came from (and you should).
You can but in practice nobody does this because they don't have time. For example, once you have investigated ideas from a crank a couple of times - you don't do it again. Life is too short.
Couldn’t make it more than a few sentences in before the bile started to build up in the back of my throat and I had to back out. It’s shocking to me that people knowingly post unedited Claude-slop drivel and are seemingly unashamed about it. In 2026, it seems the main role of technical humans should be to act as a barrier between our agents’ output and other humans.
Whether it would make sense in this AI world was not a consideration.
The syntax and semantics were mostly designed for humans. That said, using it optimally asks a lot of the human, and in turns out the better LLMs don't break a sweat using it, so maybe it accidentally hits the spot. Goose with LLM can give you lots of speed without the effort.
In some weird way it is a great time to make new languages, because the downside of convincing humans to learn it is gone. Anyone that has a project that needs to be fast can decide to use Goose for it at very little cost.
> I made this one because I had a really strong design in mind that I think should exist.
Hows the compile time? Do you have a number or is it similar to another language?
Optimized builds go thru the local C compiler, so they are limited by the speed of that. Dev/test build can use the built-in libtcc JIT which is super fast.
That is about where our similarities end, though, since I'm doing quite a lot of other stuff in the midst as well (much heavier type stuff, fully incremental, retargetable, reflection, integer range tracking, blah blah blah), and the more goals you have, the complexity blows up exponentially. I do think that the region based memory part alone is worthwhile to have as a language feature, so I applaud your pragmatism. I like your syntax for returning through call stacks, too.
There are other languages that do this, though. Did you look into any of the others? Or ones like Odin which give you the configurable bump allocators and scratch space as well? Mainly I'm curious about your opinions of prior art.
anyway, hope this project goes well! the secret of the arena allocator seems to be out now to the mainstream. I think this is also a strength of array programming languages in the tradition of APL/J/K/Q.
As this project develops, I'll get to benefit from your public crowd sourced testing and design before having to publicize mine :P
And FWIW, I actually think that "faster than C++ and than safe Rust" is clearer than the more idiomatic "faster than C++ or safe Rust", and certainly clearer than "faster than C++ and safe Rust", which looks like a conjunction of "C++" and "safe Rust". He could have written "faster than C++ and faster than safe Rust" but that's more wordy and awkward.
Enough of this pointless and irrelevant pedantics ... I won't respond further.
P.S. Just to be complete, here's an AI slop response:
You are completely right, and that is exactly why the author likely structured it that way.
In technical writing, "Faster than A and B" can be highly ambiguous. A reader could easily interpret it in two unintended ways:
• The Sum Interpretation: Faster than the speed of C++ and safe Rust combined (which makes no sense logically, but fits the literal grammar).
• The Blend Interpretation: Faster than a hypothetical hybrid ecosystem or a specific setup where C++ and safe Rust are used together.
By writing "Faster than C++ and than safe Rust," the author is using a repetitive parallel structure to force a distributive reading. It explicitly separates the two entities, making it clear that the language is:
1. Faster than C++
2. Faster than safe Rust
So while it sounds unnatural to a casual reader, it was a deliberate choice to ensure mathematical and logical precision over poetic style.
If a sentence has multiple "valid" interpretations, then it doesn't matter what the "correct" interpretation is. If someone says that a sentence is confusing or hard to read, you 100% must believe them and fix it. Dismissing concerns about clarity and ambiguity as merely "pedantic" is one reason why people fail to develop written communication skills. I have been burned many, many times in my career by making charitable assumptions about another engineer's ambiguous language, only to realize much later, after significant cost has been paid, that they had a completely different (and often wrong) idea.
Teaching people to be better writers is a hill I will gladly die on. I don't care if you defend your point or not, just read my comment and try to understand why someone would care deeply about this sort of thing.
*And really in most if not all, Raku excluded**, languages.
**In Raku junctions can be specified with infix ops, i.e. a | b, a & b, a ^ b, equivalent to list ops any(...), all(...), one(...) respectively, and can define a custom one for none(...).
https://strlen.com/
Looking at the repo it seems like the N stacks generated by the compiler are placed at least 2gb apart in virtual memory, have you run into any cases where that has been overflowed during runtime? The compiler cannot know which of the stacks are going to be used more than others and in a large complex program with many stacks any one of them could fail. I imagine this being an issue depends on target application - if you know you are building a game that you know the exact size of your levels / entity counts beforehand you know this is fine but if you were doing data processing / parsing potentially malicious user input it may be a problem.
I'm also interested how the memory locality works. Here you have the bases of your stacks at a series of very sparse virtual memory intervals which will be mapped by the page table to some physical memory addresses, does having them be so sparse cause any issues?
There are some unique ideas here - lifetimes on references to growable+shrinkable stacks, "balancing" stacks in recursive functions - and I'm glad you were able to use coding agents to actually materialize them.
I am not sure what issues could be caused by the sparsity. Like you say, all that matters is that in physical memory, we are only using what is actually in use.
Thanks! :)
I like the XY language, what do you think? https://nsl.com/k/xy/xy.htm
I guess people also differ by how much they are bothered by it :)
My other language, Lobster, has no semicolons at all :)
For details on how, see https://github.com/aardappel/goose
Also, to be transparent in your benchmarks you should compare against idiomatic safe code, and optimized code. It's trivial to throw your benchmark examples into an LLM and tell it to optimize them to parity with Goose. It's more trustworthy to show other languages can achieve the same performance, Goose isn't doing anything special there. What it is doing is doing the same with better safety guarantees, which I think is headline result not the speed itself.
As for the benchmarks, that's exactly what I do: https://aardappel.github.io/goose/bench/results.html
If you mean the other benchmarks (LangArena), I don't control their design.
> As for the benchmarks, that's exactly what I do
What I mean is the story of those benchmarks is incomplete, you're missing a column for optimized Rust. This is what I get on my M1 if I ask the LLM to write more performant (still safe) solutions to a couple benchmarks, I'm sure your LLM can do the same:
I think for the Benchmarks Game entry specifically, for the expert solutions you should use submissions to the game for both C++ and Rust instead of LLM generated code. After all, those are legitimate expert-implemented solutions to the benchmark, so it's nice to not have to lean on an LLM there. That would also give you something to optimize towards.From what little I read in the literature I seem to recall that there were enough programs with quite a bit more memory usage that they decided this approach was a dead end.
Does anyone know anymore details?
Still, for a large number of programs - like data-oriented applications - it’s probably a good fit. It might work ok with entity-component game systems as long as you reuse old memory…
If it is potentially completely unbounded, you need different solutions like a pool, or essentially reconstructing etc.
Seems any compiled language with automatic memory can make use of the techniques to obtain speed ups.
In Goose, things grow in-place only, since they have a large amount of address space reserved.
That reminds me of Dart Isolates - https://dart.dev/language/isolates
There might be some decent design ideas there but if you can't be arsed to write them down in your own words but instead make me read AI generated slop I am out.
Mandatory initialization, strong typing, context free grammar, lots of good basics. If you get the C++ header converter to work so you can use most C++ libraries I could see this as a great C++ replacement.
I guess there would be some penalty to be paid here for smaller pages, but being mostly contigous might also help some.
That to be said, such language seems to require 64-bit virtual address space in order to function reasonably, right?
Also a .dll written in it might not be the best suited, for example if loaded in the middle of fragmented virtual address space it may need to find itself hard to allocate N contigious data stacks (do they absolutely have to be contiguous, what if they are simply ropes or deques or connected chunks ... obviously if some data structure requires to be contigous that would be a problem, but maybe this can be expressed somehow.... or maybe I'm overthinking here).
Super excited about this!
If the host needs to load several of these .wasm, compiled with goose, then it'll have to run them in separate (browser) instances too (or maybe that's how wasm works by default - not sure).
It just got me thinking - the languge is prepared to translate into javascript workers, because it's really single threaded by nature with communication between threads (or put in the dart languages term "isolates"), which makes them perfect for the browser, now the only question is the memory layout.
I’d love to see 1st class lightweight ‘processes’ and typed comms like CSP. These light processes would be cheap to spawn in thousands, with synchronous comms. So it’s possible to quickly use arbitrary networks rather than OS thread worker pools with queues. Maybe like:
fn producer(out: chan<i32>) { for i in 10 { send(out, i); } }
fn consumer(inp: chan<i32>) { for i in 10 { print(recv(inp)); } }
fn main() { let c = chan<i32>();
I doubt this can work well in all cases. Sooner or later one needs proper heap.
And doc is the slop.