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#44
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?
Follow-up to #20, which shipped the reflection core in
12f2dbe:Reflect.*— enumerate properties/fields by index, resolve ids by name, read a field's declared type, and genericget/set/has/kind/model. That's enough to write an auto-serializer or debug inspector by hand (the shipped example does exactly that, summing every field of every component while naming none).This tracks the remaining piece the proposal sketched: a generic value tree and a one-call
Reflect.serialize(entity)/deserializeon top of it.Why it's separate: a value tree needs an
any/tagged-union value type (a node that is "int 7" or "fixed 0.5" or "list [...]"), which is exactly the tagged-union / container work in #1.Reflect.field_typealready returns the type name per field, so once #1 lands a canonical value type,serializeis a thin walk:Scope:
any)Reflect.serialize(entity) -> valuewalking components + fieldsReflect.deserialize(value) -> entity(or apply-into-entity) as the inverseSequence this after #1. Related: #20 (the shipped reflection core), #1 (type system — prerequisite).
Shipped in
9452557.Canonical value tree — a self-describing
Valuenode:null/int/fixed/bool/str/list/object(Value.kindreturns the tag). Constructors (Value.int,Value.fixed,Value.str,Value.list,Value.object, …), builders (Value.add,Value.put), and accessors (Value.get/has/at/key_at/count/as_int/as_str). This is the concrete node the issue sketched ("int 7" / "fixed 0.5" / "list […]"); I built it directly rather than blocking on the general #1anytype — #1 stays the home for the language-level tagged union.Reflect.serialize(entity) -> value— exactly the walk from the issue sketch: for each component the entity has, for each field, readReflect.get+Reflect.field_typeand emit a typed node. Afixedfield → afixednode, everything else → anintnode, so the round-trip is bit-exact; the model id rides under a reserved"@kind"key.Reflect.apply(entity, value) -> int— the inverse: writes a value tree's fields back into a live entity (skipping@-keys and unknown names, so partial/older saves load cleanly), returning the count applied.JSON bridge —
Json.encode/Json.parseturn the tree to and from compact, stable, diffable text.fixedis written as an exact terminating decimal (Q16.16 always terminates) and parsed back bit-for-bit — verified exact across a sweep of the raw Q16.16 range (the naive 5-digit approach failed ~66% of values; the terminating-decimal + backward-recurrence decode is exact). Soserialize → encode → parse → applyreproduces every field bit-for-bit.Additive — written in Ludic and spliced on demand (runtime/native/value.ludic + reflect_io.ludic, the Query/Light pattern). Programs that don't touch
Value.*/Json.*/Reflect.serializecompile byte-identically (verified on snake/reflect/query) andx bootstrap-cfreereproduces the seed byte-for-byte.Docs + example —
examples/library/serialize.ludic(serialize → JSON → parse → apply round-trip, the issue's motivating flow), 21 namespace-method pages + Value/Json sections. Whole CI set green:x test72/72,x test-tools30/30, check-impl (376 ns-methods)/vocabulary/docs.