Skip to content

Commit 7c14931

Browse files
Technologicatclaude
andcommitted
CHANGELOG, briefs: 2.2.0 #82 done
briefs/2.2.0-remaining-issues.md: status item #1 flipped to done with summary of what landed; detailed #82 section rewritten as a DONE summary mirroring the #35 entry; "Recommendation for next slot" updated to point at #80 (with the design-pass caveat) since #83 is explicitly do-last. Added a new "Fleet-wide follow-ups" section noting the deferred coverage.run.omit and dev-deps-via-pdm sweeps so the next session can pick them up. CHANGELOG.md: added Internal entries for the doc additions and the revived test. The continuations behaviour itself is unchanged; what changed is the documentation and the test coverage of an existing property. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d72f4fa commit 7c14931

2 files changed

Lines changed: 46 additions & 54 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
- `unpythonic.llist.cons`: dropped the internal `_immutable` sentinel; the read-only `car`/`cdr` are now installed via `object.__setattr__` in `__init__`, and `__setattr__` is a one-liner that always raises.
2727
- `unpythonic.env.env`: dropped the `_direct_write` whitelist that allowed internal slots (`_env`, `_finalized`) to bypass `__setattr__`. Internal initialisation and `finalize()` now use `object.__setattr__` directly. Client code attempting `e._env = ...` or `e._finalized = ...` is now rejected by the reserved-name check (was silently allowed via the whitelist).
28+
- `doc/macros.md`: new "Topology of continuations: how the wiring works" subsection (with inlined `callcc_topology.png` diagram explaining the `cc`/`pcc` machinery) and "Scoping of locals in continuations" subsection (the rule, the box workaround, the three load-bearing limits that ruled out auto-`nonlocal` propagation). Closes #82.
29+
- `unpythonic/syntax/tests/test_conts.py`: revived the `"scoping, in presence of nonlocal"` testset that was disabled in 2022 due to a coverage.py source-parsing limitation. The new `[tool.coverage.run]` config in `pyproject.toml` scopes coverage to production code (excluding `*/tests/*`) and sidesteps the parse failure at report time.
2830

2931

3032
---

briefs/2.2.0-remaining-issues.md

Lines changed: 44 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
# 2.2.0 — Remaining open issues (session handoff)
22

3-
Updated 2026-05-06 after #35 landed. The original snapshot ordering is
4-
preserved below; status flags mark what's done.
3+
Updated 2026-05-06 after #35 + #82 landed. The original snapshot
4+
ordering is preserved below; status flags mark what's done.
55

66
## Status
77

8-
1. **#82** — pending; docs-only.
8+
1. ~~**#82**~~**done** this session. New `doc/macros.md` subsections
9+
"Topology of continuations: how the wiring works" (with inlined
10+
`callcc_topology.png` diagram explaining the `cc`/`pcc` machinery)
11+
and "Scoping of locals in continuations" (the rule, the workaround,
12+
three load-bearing limits that ruled out auto-`nonlocal`
13+
propagation). Revived the `"scoping, in presence of nonlocal"`
14+
testset (disabled in 2022); the original coverage.py source-parsing
15+
issue is now sidestepped via a new `[tool.coverage.run]` config
16+
that scopes coverage to production code and excludes `*/tests/*`.
17+
Issue closed.
918
2. ~~**#76**~~**done** (commit `b6423e7`, plus `ad6c3f6` for the
1019
`tryf`/`withf` `_accepts_arity` unification). Issue closed.
1120
3. ~~**#85 step 1**~~**done** (commit `7034add`). `expect[]` shipped,
@@ -14,16 +23,33 @@ preserved below; status flags mark what's done.
1423
4. ~~**#35**~~**done** this session. `cons.__delattr__` interception
1524
(bug fix), `cons` simplified via `object.__setattr__` (drops the
1625
`_immutable` sentinel), error-message wording corrected. Bonus
17-
`assignonce` `del`-rebind bypass fix and `env._direct_write` cleanup
18-
(resolves the TODO at env.py:77). New issue **#102** opened against
19-
3.0.0 for the `TypeError``dataclasses.FrozenInstanceError` swap
20-
that was held back for API stability.
26+
`assignonce` `del`-rebind bypass fix and `env._direct_write` cleanup.
27+
New issue **#102** opened against 3.0.0 for the `TypeError`
28+
`dataclasses.FrozenInstanceError` swap that was held back for API
29+
stability; subsequently superseded in scope by the
30+
`FrozenAttributeError` shim (`TypeError` + `FrozenInstanceError`)
31+
which lets us align with the stdlib idiom now without breaking 2.x
32+
callers — #102 retained as the 3.0.0 "drop the `TypeError` base"
33+
tracker.
2134
5. **#80** — pending; multi-shot generators, design pass before code.
2235
6. **#83** — pending; `end_lineno` / `end_col_offset` sweep, last.
2336

