Lifecycle hooks: @OnStart/@OnQuit, @OnDespawn, @OnAttach (like @OnSpawn)
Adds the rest of the game/entity/property lifecycle as @-hooks, each firing at one timeline moment and reducing to ordinary code: - @OnStart / @OnQuit (program): @OnStart aliases the Start phase; @OnQuit runs in the frame loop's done: block, after the loop stops and before teardown. - @OnDespawn(Model) (entity): a destructor. Despawn doesn't statically know the entity's model, so hooks compile to @on_despawn_<Model>(entity) functions and emit_despawn dispatches on @L_kind. Symmetric with @OnSpawn. - @OnAttach(Property): fires in emit_init_component once a property is attached and seeded, with the property bound by name. Registries + parsing mirror @OnSpawn. examples/lifecycle.ludic narrates the whole timeline (output 1 700 50 950 2). Behaviour-preserving (goldens byte-identical, despawn users unaffected when no hooks registered); test.sh 16/16, fixpoint holds. Deferred: @OnDetach (per-property runtime dispatch) and scene @OnEnter/@OnExit (need scene support in the compiler). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
28abd3a2c3
commit
6e11212cf2
8 changed files with 3993 additions and 3258 deletions
39
LANGUAGE.md
39
LANGUAGE.md
|
|
@ -295,24 +295,43 @@ property Velocity {
|
|||
}
|
||||
```
|
||||
|
||||
**`@OnSpawn` — a constructor.** `@OnSpawn(Model)` on a handler runs its body every
|
||||
time a `Model` is spawned, with the model's properties bound by name — a place to
|
||||
initialize an entity. It's a handler keyed to the spawn, not an observer on the
|
||||
data, so the ECS model is untouched:
|
||||
**Lifecycle hooks.** A game's timeline has fixed moments, and each is a handler
|
||||
annotation. They fire in this order and each reduces to ordinary code, so the
|
||||
data stays plain and behaviour stays in handlers:
|
||||
|
||||
```
|
||||
boot ── @OnStart ─▶ spawn ── @OnAttach(P), @OnSpawn(M) ─▶ … ── @OnDespawn(M) ─▶ quit ── @OnQuit
|
||||
```
|
||||
|
||||
- **`@OnStart` / `@OnQuit`** — the *program*. `@OnStart` runs once at boot (it is
|
||||
the `Start` phase); `@OnQuit` runs once at shutdown, after the frame loop stops
|
||||
and before the process exits — the place to `save()` or clean up.
|
||||
- **`@OnSpawn(Model)` / `@OnDespawn(Model)`** — an *entity*. Both bind the model's
|
||||
properties by name; `@OnSpawn` is a constructor, `@OnDespawn` a destructor.
|
||||
Despawn doesn't statically know an entity's model, so despawn hooks compile to
|
||||
functions dispatched on the entity's kind.
|
||||
- **`@OnAttach(Property)`** — a *property*, fired each time that property is
|
||||
attached to an entity (once its fields are seeded), with the property bound by
|
||||
name.
|
||||
|
||||
```ludic
|
||||
# doc-check: skip — a spawn hook
|
||||
@OnSpawn(Enemy)
|
||||
handler InitEnemy { Health.hp = Health.max } # start every Enemy at full HP
|
||||
# doc-check: skip — lifecycle hooks
|
||||
@OnStart handler Boot { seed(1) }
|
||||
@OnSpawn(Enemy) handler Init { Health.hp = Health.max } # constructor
|
||||
@OnDespawn(Enemy) handler Clean { drop_loot(Health.hp) } # destructor
|
||||
@OnAttach(Sprite) handler Load { Sprite.id = image_load("goblin.png") }
|
||||
@OnQuit handler Save { save() } # once, at shutdown
|
||||
```
|
||||
|
||||
**`@Handles` — the handlers a program drives.** Written in front of the
|
||||
`program`, `@Handles(Move)` names the handlers it uses. It parses and reads as
|
||||
documentation; every declared handler still runs (registration is implicit).
|
||||
|
||||
See [`examples/annotations.ludic`](examples/annotations.ludic), which uses all
|
||||
four. (`@OnDespawn` and change-reactions are future work — despawn doesn't
|
||||
statically know an entity's model, and reactions need change-tracking.)
|
||||
See [`examples/annotations.ludic`](examples/annotations.ludic) (queries, computed
|
||||
fields, one hook) and [`examples/lifecycle.ludic`](examples/lifecycle.ludic) (the
|
||||
whole timeline). Still to come: **`@OnDetach`** (needs the same runtime kind
|
||||
dispatch as despawn, per property) and **scene** hooks (`@OnEnter`/`@OnExit`),
|
||||
which wait on `scene` support landing in the compiler.
|
||||
|
||||
## Structs, arrays and slices
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue