Private
Public Access
5.6 KiB
5.6 KiB
Capy scope reflection
Objective and invariants
Replace type(value) with value::type. Add static type and struct reflection without adding runtime type metadata to ordinary values.
Preserve these invariants:
- Reflection must not change struct object layouts.
- ABI changes must have explicit version increments.
value::itemsmust evaluate the receiver once.- Reflection must preserve managed-value ownership.
- Every declared struct must carry a descriptor. Units that do not use
value::itemsmust not import the reflection host function. - Imported type lookup must continue to work.
Success criteria
value::typeworks for dependent generic parameters and results.- The compiler rejects
type(value). value::type_namereturns the concrete static type name as a string.- A struct value exposes its field count through
value::sizeass64. - A struct value exposes a
dvalmap throughvalue::items. - Each
itemsentry containsvalueandtype_namekeys. - Indexed and fixed-key DValue access both work.
- Reflection preserves ARC and evaluates the receiver once.
- Documentation, generated files, manifests, and artifact hashes are current.
- The complete acceptance suite passes.
Current state
- Status: complete.
- Source and runtime:
/root/mount_ssh/capy-bearerandcapy-bearer-dev:/Code/capy-bearer - Baseline:
daba223a9e73a4df5e3724b5721ed2c827eadc57
Goal tree
- G1: Define the reflection contract and representation.
- G1.1: Trace scope lookup, struct layout, DValue conversion, and ARC.
- G1.2: Define an embedded descriptor for every declared struct.
- G1.3: Define one metadata-driven runtime path for field values.
- G2: Implement the metadata and syntax.
- G2.1: Emit a reflection descriptor for every struct declaration.
- G2.2: Remove
type(value)and keep dependentvalue::type. - G2.3: Implement
value::type_name,value::size, andvalue::itemsthrough the descriptors.
- G3: Add focused tests.
- G3.1: Cover generic dependent types and rejected
type(value). - G3.2: Cover field access, dynamic keys, nested values, ARC, and evaluate-once behavior.
- G3.3: Cover invalid receivers and unknown scope members.
- G3.1: Cover generic dependent types and rejected
- G4: Update documentation and generated artifacts.
- G5: Run acceptance and adversarial review.
- G6: Commit, push, and update project notes.
Decisions, assumptions, and risks
value::type_namereports the concrete static type after alias resolution.- Every struct declaration must emit reflection metadata into the Wasm unit. Reflection must not depend on
#exportsor an external.apifile. - A custom section alone is insufficient because guest reflection code cannot read it. The unit needs descriptor data in linear memory.
value::sizeandvalue::itemsapply only to structs.value::itemshas this shape:{field_name: {value: field_value, type_name: "field_type"}}.- The DValue conversion must support every type that a struct can store. Nested structs and arrays need recursive conversion.
- Function fields can use the existing DValue callable encoding. Structs cannot store module handles.
- The compiler currently also accepts
import_alias::Type. This work must not remove that imported type spelling unless the implementation proves it obsolete. - Type aliases lose their source spelling during current type resolution. Reflection will report the resolved type unless preserving alias spelling has a clear local implementation.
Evidence
- 2026-09-01:
ScopeLookupparses anyexpression::identifier. The compiler currently gives it meaning only for dependent::typeand imported types. - 2026-09-01: DValue construction currently accepts scalars, strings, DValues, callables, map literals, and list literals. It does not directly accept struct or array expressions.
- 2026-09-01: The compiler keeps struct field metadata only while it compiles.
#exportscopies selected type declarations to external unit API metadata. The Wasm unit has no general struct reflection descriptor. - 2026-09-01: An initial expression-specific lowering prototype was discarded. It did not meet the embedded-metadata requirement.
- 2026-09-01: Commit
1fe0bd8added and pushed the embedded reflection implementation.
Result
- The compiler emits recursive descriptors in linear memory for local and imported structs.
- Reflection lowering uses descriptor offsets relative to
__memory_base. value::itemscallsbearer_capy_reflect_struct_brrb. It preserves callable and receiver ownership.- Core ABI 32 and compiler unit ABI 34 identify the new host function and unit metadata.
- The compiler emits no reflection host import when source does not use
value::items.
Verification
- Native frontend, compiler, Wasm, CLI, and tracked fixture tests passed.
- The phase-one runtime suite passed.
- The reflection fixture passed in the live runtime. It covered fixed and indexed field access, nested structs, typed arrays, DValues, wide integers, callables, an empty struct, receiver evaluation, and ARC.
- Documentation generator and compile-timeout tests passed.
- Guide tests passed after the generated example included its type alias.
- Artifact hashes were regenerated after the ABI and embedded descriptors changed unit bytes. The non-write golden test passed.
Concerns
- Imported struct descriptors have compile-time coverage. Imported struct values do not have a current cross-unit runtime path.
- The reflection host validates all addresses against the unit linear memory. A unit can still pass descriptors that point at other data in its own memory. This does not cross the unit memory boundary.