Attempt 1 rejected only LITERAL initializers that mismatch a typed module
const's annotation; a const-EXPRESSION initializer escaped, so the same
issue-0088 root remained for `M :: 2; N : string : M + 2` — accepted at exit 0,
folding `[N]s64` to 4 and printing N as an integer.
Root cause: `registerTypedModuleConst` validated only the enumerated literal
node kinds; any other kind fell through to `else => {}`, and pass 0
pre-registers binary_op/unary_op consts as a `.s64` placeholder that was never
reconciled with the annotation.
Fix — validate by TYPE, not by node kind:
- lower.zig: `registerTypedModuleConst` now covers literals AND const-expressions
(binary_op/unary_op) through one path. `typedConstInitFits` keeps the literal
arms and routes any non-literal through the new `constExprInitFits`, which
compares the initializer's INFERRED type (`inferExprType`, the existing
type-inference facility — no second const evaluator) to the annotation with the
same integer/float compatibility. A mismatch emits the `type mismatch` diagnostic
(a const-expression is described by its inferred type, e.g. "an integer
expression") and evicts the pass-0 placeholder; a match registers the const at
its resolved annotation type (the same `put` the literal path always did), so a
const-expression folds and emits at its declared type.
- `literalKindName` → `initializerDescription` (+ `constExprDescription`) so the
message is accurate for both a literal and a const-expression initializer.
Regression:
- examples/1143: extended with `E : string : M + 2` and `V : string : -M`
(const-expr mismatches → exit 1, pinned diagnostics).
- examples/0162: extended with `KE : s64 : M + 2` (used as a count + printed) and
`WE : f32 : M + 2` (over-rejection guard — valid const-exprs still work).
- program_index.test.zig: count-gate test extended with a binary_op value node
declared `string` (must not fold as a count).
Docs: specs.md §3 + readme.md generalized from "initializer literal" to cover
constant expressions; issues/0088 RESOLVED banner updated.
48 lines
1.7 KiB
Plaintext
48 lines
1.7 KiB
Plaintext
// Valid typed module-level constants compile, fold, and print correctly across
|
|
// every initializer/annotation pairing the registrar accepts:
|
|
// - integer literal → integer (`K : s64 : 4`) — usable as an array count too
|
|
// - integer literal → float (`W : f32 : 800`)
|
|
// - float literal → float (`PI : f32 : 3.14159`)
|
|
// - string literal → string (`S : string : "hi"`)
|
|
// - null → pointer (`P : *void : null`)
|
|
// - integer EXPRESSION → integer (`KE : s64 : M + 2`) — usable as a count too
|
|
// - integer EXPRESSION → float (`WE : f32 : M + 2`)
|
|
//
|
|
// Companion to the negative example 1143: the issue-0088 fix rejects a typed
|
|
// const whose initializer mismatches its annotation, and these correctly-typed
|
|
// consts must keep working (no over-rejection) — including const-EXPRESSION
|
|
// initializers, whose type-based validation (attempt 2) must accept a correctly
|
|
// typed expression even though it isn't a literal.
|
|
#import "modules/std.sx";
|
|
|
|
M :: 2;
|
|
|
|
K : s64 : 4;
|
|
W : f32 : 800;
|
|
PI : f32 : 3.14159;
|
|
S : string : "hi";
|
|
P : *void : null;
|
|
KE : s64 : M + 2;
|
|
WE : f32 : M + 2;
|
|
|
|
main :: () {
|
|
// Integer const: prints AND drives an array dimension (len 4).
|
|
a : [K]s64 = ---;
|
|
a[0] = 10;
|
|
a[3] = 40;
|
|
print("K={} len={} a0={} a3={}\n", K, a.len, a[0], a[3]);
|
|
|
|
// Integer-into-float and float consts print as floats.
|
|
print("W={} PI={}\n", W, PI);
|
|
|
|
// String const prints its text.
|
|
print("S={}\n", S);
|
|
|
|
// Null pointer const is null.
|
|
print("P_is_null={}\n", P == null);
|
|
|
|
// Integer const-EXPRESSION: prints AND drives an array dimension (len 4).
|
|
b : [KE]s64 = ---;
|
|
print("KE={} len={} WE={}\n", KE, b.len, WE);
|
|
}
|