# c has no closure syntax

One `Ishikawa → scientific method → Six Sigma` loop. The record below is the
commit message as written at the time, before the outcome was known to anyone
reading this file.

## Record — `2bed848`

```
EXPERIMENT: hand the construct the body as a real closure

ROOT CAUSE of the weaker design: "C has no closures" was taken as a fact about
what is possible. It is a fact about one grammar. Every C++ lambda, every Go
closure, every Rust closure compiles to a struct of captured values plus a
function pointer -- which is what is emitted here. Codegen emits C; it is not
written in C's syntax, and the distinction is the whole difference between a
construct that can only decide whether to repeat and one that controls
invocation.

It would also have crippled the JS backend, which has closures natively, for a
limit that applies only to the C one.

PREDICTIONS AND RESULTS
  1 env struct + thunk taking void*                        TRUE
  2 fails to compile: struct redefinition                  FALSE -- C allows the
    inner declaration to shadow. Prediction wrong; C is more permissive than
    assumed. A different real defect surfaced instead: a wrap with no exit
    construct emitted `(EL_STR("f"), EL_STR(""), __r);` -- a call to an empty
    target -- because has_exit was reused as "needs a wrapper" and the exit line
    was emitted unconditionally. Fixed.
  3 compiles when the target is declared in El             FALSE -- and this is
    the root cause worth keeping: El has ONE type, el_val_t = int64_t. El's type
    system cannot describe a callable, so `extern fn` and the real signature
    cannot be made to agree in El's own vocabulary. The fix is not a cast:
    codegen DEFINES the wrap calling convention, so codegen emits the extern
    declaration. The convention is not El-expressible; it is emitted.
  4 target controls invocation, 0..N times                 TRUE
  5 existing @manager output byte-identical                TRUE
  6 compiler fixpoint holds                                TRUE
  7 emitting the convention makes it compile               TRUE

MEASURED
  base(5) wrapped by a target that invokes the body twice and sums -> 10
  never_runs(5) wrapped by a target that never invokes it        -> 999

Neither is expressible by "decide whether to repeat". This supersedes the
repeats_body experiment on experiment/repeats-body, which was built around the
mistaken limit.
```

## Record — `7d01608`

```
land wraps_body: a construct controls invocation

Proven on experiment/wraps-body (2bed848): base(5) wrapped by a target that
invokes the body twice returns 10; a target that never invokes it returns 999.
Neither is expressible by deciding whether to repeat.

Root cause it corrected: 'C has no closures' is a fact about one grammar, not
about what can be emitted. And El's single type (el_val_t = int64_t) cannot
describe a callable, so codegen emits the calling convention rather than asking
El's type system for something it structurally cannot say.
```
