Skip to content

# fold-1: fold becomes an imperative construct (first syntax-reform constuct)#39

Merged
vpisarev merged 1 commit into
masterfrom
fold-1
Jul 11, 2026
Merged

# fold-1: fold becomes an imperative construct (first syntax-reform constuct)#39
vpisarev merged 1 commit into
masterfrom
fold-1

Conversation

@vpisarev

Copy link
Copy Markdown
Owner

fold is now a thin imperative sugar over for:

fold <acc> = <init> for <clauses> { body }
  ==>  { var <acc> = init; for <clauses> { body }; <acc> }

The accumulator is a real mutable var, ASSIGNED in the body (acc = f(acc,x) / acc += x), not yielded as the tail value; the whole-fold value is the accumulator after the loop. Multiple accumulators are multiple vars (fold a=0, b=1 for ..). break/continue/return are legal in the body (it is a plain for). A closure in the body captures the accumulator VAR. The named reduction sugars (all/exists/count/find/find_opt/filter/vector, spelled name(for ...)) are a separate construct, unchanged.

Highlights (full history in docs/fold1_report.md):

  • Simultaneous tuple assignment (a,b) = (b,a+b): a parse-time desugar (materialize RHS into a temp before any store) — the Fibonacci/swap idiom.
  • FB-023 fixed: a latent C-gen soundness hole (single-use temp reading mutable memory inlined past an aliasing store), surfaced by the swap; fixed with a recursive movement_unsafe_read guard in find_single_use_vals.
  • Token-precise spans: the reform-prep-1 batch spans now give each token its own span; a side win is 12 negative goldens with tighter, correct carets.
  • The whole 68K-line corpus AND the self-hosting compiler migrated to the new form (census docs/fold_census.md: 261 sites, zero closure-captures-accumulator sites, so the var-capture semantics change is behavior-neutral). Compiler migration handled a silent-bug class where an accumulator name shadows its own iteration collection / a body val — every such site renames the accumulator.
  • An old-style value body warns "'fold' accumulator 's' is never assigned … the body must UPDATE the accumulator ('s = ' / 's += ...')".

Verification: full ladder green (unit 168, negative 90, T4 IR 63, cfold, corpus O0/O3); bootstrap fixpoint holds (the compiler self-builds deterministically after migrating its own folds); -pr-resolve census unaffected.

CLAUDE.md fold gotcha rewritten; language_changes_brief.md §2 -> IMPLEMENTED.

…onstruct)

`fold` is now a thin imperative sugar over `for`:

    fold <acc> = <init> for <clauses> { body }
      ==>  { var <acc> = init; for <clauses> { body }; <acc> }

The accumulator is a real mutable var, ASSIGNED in the body (`acc = f(acc,x)` /
`acc += x`), not yielded as the tail value; the whole-fold value is the
accumulator after the loop. Multiple accumulators are multiple vars
(`fold a=0, b=1 for ..`). break/continue/return are legal in the body (it is a
plain `for`). A closure in the body captures the accumulator VAR. The named
reduction sugars (all/exists/count/find/find_opt/filter/vector, spelled
`name(for ...)`) are a separate construct, unchanged.

Highlights (full history in docs/fold1_report.md):
- Simultaneous tuple assignment `(a,b) = (b,a+b)`: a parse-time desugar
  (materialize RHS into a temp before any store) — the Fibonacci/swap idiom.
- FB-023 fixed: a latent C-gen soundness hole (single-use temp reading mutable
  memory inlined past an aliasing store), surfaced by the swap; fixed with a
  recursive movement_unsafe_read guard in find_single_use_vals.
- Token-precise spans: the reform-prep-1 batch spans now give each token its own
  span; a side win is 12 negative goldens with tighter, correct carets.
- The whole 68K-line corpus AND the self-hosting compiler migrated to the new
  form (census docs/fold_census.md: 261 sites, zero closure-captures-accumulator
  sites, so the var-capture semantics change is behavior-neutral). Compiler
  migration handled a silent-bug class where an accumulator name shadows its own
  iteration collection / a body val — every such site renames the accumulator.
- An old-style value body warns "'fold' accumulator 's' is never assigned … the
  body must UPDATE the accumulator ('s = <expr>' / 's += ...')".

Verification: full ladder green (unit 168, negative 90, T4 IR 63, cfold, corpus
O0/O3); bootstrap fixpoint holds (the compiler self-builds deterministically
after migrating its own folds); -pr-resolve census unaffected.

CLAUDE.md fold gotcha rewritten; language_changes_brief.md §2 -> IMPLEMENTED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vpisarev vpisarev merged commit 1f9b372 into master Jul 11, 2026
3 checks passed
@vpisarev vpisarev deleted the fold-1 branch July 11, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant