Skip to content

Transpiler: support closure structs from local functions capturing variables #267

@jonathanpeppers

Description

@jonathanpeppers

Problem

When local functions in top-level statements reference outer byte[] variables, the C# compiler generates closure structs (display classes). The transpiler encounters stfld/ldfld on these compiler-generated types and throws TranspileException.

Closures are not supported. The compiler generated a closure struct
'<>c__DisplayClass0_0' capturing variable(s): collision_top_left, ...

This blocks the crypto sample (PR #211) which has 7 local functions capturing ~120 byte[] arrays.

Expected behavior

The transpiler should handle closure structs by recognizing that captured byte[] arrays are ROM data tables (same as top-level locals) and captured scalar variables map to zero-page addresses. The ldfld/stfld on the display class should resolve to the same addresses as the original variables.

Workaround

Inline all local functions that capture variables, eliminating closures entirely. This works but loses code structure and causes duplication for functions called from multiple sites (e.g., isBlocked has 9 call sites).

Implementation

  1. In DetectStructLayouts(), recognize compiler-generated display classes (<>c__DisplayClass*) as closure structs rather than throwing
  2. Map each captured field back to its original variable's transpiler allocation (ROM table address for byte[], zero-page address for scalars)
  3. Emit ldfld/stfld on closure fields as regular LDA/STA to the mapped addresses
  4. Handle the implicit this parameter (ldarg.0 + ldfld pattern) that the compiler uses to access captured variables inside local functions

Context

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions