fix(ir): evalConstFloatExpr reaches parity with evalConstIntExpr — numeric-limit float leaves + float % fold under the unified rule [F0.11]
The compile-time float evaluator lagged the integer one: it had no numeric-limit field-access arm, so `y : s64 = f64.true_min + 0.5` (=0.5) silently truncated to 0 even though the direct `f64.true_min` already errored; the arm-by-arm audit also found a missing `%` arm, so `y : s64 = 5.5 % 2.0` (=1.5) silently truncated to 1. Bring evalConstFloatExpr to PARITY with evalConstIntExpr: - Add a `.field_access` arm resolving a builtin FLOAT numeric-limit accessor (`f64.max`, `f32.epsilon`, `f64.true_min`, …) via the SAME `type_resolver.floatLimitFor` that `lowerNumericLimit` uses — the float twin of the int evaluator's `integerLimitFor` arm. - Add a `.mod` arm via `@rem` (matching evalConstIntExpr and codegen's `frem`): `6.0 % 4.0` folds to 2 (via int delegation), `5.5 % 2.0` = 1.5 is rejected. The two evaluators now share every leaf/operator shape, so no compile-time-const float form escapes the unified float→int rule at one site while folding at another. All five sites (local/field/param/const/ array-dim) stay consistent. Regression: 0168 (positive) adds `f64.max - f64.max` → 0, `6.0 % 4.0` → 2, integer-limit `s8.max`/`[u8.max]` unregressed, `xx` escapes for both new forms; 1146 (negative) adds `f64.true_min + 0.5` and `5.5 % 2.0` erroring at a binding site; program_index.test.zig covers the floatLimitFor arm and the `%` arm. specs.md + readme.md state the parity. issues/0095 RESOLVED banner gains the attempt-5 entry.
This commit is contained in:
@@ -128,7 +128,12 @@ integer-typed binding *without* a cast follows the same integral-fold rule an
|
||||
array dimension uses: an **integral** compile-time float folds to its integer, a
|
||||
**non-integral** one is a compile error. It holds whether the value is a literal
|
||||
or *any* compile-time-constant float expression — including one that references a
|
||||
float-typed const (`F : f64 : 2.5; y : s64 = F + 1.5` → `4`) — and is uniform
|
||||
float-typed const (`F : f64 : 2.5; y : s64 = F + 1.5` → `4`), a builtin float
|
||||
numeric-limit accessor (`f64.max - f64.max` → `0`, while `f64.true_min + 0.5`
|
||||
errors), or a float `%` (`6.0 % 4.0` → `2`, while `5.5 % 2.0` = `1.5` errors): the
|
||||
compile-time float evaluator recognises every leaf shape the integer one does, so
|
||||
no constant float form escapes the rule at one site while folding at another — and
|
||||
is uniform
|
||||
across a typed local, a parameter default, a struct field default, a call
|
||||
argument, a typed constant, **and an array dimension / count** — `y : s64 = 4.0`,
|
||||
`K : s64 : 4.0`, `y : s64 = M + 2.0`, and `[F + 1.5]s64` (≡ `[4]s64`, whether
|
||||
|
||||
Reference in New Issue
Block a user