aboutsummaryrefslogtreecommitdiff
path: root/docs/LEARN.md
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 10:39:47 +0000
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 10:39:47 +0000
commit54b8a8918bb63c98a8f58e823033232243647562 (patch)
treee0608f7dab1f568c22390262e5a6d39966519760 /docs/LEARN.md
parenttodo: handoff section with state, conventions, in-flight work and architectur... (diff)
zc: add the defer statement
defer expr; and defer { ... } register code that runs when the enclosing block ends: at the end of the block, and at return, break and continue that leave it. the tokens are kept at the defer and compiled again at each exit (block_close, body, kw_return, kw_break, kw_continue), newest first, before the block's variables are released, so the analyzer sees a deferred rt.free(p) as the transfer of p where it runs. names mean what they meant at the defer; values are read when it runs. return, break and continue inside a deferred statement are errors, reported once. works in unchecked code and closures (own base per function context).
Diffstat (limited to 'docs/LEARN.md')
-rw-r--r--docs/LEARN.md38
1 files changed, 38 insertions, 0 deletions
diff --git a/docs/LEARN.md b/docs/LEARN.md
index a3588e7..d514d85 100644
--- a/docs/LEARN.md
+++ b/docs/LEARN.md
@@ -174,6 +174,44 @@ output:
0 5 6
```
+### defer
+
+`defer expr;` or `defer { statements }` runs code when the enclosing block ends: after the last statement, and also on `return`, `break` and `continue` out of it. defers in a block run last registered first. the deferred code is compiled at each exit, so it sees the variables as they are when it runs, and `return e;` computes `e` before any defer runs. `defer rt.free(p);` hands the owner `p` over at that point: `p` stays usable until the block ends and is not freed twice. `return`, `break` and `continue` are not allowed inside a deferred statement.
+
+[example source](../examples/learn/34-defer.zc):
+
+```zc
+namespace;
+include rt;
+fn say(n) { rt.put_n(n); rt.put_c(32); return 0; }
+int work(int n) {
+ int* p = rt.new(int);
+ defer rt.free(p);
+ defer say(100);
+ *p = n * 2;
+ say(*p);
+ if (n > 2) return *p + 1;
+ say(1);
+ return 0;
+}
+fn main() {
+ for (let i = 0; i < 4; i++) {
+ defer { say(i); rt.put_c(10); }
+ if (i == 1) continue;
+ say(work(i));
+ }
+}
+```
+
+output:
+
+```text
+0 1 100 0 0
+1
+4 1 100 0 2
+6 100 7 3
+```
+
## numbers and strings
### sized integers