;;;; defer in a let whose extent is the function body. ;;;; ;;;; A let is not a frame here: its bindings are function slots like any other, ;;;; and nothing is released at scope exit (spec-memory.md, "When storage is ;;;; released"). So a let at the top level of a function body has exactly the ;;;; function's extent, a defer written in it always registers, and it is as ;;;; safe as one written at the top level. A let nested inside such a let has ;;;; the same extent and the same permission. ;;;; ;;;; The numbers differ per failure, so a wrong answer names its own cause. (defvar order i64) (defn note [n i32] () (set order (+ (* order 10) (i64 n)))) ;;; One defer in a let, with the acquisition it is paired with above it. This ;;; is the shape the relaxation exists for: acquire, defer the release beside ;;; it, then use it. (defn one [] i64 (let [a 1] (defer (note a)) (note 9)) order) ;;; Two resources in one let. This is the case a flag granted once per block ;;; instead of once per form gets wrong: the first defer registers and the ;;; second is refused. (defn two [] () (let [a 1 b 2] (defer (note a)) (defer (note b)) (note 9))) ;;; A nested let still has the function's extent, so a defer in it registers ;;; too — and it registers *later* than the outer one, so it runs first. (defn nested [] () (let [a 1] (defer (note a)) (let [b 2] (defer (note b)) (note 9)))) ;;; Registration order is one order across the boundary: a defer at the top ;;; level and a defer inside a let interleave by where they are written, not by ;;; which construct they are in. Written 1, 2, 3; run 3, 2, 1. (defn mixed [] () (defer (note 1)) (let [x 2] (defer (note x)) (defer (note 3)) (note 9))) ;;; An early return runs them too, and innermost-first, exactly as it does for ;;; a defer at the top level. The let's binding is still live when the defer ;;; reads it, because the slot is the function's. (defn early [] i64 (let [a 1] (defer (note a)) (let [b 2] (defer (note b)) (return 7))) 0) (defn main [] i32 (set order 0) (print (one)) (println "") ; 9 — read before the defer runs (set order 0) (one) (print order) (println "") ; 91 (set order 0) (two) (print order) (println "") ; 921 — reverse of writing (set order 0) (nested)(print order) (println "") ; 921 (set order 0) (mixed) (print order) (println "") ; 9321 (set order 0) (print (early)) (println "") ; 7 (print order) (println "") ; 21 0)