d5f63bc3e5
Lift 16b.1's no-capture restriction. The desugar pass's `scope` becomes a `BTreeMap<String, ScopeEntry>` carrying `KnownType` for fn/Lam-params, sentinels for Let-/Match-bindings. LetRec captures of `KnownType` names are lifted: the synthetic top-level fn's signature gets the capture types appended, and every call site of the LetRec name is rewritten via `subst_call_with_extras` to pass the captures positionally. Captures from let-bindings, match-arm patterns, polymorphic enclosing fns, and name-as-value uses are rejected at desugar with panics pointing at 16b.3-16b.7. Demo: `sum_below(n)` recurses via `(let-rec loop (params i) ... (body ... uses n ...) (in (app loop 1)))`. Lifts to `loop$lr_0(i: Int, n: Int) -> Int` with `(app loop X)` rewritten to `(app loop$lr_0 X n)`. Outputs 0, 10, 45. Tests: 103 -> 106 (+1 e2e local_rec_capture_demo, +2 desugar unit; the 16b.1 capture-panic test was repurposed into the positive fn-param-capture test). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.3 KiB
Plaintext
36 lines
1.3 KiB
Plaintext
; Iter 16b.2 — LetRec captures of fn-params (path-1 safe subset).
|
|
; `sum_below(n)` returns the sum of integers from 1 up to but not
|
|
; including n. The recursive helper `loop` captures the upper
|
|
; bound `n` from `sum_below`'s param list and recurses on its own
|
|
; counter `i`. The 16b.2 desugar pass lifts `loop` to a synthetic
|
|
; top-level fn `loop$lr_0(i: Int, n: Int) -> Int` (capture appended)
|
|
; and rewrites every `(app loop ARGS)` to `(app loop$lr_0 ARGS n)`.
|
|
;
|
|
; Expected stdout (one per line): 0 (sum below 1), 10 (1+2+3+4),
|
|
; 45 (1+2+...+9).
|
|
|
|
(module local_rec_capture
|
|
|
|
(fn sum_below
|
|
(doc "Sum 1 + 2 + ... + (n-1). Helper captures n from the enclosing scope.")
|
|
(type (fn-type (params (con Int)) (ret (con Int))))
|
|
(params n)
|
|
(body
|
|
(let-rec loop
|
|
(params i)
|
|
(type (fn-type (params (con Int)) (ret (con Int))))
|
|
(body
|
|
(if (app >= i n)
|
|
0
|
|
(app + i (app loop (app + i 1)))))
|
|
(in (app loop 1)))))
|
|
|
|
(fn main
|
|
(doc "Drive sum_below at 1, 5, 10. Expected (per line): 0, 10, 45.")
|
|
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
|
(params)
|
|
(body
|
|
(seq (do io/print_int (app sum_below 1))
|
|
(seq (do io/print_int (app sum_below 5))
|
|
(do io/print_int (app sum_below 10)))))))
|