From 54b8a8918bb63c98a8f58e823033232243647562 Mon Sep 17 00:00:00 2001 From: zinc Date: Wed, 14 Oct 2026 10:39:47 +0000 Subject: 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). --- tests/langerrors/defer_break.zc | 11 +++++++++++ tests/langerrors/defer_continue.zc | 11 +++++++++++ tests/langerrors/defer_later_name.zc | 9 +++++++++ tests/langerrors/defer_return.zc | 8 ++++++++ 4 files changed, 39 insertions(+) create mode 100644 tests/langerrors/defer_break.zc create mode 100644 tests/langerrors/defer_continue.zc create mode 100644 tests/langerrors/defer_later_name.zc create mode 100644 tests/langerrors/defer_return.zc (limited to 'tests/langerrors') diff --git a/tests/langerrors/defer_break.zc b/tests/langerrors/defer_break.zc new file mode 100644 index 0000000..193f3f0 --- /dev/null +++ b/tests/langerrors/defer_break.zc @@ -0,0 +1,11 @@ +namespace; +include rt; + +// expect: break can't leave a deferred statement +fn main() { + while (1) { + defer { break; } + rt.put_n(1); + } + return 0; +} diff --git a/tests/langerrors/defer_continue.zc b/tests/langerrors/defer_continue.zc new file mode 100644 index 0000000..079b02b --- /dev/null +++ b/tests/langerrors/defer_continue.zc @@ -0,0 +1,11 @@ +namespace; +include rt; + +// expect: continue can't leave a deferred statement +fn main() { + for (let i = 0; i < 2; i++) { + defer { continue; } + rt.put_n(i); + } + return 0; +} diff --git a/tests/langerrors/defer_later_name.zc b/tests/langerrors/defer_later_name.zc new file mode 100644 index 0000000..17f175d --- /dev/null +++ b/tests/langerrors/defer_later_name.zc @@ -0,0 +1,9 @@ +namespace; +include rt; + +// expect: y is used but never defined +fn main() { + defer rt.put_n(y); + int y = 3; + return 0; +} diff --git a/tests/langerrors/defer_return.zc b/tests/langerrors/defer_return.zc new file mode 100644 index 0000000..bceefe0 --- /dev/null +++ b/tests/langerrors/defer_return.zc @@ -0,0 +1,8 @@ +namespace; +include rt; + +// expect: return can't be used in a deferred statement +fn main() { + defer { rt.put_n(1); return 1; } + return 0; +} -- cgit v1.2.3