1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
//! Global registries collected via `inventory`.
//!
//! lives in [`bb_ir::registry`] (foundation, shared by `bb-dsl` and
//! `bb-runtime`). This module re-exports it and adds the custom-op
//! registry, which depends on runtime-side types (`RuntimeResourceRef`,
//! `OpError`, `DispatchResult`) and therefore stays alongside the
//! engine.
//!
//! See the module-level docs in `bb_ir::registry` for the
//! concrete-component half's authoring patterns. The custom-op
//! registry follows the same `inventory::submit!` pattern; the
//! `bb::register_op!{}` declarative macro emits the submission for
//! library makers.
// Re-export the concrete-component registry so legacy
// `crate::registry::ConcreteComponentRegistration` paths (emitted by
// the bb-derive proc macros) keep resolving.
pub use DependencyDecl;
pub use ;
// --- Unified op registration ---------------------------------------
//
// One `OpRegistration` covers every op the framework dispatches —
// user-shipped via `bb::register_op!` AND framework-shipped from
// `bb-ops`. `RegistrationKind::{Custom, Syscall}` discriminates
// which iterator surface returns the entry.
/// Type-erased dispatch fn for any op (custom OR syscall).
pub type OpInvokeFn = fn ;
/// User-custom vs framework-syscall discriminator on
/// [`OpRegistration`]. Iterators surface entries filtered by kind.
/// Single inventory entry covering every op the framework
/// dispatches. Library makers ship via `bb::register_op!`; bb-ops's
/// syscalls submit directly. Engine dispatch keys on
/// `(domain, op_type)` — no TypeId lookup.
collect!;
/// Look up a Custom-kind op by its `(domain, op_type)` key. Used
/// by the engine's dispatch fallback for user-shipped ops outside
/// the role surface.
/// Iterate every Custom-kind op registration this binary links in.
/// Iterate every Syscall-kind registration. Consumed by
/// `Engine::register_all_framework_syscalls` at Node construction
/// time.
// --- Component-role registration ----------------------------------
//
// Every `#[derive(bb::<Role>)]` proc-macro emits one
// `ComponentRoleBinding` per `(component_type, role)`. The Engine
// merges them at install time so a single `ComponentRegistration`
// (the existing `ConcreteComponentRegistration` foundation entry +
// these per-role bindings) carries the full picture: state
// serialize/restore + every role the component implements.
/// One concrete framework role a component declares.
/// Per-`(component_type, role)` inventory entry: each
/// `#[derive(bb::<Role>)]` proc-macro emits one of these alongside
/// the universal triple. `Node::ensure_ready` walks the channel +
/// joins by `type_name` to compute the role bitflags per
/// concrete component.
collect!;
/// Per-`(component_type, role)` inventory carrying a per-T
/// dispatcher-registration fn pointer. Each role derive emits
/// one of these alongside [`ComponentRoleBinding`]; `install()`
/// walks the channel + calls `register_fn(engine)` for each
/// bound concrete so the engine learns about every role
/// dispatcher without the install path needing the typed `&T`.
collect!;
/// Look up the dispatcher-registration fn for
/// `(type_name, role)`. `install()` calls this for every binding
/// in the artifact's `BindingSpec`. Returns `None` when the role
/// derive isn't present in this binary's inventory (e.g. a
/// hand-implemented role trait without the derive).
/// Per-concrete inventory carrying a per-T Bootstrap dispatcher-
/// registration fn pointer. The `#[derive(bb::Concrete)]` macro
/// emits one of these per registered concrete so the install path
/// can register every concrete's `Bootstrap` dispatcher without the
/// per-T downcast. Pairs with [`crate::engine::Engine::register_bootstrap_dispatcher`].
///
/// The derive's emitted impl falls back to the
/// [`crate::contracts::bootstrap::Bootstrap`] trait default (no-op),
/// so a Concrete with no manual `impl Bootstrap` still registers a
/// dispatcher entry that drains the Component bootstrap phase
/// cleanly. Authors override the default by hand-writing
/// `impl Bootstrap for X` alongside the derive — the derive's
/// `#[bb(bootstrap_override)]` attribute (parsed in
/// `bb-derive::parse`) suppresses the default-impl emission so the
/// two impls do not collide.
collect!;
/// Look up the Bootstrap dispatcher-registration fn for `type_name`.
/// `install()` calls this for every registered concrete so the
/// Component bootstrap fire path can dispatch through the right impl.
/// Returns `None` when the concrete was registered without the
/// `#[derive(bb::Concrete)]` Bootstrap-bridge emission.
/// Iterate every role binding for a given component type. Used by
/// `Node::ensure_ready` to compute the bitflags + by introspection
/// tools to discover what roles a struct implements.
+ use<'_>
// --- Storage-type registration ------------------------------------
//
// Every `#[derive(bb::<Role>)]` proc-macro emits one or two
// `StorageTypeEntry` structs (Codec emits two — one for In, one for
// Out) into the inventory carrier. The compiler binding step (Task 9)
// reads these to populate `BindingSlot.storage_types`. The fn-pointer
// slot is necessary because `Storage::TYPE` is a const on a generic
// associated type that can't be named at registry-definition time —
// the derive captures the monomorphized path in the fn body.
/// Per-concrete Storage-type entry registered by `#[derive(bb::<Role>)]`.
///
/// Keyed on the triple `(concrete_type_name, role_runtime, port)`.
/// `type_node_fn` returns the `Storage::TYPE` static for the
/// concrete's associated type at that port.
collect!;
/// Iterate every registered Storage-type entry in this binary.
/// Look up the `TypeNode` for a specific `(concrete_type_name, role_runtime, port)` triple.
///
/// Returns `None` when no matching entry exists in the binary's
/// inventory (e.g. the concrete's role derive is absent or the port
/// name is wrong).