Hugs> 94535^445
13763208823213770506960538876615156211048901640052821530697264247739998018468419032448277029434879827074549660094560167350418780006041435009085328
As already mentioned, if you have 32 bit words and use the full range you get -2^31 to 2^31-1 using two's complement.
By reserving a few bits of the word, those bits can be used to carry type-information for the value. That is, values "know" their own type at runtime. The remaining bits are used to carry the value's data.
Integer values that fit in these remaining bits can be stored directly in the word. Such integers are typically called 'fixnums'. If they don't fit, then the type bits of the word indicate it is a 'bigint', and the remaining bits are used to store a memory pointer into the heap where the bigint value is stored.
The compiler needs to translate your arithmetic expressions into multiple code paths that cover allowed type combinations for the operands. Example for addition:
A lot of optimizations in compilers for these languages focus on avoiding overhead for the runtime type-checks needed to make this work. There are often also ways to explicitly tell the compiler that automatic demotion from fixnum to bignum is undesired, and instead one want the overflow behavior of 32bit integers. This can be very important for implementing cryptography algorithms efficiently.