Proposal: reflection / runtime type info (Reflect.*) — powers auto-serialization & debug inspectors #20
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A reflection capability: inspect properties, models, and fields at runtime
(and/or compile time) — names, types, and values. Primarily an engine/tooling
feature that powers things game devs consume without writing reflection code
themselves.
Why it matters (indirectly) for game devs
Reflection is advanced, so it's low priority as a user-facing feature — but
it unlocks conveniences non-experts love:
propertywithout hand-writing it.Most developers should get these benefits via built-in features, not by calling
a reflection API directly.
Proposed API (illustrative)
property/model(name, type, offset).Considerations
at compile time; zero or near-zero runtime cost) — fits Ludic's AOT, native,
deterministic model far better than heavy runtime introspection.
don't pay for it.
— sequence this after that lands.
Scope / acceptance
serialize.Related: #1 (type system — prerequisite), Filesystem (serialization), Logging.
Shipped the reflection core in
12f2dbe(pushed tomain).Reflect.*— runtime reflection over the world schema:prop_count/prop_name(i),field_count(prop)/field_name(prop, i)/field_type(prop, i)— walk every component and field by index;field_typereports the declared type ("int"/"fixed"/ …).prop(name)/field(prop, name)— ids by name (-1= none).get/set/has(entity, prop, …)— a field by(prop, field)id.kind(entity)/model(name)— an entity's model.Implementation: the enumeration adds an EV8 metadata layer to the generated reflection ABI (
ludic_prop_count/prop_name/field_count/field_name/field_type, generated the same way asludic_prop_id— a switch over compile-time property/field metadata, falling through to mod-registered components). It's all built at compile time — a table walk, not heavy runtime introspection — so, per the issue's "prefer compile-time reflection, opt-in per binary" guidance, a program that never reflects pays nothing, and one that usesReflect.*force-emits the ABI without needing@eventsof its own.Two of the acceptance items are covered directly: field enumeration + get/set by name + entity component iteration, and one real consumer —
examples/library/reflect.ludicincludes a generic inspector that sums every field of every component an entity has while naming none of them (the auto-save / debug-overlay pattern end to end), 20 self-asserting cases wired intox test(now 64 passed). Docs: aReflectsection + 12 per-symbol pages, positioned as an advanced/tooling surface;x check-impl/x check-docsgreen.Deferred: the generic value-tree
serializethe proposal also lists. It needs anany/tagged-union value type — exactly the #1 type-system work this issue names as the prerequisite — so I've tracked it as #44 rather than forcing a value type in ahead of #1.Reflect.field_typealready exposes the per-field type that a serializer will switch on, so #44 becomes a thin walk once #1 lands. Closing this as the reflection core + inspector consumer.