feat(lang): integer numeric-limit accessors (s64.max, u8.min, s3.max) [NL.1]
A field-like access on a builtin INTEGER type name folds to a compile-time
constant of the queried type, driven by (width, signedness) arithmetic:
sN: min=-(2^(N-1)), max=2^(N-1)-1; uN: min=0, max=2^N-1
for every width s1..s64 / u1..u64 (not just power-of-two), plus usize/isize.
- type_resolver.zig: extract the single width parser (parseWidthInt) reused by
resolveNamed AND the new accessors (no second parser — issue-0083 class);
add resolveBuiltinName / integerWidthSign / integerLimitBits / integerLimitFor.
- lower.zig: lowerNumericLimit intercept beside the error.X / Struct.CONST /
pack-arity identifier-receiver intercepts; folds ints via constInt, emits a
clean diagnostic for a non-numeric receiver (bool/string/void/Any/noreturn),
falls through for floats (NL.2).
- expr_typer.zig: mirror the result type so inferExprType reports the queried type.
- program_index.zig: recognize the accessors in the comptime-int / array-dim path
so [u8.max]T (255) / [s16.max]T (32767) work; [u64.max]T is rejected oversized.
- u64.max / usize.max stored as the all-ones bit pattern with TYPE u64 (i64 -1),
asserted via union { u: u64; s: s64 } reinterpret.
Docs: specs.md numeric-limits subsection (formulas + result-type + u64 note);
readme.md language overview. Examples 0148 (positive) / 0149 (negative-receiver).
Unit tests for the value computation in type_resolver.test.zig.
Gate: zig build, zig build test (359/359), tests/run_examples.sh (416 ok, 0 failed).
This commit is contained in:
37
specs.md
37
specs.md
@@ -117,6 +117,43 @@ GLSL;
|
||||
- `Any` — type-erased value, represented as `{ i64, i64 }` (type tag + payload). Used for variadic arguments and runtime type dispatch.
|
||||
- `Type` — compile-time type value. At runtime, represented as an `i64` type tag (same tag space as `Any`).
|
||||
|
||||
### Numeric Limits
|
||||
|
||||
A field-like access on a builtin **integer** type name folds, at compile time, to
|
||||
that type's smallest/largest representable value:
|
||||
|
||||
```sx
|
||||
maxS64 := s64.max; // 9223372036854775807
|
||||
minS32 := s32.min; // -2147483648
|
||||
maxU8 := u8.max; // 255
|
||||
minU8 := u8.min; // 0
|
||||
m3 := s3.max; // 3 (arbitrary width)
|
||||
n := u64.max; // 18446744073709551615 (all-ones)
|
||||
```
|
||||
|
||||
- **Receiver.** Any builtin integer type: every signed width `s1`..`s64`, every
|
||||
unsigned width `u1`..`u64` (arbitrary 1–64 bit widths, not only the
|
||||
power-of-two ones), plus `usize`/`isize` (target-width — `u64`/`s64` on a
|
||||
64-bit host).
|
||||
- **Value.** Pure `(width, signedness)` arithmetic — never a per-name table:
|
||||
- `sN`: `min = -(2^(N-1))`, `max = 2^(N-1) - 1`
|
||||
- `uN`: `min = 0`, `max = 2^N - 1`
|
||||
- **Result type.** The constant has the **queried** type: `s3.max` is an `s3`,
|
||||
`u64.max` is a `u64`. So it is usable anywhere a constant of that type is
|
||||
legal — initializers, `::` / `:=` bindings, and larger expressions — and in
|
||||
array-dimension / count position via the compile-time integer path
|
||||
(`[u8.max]T` is a 255-element array; `[s16.max]T` a 32767-element one). A
|
||||
count that does not fit (`[u64.max]T`) is rejected as an oversized dimension.
|
||||
- **Representation note.** `u64.max` / `usize.max` is the all-ones 64-bit value
|
||||
(`18446744073709551615`), which exceeds the signed `i64` range used for
|
||||
integer constants; it is stored as that exact bit pattern carrying the `u64`
|
||||
type (it reinterprets to `-1` as an `s64`). It cannot be written as a decimal
|
||||
literal, and the default integer formatter (which is `s64`-based) prints it as
|
||||
`-1`; assert it exactly through a bit reinterpret (`union { u: u64; s: s64 }`).
|
||||
- **Non-numeric receivers.** `.min` / `.max` on a non-numeric type (`bool`,
|
||||
`string`, a pointer, a `struct`, `void`, an `enum`) is a compile error, never
|
||||
a silent value.
|
||||
|
||||
### Enum Types
|
||||
User-defined sum types with named variants. Variants may optionally carry typed data (tagged unions). Internally, payload-less enums are represented as `i64` (variant index). Enums with payloads are represented as `{ i64, [max_payload_size x i8] }` (tag + data).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user