Have we had thoughts about where we want to put the builtin symbols?
This may be something @Sam Mohr has already planned.
I'm thinking of taking a small side quest to build that out a bit.
I've been thinking... we could use hardcoded integers that work backwards. So when you lookup
an Module.Idx
during Can and you're looking for say Str.toUtf8
you might get the hardcoded id. e.g. Module.Idx(Str) = maxU32 - 1 = 4_294_967_294u32
, or Module.Idx(Bool) = maxU32 - 2 = 4_294_967_293u32
.
Counting backwards instead of using the lowest values means we don't need to actually add these to the ArrayList, and we can always know if they're builtin Module/Ident by checking if the Idx is above a certain value.
Also we know what these values are at comptime, so they are constants and we can switch on them etc elsewhere.
We might want to do this over the current method because then any index Idx
is actually something stored in the array at that offset. Unlike today where I think things are offset by 1
.
The builtins are hardcoded and not in the array, indexing into it using a builtin would blow up out of bounds, so we would know immediately if something was wired incorrectly.
I just think we need to make sure they don't bottleneck compilation of the roc compiler and lead to crazy amounts of rebuilds. So they probably should be compiled lazily after the roc compiler has been fully built. (Talking about the roc builtins).
Cause that loop is one of the most painful in the old compiler. Change almost anything -> must recompile to roc builtins -> need to recompile a ton of other things downstream.
or maybe we could control that with a build flag too, like llvm?
actually nm, since we want to prioritize simplicity and correctness in the 0.1.0 compiler, +1 to just doing it at runtime for now
keep it simple
we can always optimize more in a future revision
I'm busy all day today, but in short, I'd like to see if we can have minimal hardcopies for now on builtins
We should only need operator desugaring (e.g. Num.add), Str.concat, and some types like List and Str and Result
And also derive functions, like to_str and encode
If we can make some system that can look for an ident in "a builtin somewhere" that looks those up
Then we can avoid hardcoding altogether
At least for now, during the correctness is paramount phase of development
I don't think the runtime cost matters. Can cache it once per roc version in the global cache
Agreed
yeah that's a good point
also in the future we can get fancy and like as soon as we see from the CLI args that we're going to be doing a check or build, we can go load all the builtins from cache into memory in the background while we proceed on the main thread to start working on the source file we got from the CLI
One question I have as I start bringing the Builtins over to the zig compiler and v0.1 syntax.
Are we doing any changes to Num
? I thought I remember Richard or someone else suggesting that we don't need the Num
type anymore because of static dispatch.
Bringing over Num
(or it's replacement(s)) blocks bringing over a number of other Builtin modules
we definitely still need the Num
type as far as I know :smile:
so you think that Num moves over mostly at is as far as the structure of the types?
should be exactly as-is! :grinning_face_with_smiling_eyes:
Last updated: Jul 06 2025 at 12:14 UTC