# Milestone 19: `defer` and bare block statements. # # `defer ` runs the statement when the enclosing scope exits, in reverse # (LIFO) order, on every exit path. A bare `{ ... }` introduces a scope. Each # section returns a distinct code on failure; success falls through to 42. # The return value is captured before defers run, so the mutation here does not # change what is returned (Zig semantics). spill_check :: func() i32 { x i32 = 5 defer x = 999 return x } # A function-scope defer runs only at function exit; a `break` runs the loop-body # defer but NOT the enclosing function-scope defer. enclosing_defer_check :: func() i32 { v i32 = 0 defer v = v + 100 for 0..3 |i| { defer v = v + 1 if (i == 1) break } return v # 0->1 (i=0 fall-through), ->2 (i=1 break); the +100 runs after capture } main :: func() i32 { # 1. return value captured before defers run. if (spill_check() != 5) return 101 # 2. LIFO ordering, run at end of each loop iteration. r i32 = 0 for 0..1 |i| { defer r = r * 2 + 1 # registered first -> runs last defer r = r * 2 # registered second -> runs first _ = i } if (r != 1) return 102 # 0 -> (r*2)=0 -> (r*2+1)=1 ; FIFO would give 2 # 3. scoped bare block + scoped defer (defer fires at the closing brace, and # the block-local is not visible afterwards). a i32 = 1 { defer a = 4 c i32 = 3 _ = c } if (a != 4) return 103 # 4. `defer { ... }` block: all its statements run (in order) at scope close. s i32 = 0 { defer { s = s + 1 s = s * 10 } s = 5 } if (s != 60) return 104 # 5 -> 6 -> 60 # 5. `break` flushes the loop-body defer. bc i32 = 0 for 0..5 |i| { defer bc = bc + 1 if (i == 2) break } if (bc != 3) return 105 # i=0,1 fall-through + i=2 break # 6. `continue` flushes the loop-body defer. cc i32 = 0 for 0..3 |i| { defer cc = cc + 1 if (i == 1) continue cc = cc + 10 } if (cc != 23) return 106 # 10,+1 ; +1 (continue) ; +10,+1 # 7. break does not run an enclosing function-scope defer. if (enclosing_defer_check() != 2) return 107 return 42 }