aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 22:28:06 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 22:28:06 +0330
commit5a4dc62a79af6135c7050e81a82dbfdfb0a7d4e0 (patch)
tree805283b2d30b2cf0f53af42e5a3fc119af5e839f /docs
parentdefinite assignment: reading a local before it is initialized is a compile er... (diff)
uninit: track aggregate fills per part, sticky computed-index fills, &a[k] and method calls set the aggregate; fix test/example hits; docs
Diffstat (limited to 'docs')
-rw-r--r--docs/LEARN.md2
-rw-r--r--docs/SPEC.md6
2 files changed, 5 insertions, 3 deletions
diff --git a/docs/LEARN.md b/docs/LEARN.md
index e4fcdc6..6f3e0fc 100644
--- a/docs/LEARN.md
+++ b/docs/LEARN.md
@@ -63,7 +63,7 @@ hello, world!
### variables and while
-`let` infers a variable's type from its initializer. an integer literal stays a plain word. `int i = 0;` writes the type explicitly. a local must be assigned on every path before it is read (locals are not zeroed); passing `&x` counts as initializing `x`, and an array or struct needs a full `{...}` initializer or `&agg`. the lifetime analyzer runs by default; the optional typechecker is enabled separately with `typecheck on;`.
+`let` infers a variable's type from its initializer. an integer literal stays a plain word. `int i = 0;` writes the type explicitly. a local must be assigned on every path before it is read (locals are not zeroed); passing `&x` counts as initializing `x`, and an array or struct is set once every field or constant-index element is written, by a `{...}` initializer, by `&agg`, or by a computed-index fill such as `a[i] = e` in a loop; reading a part that was written is fine. the lifetime analyzer runs by default; the optional typechecker is enabled separately with `typecheck on;`.
`while` tests before entering the body. `i++` increments the variable, and `break` leaves the loop.
diff --git a/docs/SPEC.md b/docs/SPEC.md
index b645742..7ba5ce0 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -553,12 +553,14 @@ let sq = { let t = 3 + 4; t * t }; // 49
4.1.4 `const k = e;` declares a local constant: no type is written, it takes the initializer's type (read-only, 2.10), needs an initializer (error: a const needs an initializer), and cannot be assigned (error: const storage cannot be modified). `const T k = e;` is a typed const.
-4.1.5 definite assignment. a local with no initializer is unset until every path that reaches a read has assigned it (or taken its address). reading an unset local is error: X: used before it is initialized. a local is set by an initializer, by `x = e`, by passing `&x` (the out-parameter pattern), or by a full array initializer list `{...}` (structs have no brace initializer; use `&agg` or pass the array). writing some fields or elements does not set the aggregate: the whole value stays unset until a full array initializer, `&agg`, or using the aggregate as an address (an array decaying to a pointer). at a join (if/else, loop exit, switch, `?:`) a local is set only if every reaching path set it. a `while` or `for` that may run zero times does not count an assignment only inside the body; a `do`/`while` always runs once, so an assignment in its body does. parameters and globals are set from the start (a global with no initializer is 0). locals are not zeroed.
+4.1.5 definite assignment. a local with no initializer is unset until every path that reaches a read has assigned it (or taken its address). reading an unset local is error: X: used before it is initialized. a local is set by an initializer, by `x = e`, by passing `&x` (the out-parameter pattern), or by a full array initializer list `{...}` (structs have no brace initializer; use `&agg` or pass the array). an array or struct is tracked part by part: writing every field (top-level) or every element by constant index sets the whole value, and reading a field or constant-index element that was written is fine even before the rest is; reading an unwritten part, or the whole value, before it is set is the error. a write through a computed index (`a[i] = e`, a fill loop) counts as setting the whole array, on every path (an approximation: the analyzer does not prove the loop covers it). a full `{...}` initializer, `&agg`, `&a[k]`, using the aggregate as an address (an array decaying to a pointer), or calling a method on it also set it. at a join (if/else, loop exit, switch, `?:`) a local is set only if every reaching path set it. a `while` or `for` that may run zero times does not count an assignment only inside the body; a `do`/`while` always runs once, so an assignment in its body does. parameters and globals are set from the start (a global with no initializer is 0). locals are not zeroed.
```
int b; pn(b); // error: b: used before it is initialized
int x; x = 1; pn(x); // ok
int y; if (c) y = 1; pn(y); // error unless every branch sets y
-point p; p.x = 1; pn(p.y); // error: partial fill does not set p
+point p; p.x = 1; pn(p.y); // error: p.y was never written
+point r; r.x = 1; pn(r.x); // ok: that part was written
+int[2] a; a[0] = 1; a[1] = 2; f(a); // ok: every element written
point q; fill(&q); pn(q.x); // ok: &q sets q (structs have no brace initializer)
int z; fill(&z); pn(z); // ok: &z sets z
```