Skip to main content

brink_format/
story.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3
4use crate::definition::{
5    AddressDef, AddressPath, AliasEntry, ContainerDef, DebugInfoSection, EffectRowEntry,
6    ExternalFnDef, FrameShapeDef, GlobalVarDef, LineVariantGroup, ListDef, ListItemDef,
7    ScopeLineTable, StructShapeDef,
8};
9use crate::id::DefinitionId;
10use crate::value::ListValue;
11
12/// The top-level compiled story: everything the runtime needs to execute.
13#[derive(Debug, Clone, PartialEq)]
14pub struct StoryData {
15    pub containers: Vec<ContainerDef>,
16    /// Per-scope line tables. Each scope (root, knot, stitch) gets one table
17    /// shared by all containers within that scope.
18    pub line_tables: Vec<ScopeLineTable>,
19    pub variables: Vec<GlobalVarDef>,
20    pub list_defs: Vec<ListDef>,
21    pub list_items: Vec<ListItemDef>,
22    pub externals: Vec<ExternalFnDef>,
23    /// Address definitions mapping IDs to byte offsets within containers.
24    pub addresses: Vec<AddressDef>,
25    /// Qualified-path → address-target table. The single source of truth for
26    /// [`Program::find_address`](../../brink_runtime/struct.Program.html#method.find_address);
27    /// empty for legacy/converter output (the linker then falls back to
28    /// deriving scope paths from container names).
29    pub address_paths: Vec<AddressPath>,
30    /// Interned name strings, indexed by [`NameId`](crate::id::NameId).
31    pub name_table: Vec<String>,
32    /// List literal values referenced by `PushList(idx)` opcodes.
33    pub list_literals: Vec<ListValue>,
34    /// The T1b `LiteralPool` (`docs/format-v4-rfc.md` §2): content-hash
35    /// deduplicated constant values referenced by `PushLiteral(idx)` opcodes.
36    /// Distinct from `list_literals`/`PushList` — this is additive new
37    /// surface for T1b collection literals, not a replacement (the RFC's
38    /// `ListLiterals` absorption is a separate, larger migration; see the
39    /// T1b-2 PR description).
40    pub literal_pool: Vec<crate::value::Value>,
41    /// The TM-4 `StructShapes` table (`docs/format-spec.md` section tag
42    /// `0x0C`): one entry per declared `STRUCT`, indexed by
43    /// [`crate::value::ShapeId`]. Referenced by `RecordNew`/static
44    /// `RecordGet`/`RecordSet` opcodes and by `Value::Record` values in the
45    /// literal pool, globals, and the transcript.
46    pub struct_shapes: Vec<StructShapeDef>,
47    /// `DefinitionId`s of every `#@private` definition (M-2b,
48    /// `docs/modules-spec.md` §4 boundary rule 2). Sorted ascending by raw id
49    /// for determinism. Empty for the entire pre-modules / all-public world,
50    /// in which case the `.inkb` `Visibility` section (tag `0x0E`) is omitted
51    /// entirely — so public-only stories stay byte-identical.
52    ///
53    /// This is the complement encoding: public is the default, private names
54    /// are enumerated (mirroring how `#@local` scope defaults are carried).
55    /// The runtime builds a lookup set from it and refuses host **semantic**
56    /// access (variable get/set, entry lookup, function eval) to these defs;
57    /// host **persistence** (save/load/journal/replay) ignores it and sees
58    /// everything (§4 boundary rule 2).
59    pub private_defs: Vec<DefinitionId>,
60    /// The M-3 `AliasTable` (`docs/modules-spec.md` §5, format section tag
61    /// `0x0F`): old→new `DefinitionId` rename records emitted from
62    /// `#@was(old_name)` directives on modules and definitions. Sorted by
63    /// `old` for the runtime's binary-search miss-path lookup. Empty for
64    /// every story that uses no `#@was` — including the entire pre-M-3
65    /// corpus and converter output.
66    pub alias_table: Vec<AliasEntry>,
67    /// The T2-3 `EffectRows` table (`docs/effects-spec.md` §11, format section
68    /// tag `0x0D`): one factored effect row per knot/stitch — the host's
69    /// resume-scheduling estimate (§12.1). **Additive metadata**: the runtime
70    /// does not consume rows yet (`sleep`/narrowing are the future clients), so
71    /// a story that carries rows runs byte-identically to one that does not.
72    /// Empty for converter output and any story compiled before this slice.
73    /// Sorted by `def` (ascending raw id) for determinism.
74    pub effect_rows: Vec<EffectRowEntry>,
75    /// The FS-3 `FrameShapes` table (`docs/flow-suspension-spec.md` §4/§11,
76    /// `.inkb` section tag `0x10`): one [`FrameShapeDef`] per `await` site —
77    /// the name-keyed static description of which locals cross the park, so
78    /// the runtime knows what to spill/restore around a suspension. Sorted by
79    /// `site` (ascending raw id) for determinism.
80    ///
81    /// **Reserved-through-fence**: additive metadata the runtime does not
82    /// consume yet, and — because the E052 `await` lowering fence stands
83    /// (FS-3c) — never populated by compilation today. Empty for every story
84    /// compiled today and all converter output, so a story carrying frame
85    /// shapes runs byte-identically to one without. First emission rides the
86    /// continuation-splitting codegen when the fence drops (FS-3r). The
87    /// section is **omitted entirely** from `.inkb` when empty (self-framed in
88    /// the offset table, like `Visibility`), so existing stories stay
89    /// byte-identical.
90    pub frame_shapes: Vec<FrameShapeDef>,
91    /// D6 `DebugInfo` (`docs/debugger-spec.md` §2, `.inkb` tag `0x11`):
92    /// bytecode-offset → source-range map. `None` when debug info was not
93    /// requested at compile time — the ship-policy default (§1.2): a
94    /// release-exported story never carries this, so the section is
95    /// omitted entirely from `.inkb` and every existing byte stays
96    /// identical to before this field existed. `Some` only for a dev/studio
97    /// compile or an explicit CLI debug flag.
98    pub debug_info: Option<DebugInfoSection>,
99    /// Line-variant groups (stage 1 of the shared-alternatives track,
100    /// issue #3273): records tying runs of consecutive line-table entries
101    /// back to one authored line whose inline alternatives were enumerated
102    /// at recognition time. Empty until the stage-2 flip routes lines here;
103    /// the `.inkb` section (tag `0x12`) is **omitted entirely when empty**,
104    /// so every story without variant groups stays byte-identical.
105    pub line_variant_groups: Vec<LineVariantGroup>,
106    /// CRC-32 checksum from the `.inkb` header, used for locale validation.
107    /// Zero for stories not loaded from `.inkb`.
108    pub source_checksum: u32,
109}