24-
Recommendation for next slot: **#82** is the most parked of the
25-
remaining items, and the resume notes for it are detailed enough
26-
to pick up cold.
37+
Recommendation for next slot: **#80** is the more substantive of the
38+
two remaining items but wants an API-design discussion first (see its
39+
detailed entry below). **#83** is explicitly *do last* — cross-cutting,
40+
and easy to merge-conflict with anything else in flight.
41+
42+
## Fleet-wide follow-ups (deferred to a future session)
43+
44+
- **`[tool.coverage.run].omit` pattern** for other PDM projects. The
45+
pattern is documented in `~/.claude/CI-SETUP-NOTES.md` §4a; sweep
46+
applies to `pylu`, `pydgq`, `wlsqm`, `mcpyrate`, `raven`, `pyan3`
47+
as relevant.
48+
- **Declare `coverage` (and `pytest-cov` where used) in
49+
`[dependency-groups].dev`** rather than ad-hoc `pip install` in CI
50+
workflows. Baseline updated in
51+
`~/.claude/PROJECT-SETUP-NOTES.md`; project-by-project propagation
52+
pending.
2753

2854
## Open before release
2955

@@ -40,50 +66,14 @@ to pick up cold.
4066

4167
## #82 — Document scoping of locals in continuations
4268

43-
**Decision: docs only, do not fix.** Per the ticket comments
44-
(Technologicat, 2022), implementation was tried (commit `2c7477c`,
45-
propagating parent-scope declarations into the continuation) but ran
46-
into three load-bearing limits:
47-
48-
- Continuation parameters (assignment targets of `call_cc`) must shadow
49-
same-named names from the parent scope.
50-
- No propagation upward — a name declared inside a continuation can't
51-
become available to the parent context, even though source-wise
52-
they're the same function. Would need a second pass.
53-
- At the top of a `with continuations` block, you can't tell from the
54-
AST whether the block is inside a function (so `nonlocal` vs `global`
55-
for parent locals is undecidable without whole-module analysis).
56-
57-
Therefore: continuations introduce a scope boundary. Document this
58-
analogously to how Python's comprehensions and generator expressions do.
59-
60-
**Resume notes (added 2026-05-05)**:
61-
62-
- The original experiment lives at commit `2c7477c` — recover via git
63-
archaeology (`git show 2c7477c`, `git diff 2c7477c~1 2c7477c` for the
64-
shape of the change). The half-finished propagation logic and any
65-
failing-test commits around it are the clearest source of the *why*.
66-
- There's an SVG/PDF illustration in the repo somewhere (predates this
67-
session) that maps the scoping situation; needs locating and
68-
deciphering to fold into the docs. Worth a `find . -name '*.svg'`
69-
/ `*.pdf` and a look at anything in `doc/` that isn't already
70-
cross-referenced from `macros.md`.
71-
- Continuations are one of the most complex features in unpythonic.
72-
Plan: either a dedicated subsection in `doc/macros.md` near the
73-
existing continuations material, or a standalone `doc/continuations.md`
74-
linked from there.
75-
- The compiled-out experimental code in `unpythonic/syntax/tailtools.py`
76-
(mentioned in the original ticket) is half of the *why* — the other
77-
half is the ticket comment thread. Both need to make it into the doc
78-
in present-tense form.
79-
80-
Touchpoints (when ready):
81-
- **Where to write**: `doc/macros.md` continuations section, or new
82-
`doc/continuations.md`.
83-
- **Updated examples**: `unpythonic/syntax/tests/test_conts.py`, near
84-
end of file (per ticket as of `f772df4`).
85-
86-
Save for its own session — the writing is more careful than the code.
69+
**DONE this session.**
70+
71+
- `doc/macros.md`: new `#### Topology of continuations: how the wiring works` subsection with inlined `callcc_topology.png` diagram, walking through the five panels (Base case, Sequence, Nested, Confetti chaining rule, Tail-call composition) and explaining what `cc` and `pcc` are, who sets them, and how the chain unwinds when a function ends or tail-calls another. Followed by `#### Scoping of locals in continuations` covering the rule (each `call_cc[]` introduces a scope boundary), the box workaround, and the three load-bearing limits that ruled out auto-`nonlocal` propagation. TOC updated.
72+
- `doc/callcc_topology.svg` re-exported with a white background (xviewer's checkerboard fallback made the transparent original unreadable); PNG export added.
73+
- `unpythonic/syntax/tests/test_conts.py`: revived the `"scoping, in presence of nonlocal"` testset (disabled in 2022 due to a coverage.py source-parsing issue). The test demonstrates that `nonlocal x` inside a continuation reaches back to the parent's `x`, just as in any ordinary nested closure. Ruff F811 silenced at the use site (post-macro the `nonlocal` is at the top of a separate function, so it isn't actually a redefinition).
74+
- `pyproject.toml`: new `[tool.coverage.run]` section scopes coverage to production code (`source = ["unpythonic"]`) and excludes `*/tests/*`. Sidesteps the coverage.py parse failure on the revived test at `coverage xml` time, and aligns with general "coverage signal is about production code, not tests" hygiene. Pattern documented in `~/.claude/CI-SETUP-NOTES.md` §4a for fleet propagation.
75+
- Bonus: `shift`/`reset` attribution corrected in the delimited-continuation parenthetical (Danvy & Filinski 1990, not Felleisen — Felleisen's operators are `control`/`prompt`) with links to Wikipedia and the Racket reference.
76+
- Issue closed.
8777

8878
## #76 — Add expression form of `with` (`withf`)
8979

0 commit comments

Comments
 (0)