Hello,
this works because the number is not u128.
All number literals in Zig are comptime_int (comptime_float also exists, but has different behavior). This data type can hold almost any number.
The max limit of bit width for signed and unsigned integers in Zig is 65535 bits.
EDIT: I see you modified your question, what part of it do you want to know how works?
In Zig all integer literals are of type comptime_int, behind the scenes this is using the big int implementation from the standard library.
Zig also tries to evaluate things at compile time as much as possible, so if you create a const and initialize it with a compile-time known value, then the constant will also be compile time known.
If you explicitly want to use u128 then you have to tell it the type:
const big_number: u128 = ...;
And even that will remain compile-time known by the way if you initialize it with e.g. an integer literal.
Also interesting place to look at is here.
It may not be the current implementation, but generally describes how print works.
If you want a quick run down, most languages have formatted printing hard coded into compiler (even new ones like Rust), because if it were implemented in user space it would either be slower or would lack nice error messages.
Zig is able to describe it fully in user land with compile time reflections. (its a bit harder for new commer, but really cool)
If you want to get a usefull information about the language and try to learn basics in coordinated way, there is Ziglings which is popular to get the know-how about the language, has really nice descriptive comments. (it targets people who know how to program, but are new to Zig)
I don’t believe that’s true, Rust’s println! is implemented with macros; which can’t really be called a part of the compiler any more than Zig’s comptime is.
It used to be 100% that way, the macros after some indirection used to call exposed special compiler functions. I dont know whether its still the case, but i dont think they changed it.