fix(ir): const evaluators' field-access arm is raw value-shadow aware [F0.11]
A backtick raw value-shadow receiver (`` `f64 := … `` then `` `f64.epsilon ``, `` `s8.max ``) was misclassified as the builtin numeric-limit accessor by the shared compile-time evaluators. The sibling `isFloatValuedExpr` already guards this with an `is_raw` check, but `evalConstFloatExpr` / `evalConstIntExpr` did not — so once a raw value-shadow's field read flowed into the unified float→int narrowing rule or an array-dim count, the float folder returned the BUILTIN `f64.epsilon` (2.22e-16) and wrongly errored, and the integer folder turned `` `s8.max `` into the builtin `127` (a fabricated 127-element array). Both evaluators' field-access arms now mirror `isFloatValuedExpr`'s `is_raw` guard: a raw receiver yields `obj_name = null`, so it is never a numeric-limit/pack leaf and falls through to the ordinary runtime field read. A raw value-shadow is a mutable-local field (an observable later reassignment), so it is genuinely runtime and must not be const-folded — it now behaves exactly like a plainly-named field read: `` `f64.epsilon `` narrowing into `s64` truncates its field value (11.5 → 11, identical to `b.epsilon`), and `` `s8.max `` as an array dimension is rejected as a non-constant count (identical to `b.max`). The bare builtin path is unchanged. Regression (issue 0095 / F0.11-7): - examples/0169-types-value-shadow-field-narrowing.sx (positive — raw float-field read narrows/truncates, mutation proves runtime, bare limit still folds) - examples/1148-diagnostics-value-shadow-field-dim-not-const.sx (negative — raw int-field dim rejected as non-const) - program_index.test.zig "a backtick raw-shadow receiver is a field read, not a numeric-limit fold (F0.11-7)" specs.md + readme.md note the value-shadow rule extends into the narrowing/count contexts.
This commit is contained in:
7
specs.md
7
specs.md
@@ -353,7 +353,12 @@ qn := f64.nan; // a quiet NaN
|
||||
global, or a `` `f64 :: … `` module constant — so the fold can never silently
|
||||
hijack a raw value, whatever its scope. The two never collide: a bare builtin
|
||||
name in expression position is always a type, and only the raw `` `…` `` spelling
|
||||
can bind a value under it.
|
||||
can bind a value under it. The same rule governs the compile-time **narrowing
|
||||
and count** contexts: a raw value-shadow field read is an ordinary *runtime*
|
||||
read there too — never a compile-time numeric-limit leaf — so `` `f64.epsilon ``
|
||||
narrowing into an integer binding truncates like any runtime float (its field
|
||||
value, not the limit), and `` `s8.max `` used as an array dimension is rejected
|
||||
as a non-constant count rather than folding to the builtin `127`.
|
||||
|
||||
### 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