Skip to main content

bb_ir/types/
builtins.rs

1//! Built-in `TypeNode` constants the framework + DSL ship out of
2//! the box.
3//!
4//! Every framework primitive's type is listed here and submitted to
5//! the inventory so the [`super::Lattice`] picks it up at startup.
6//! Custom application or library types follow the same pattern from
7//! any downstream crate.
8
9use super::{TypeKind, TypeNode, TypeNodeReg};
10
11// ---- Root --------------------------------------------------------
12
13/// The universal supertype. Every other type is a (transitive)
14/// subtype of `Any`. Used as a port bound when no narrower
15/// constraint applies.
16pub static TYPE_ANY: TypeNode = TypeNode {
17    id: "any",
18    parent: None,
19    kind: TypeKind::Abstract,
20    ffi_name: "",
21    wire_hash: 0,
22    denotation: "",
23};
24
25// ---- Tensor branch -----------------------------------------------
26
27/// Abstract `Tensor` - matches any `Tensor<T>` concrete leaf.
28pub static TYPE_TENSOR: TypeNode = TypeNode {
29    id: "tensor",
30    parent: Some("any"),
31    kind: TypeKind::Abstract,
32    ffi_name: "",
33    wire_hash: 0,
34    denotation: "",
35};
36
37/// Concrete `Tensor<F32>` - dense f32 tensor.
38pub static TYPE_TENSOR_F32: TypeNode = TypeNode {
39    id: "tensor.f32",
40    parent: Some("tensor"),
41    kind: TypeKind::Concrete,
42    ffi_name: "bb_tensor_f32_t",
43    wire_hash: 0x0000_0000_0000_0101,
44    denotation: "ai.bytesandbrains.tensor.f32",
45};
46
47/// Concrete `Tensor<F64>` - dense f64 tensor.
48pub static TYPE_TENSOR_F64: TypeNode = TypeNode {
49    id: "tensor.f64",
50    parent: Some("tensor"),
51    kind: TypeKind::Concrete,
52    ffi_name: "bb_tensor_f64_t",
53    wire_hash: 0x0000_0000_0000_0102,
54    denotation: "ai.bytesandbrains.tensor.f64",
55};
56
57/// Concrete `Tensor<F16>` - dense f16 tensor.
58pub static TYPE_TENSOR_F16: TypeNode = TypeNode {
59    id: "tensor.f16",
60    parent: Some("tensor"),
61    kind: TypeKind::Concrete,
62    ffi_name: "bb_tensor_f16_t",
63    wire_hash: 0x0000_0000_0000_0103,
64    denotation: "ai.bytesandbrains.tensor.f16",
65};
66
67/// Concrete `Tensor<U8>` - dense u8 tensor.
68pub static TYPE_TENSOR_U8: TypeNode = TypeNode {
69    id: "tensor.u8",
70    parent: Some("tensor"),
71    kind: TypeKind::Concrete,
72    ffi_name: "bb_tensor_u8_t",
73    wire_hash: 0x0000_0000_0000_0104,
74    denotation: "ai.bytesandbrains.tensor.u8",
75};
76
77/// Concrete `Tensor<I32>` - dense i32 tensor.
78pub static TYPE_TENSOR_I32: TypeNode = TypeNode {
79    id: "tensor.i32",
80    parent: Some("tensor"),
81    kind: TypeKind::Concrete,
82    ffi_name: "bb_tensor_i32_t",
83    wire_hash: 0x0000_0000_0000_0105,
84    denotation: "ai.bytesandbrains.tensor.i32",
85};
86
87/// Concrete `Tensor<Bool>` - dense bool tensor. Masks, predicates,
88/// comparison-op results.
89pub static TYPE_TENSOR_BOOL: TypeNode = TypeNode {
90    id: "tensor.bool",
91    parent: Some("tensor"),
92    kind: TypeKind::Concrete,
93    ffi_name: "bb_tensor_bool_t",
94    wire_hash: 0x0000_0000_0000_0106,
95    denotation: "ai.bytesandbrains.tensor.bool",
96};
97
98/// Concrete `Tensor<BF16>` - dense bfloat16 tensor. Modern ML
99/// mixed-precision standard. Stored as `half::bf16` (binary newtype
100/// around the 16-bit bfloat bit pattern).
101pub static TYPE_TENSOR_BF16: TypeNode = TypeNode {
102    id: "tensor.bf16",
103    parent: Some("tensor"),
104    kind: TypeKind::Concrete,
105    ffi_name: "bb_tensor_bf16_t",
106    wire_hash: 0x0000_0000_0000_0107,
107    denotation: "ai.bytesandbrains.tensor.bf16",
108};
109
110/// Concrete `Tensor<I8>` - dense i8 tensor. Edge quantization (the
111/// positional reason this is shipping as a v1 type, not a future
112/// feature: edge ML without int8 isn't really edge ML).
113pub static TYPE_TENSOR_I8: TypeNode = TypeNode {
114    id: "tensor.i8",
115    parent: Some("tensor"),
116    kind: TypeKind::Concrete,
117    ffi_name: "bb_tensor_i8_t",
118    wire_hash: 0x0000_0000_0000_0108,
119    denotation: "ai.bytesandbrains.tensor.i8",
120};
121
122/// Concrete `Tensor<I16>` - dense i16 tensor. Wider-than-byte
123/// quantization slots, audio samples.
124pub static TYPE_TENSOR_I16: TypeNode = TypeNode {
125    id: "tensor.i16",
126    parent: Some("tensor"),
127    kind: TypeKind::Concrete,
128    ffi_name: "bb_tensor_i16_t",
129    wire_hash: 0x0000_0000_0000_0109,
130    denotation: "ai.bytesandbrains.tensor.i16",
131};
132
133/// Concrete `Tensor<I64>` - dense i64 tensor. Index / embedding
134/// lookups (the canonical 'Int' kind default for most Burn
135/// underlying backends).
136pub static TYPE_TENSOR_I64: TypeNode = TypeNode {
137    id: "tensor.i64",
138    parent: Some("tensor"),
139    kind: TypeKind::Concrete,
140    ffi_name: "bb_tensor_i64_t",
141    wire_hash: 0x0000_0000_0000_010A,
142    denotation: "ai.bytesandbrains.tensor.i64",
143};
144
145/// Concrete `Tensor<U16>` - dense u16 tensor. Image bit-depth, count
146/// types.
147pub static TYPE_TENSOR_U16: TypeNode = TypeNode {
148    id: "tensor.u16",
149    parent: Some("tensor"),
150    kind: TypeKind::Concrete,
151    ffi_name: "bb_tensor_u16_t",
152    wire_hash: 0x0000_0000_0000_010B,
153    denotation: "ai.bytesandbrains.tensor.u16",
154};
155
156/// Concrete `Tensor<U32>` - dense u32 tensor. Hash buckets, large
157/// counts.
158pub static TYPE_TENSOR_U32: TypeNode = TypeNode {
159    id: "tensor.u32",
160    parent: Some("tensor"),
161    kind: TypeKind::Concrete,
162    ffi_name: "bb_tensor_u32_t",
163    wire_hash: 0x0000_0000_0000_010C,
164    denotation: "ai.bytesandbrains.tensor.u32",
165};
166
167/// Concrete `Tensor<U64>` - dense u64 tensor. Wide indices, IDs.
168pub static TYPE_TENSOR_U64: TypeNode = TypeNode {
169    id: "tensor.u64",
170    parent: Some("tensor"),
171    kind: TypeKind::Concrete,
172    ffi_name: "bb_tensor_u64_t",
173    wire_hash: 0x0000_0000_0000_010D,
174    denotation: "ai.bytesandbrains.tensor.u64",
175};
176
177// ---- Scalar branch -----------------------------------------------
178
179/// Abstract `Scalar` - matches any `Scalar<T>` concrete leaf.
180pub static TYPE_SCALAR: TypeNode = TypeNode {
181    id: "scalar",
182    parent: Some("any"),
183    kind: TypeKind::Abstract,
184    ffi_name: "",
185    wire_hash: 0,
186    denotation: "",
187};
188
189/// Concrete `Scalar<F32>` - single f32 value.
190pub static TYPE_SCALAR_F32: TypeNode = TypeNode {
191    id: "scalar.f32",
192    parent: Some("scalar"),
193    kind: TypeKind::Concrete,
194    ffi_name: "bb_f32_t",
195    wire_hash: 0x0000_0000_0000_0201,
196    denotation: "bb.f32",
197};
198
199/// Concrete `Scalar<F64>` - single f64 value.
200pub static TYPE_SCALAR_F64: TypeNode = TypeNode {
201    id: "scalar.f64",
202    parent: Some("scalar"),
203    kind: TypeKind::Concrete,
204    ffi_name: "bb_f64_t",
205    wire_hash: 0x0000_0000_0000_0202,
206    denotation: "bb.f64",
207};
208
209/// Concrete `Scalar<F16>` - single f16 value.
210pub static TYPE_SCALAR_F16: TypeNode = TypeNode {
211    id: "scalar.f16",
212    parent: Some("scalar"),
213    kind: TypeKind::Concrete,
214    ffi_name: "bb_f16_t",
215    wire_hash: 0x0000_0000_0000_0203,
216    denotation: "bb.f16",
217};
218
219/// Concrete `Scalar<U8>` - single u8 value.
220pub static TYPE_SCALAR_U8: TypeNode = TypeNode {
221    id: "scalar.u8",
222    parent: Some("scalar"),
223    kind: TypeKind::Concrete,
224    ffi_name: "bb_u8_t",
225    wire_hash: 0x0000_0000_0000_0204,
226    denotation: "bb.u8",
227};
228
229/// Concrete `Scalar<I32>` - single i32 value.
230pub static TYPE_SCALAR_I32: TypeNode = TypeNode {
231    id: "scalar.i32",
232    parent: Some("scalar"),
233    kind: TypeKind::Concrete,
234    ffi_name: "bb_i32_t",
235    wire_hash: 0x0000_0000_0000_0205,
236    denotation: "bb.i32",
237};
238
239// ---- Peer + framework primitives ---------------------------------
240
241/// Concrete `PeerId` - canonical peer identifier (multihash).
242pub static TYPE_PEER_ID: TypeNode = TypeNode {
243    id: "peer_id",
244    parent: Some("any"),
245    kind: TypeKind::Concrete,
246    ffi_name: "bb_peer_id_t",
247    wire_hash: 0x0000_0000_0000_0010,
248    denotation: "bb.peer_id",
249};
250
251/// Concrete `Vec<PeerId>` - fan-out destination list for `g.net_out`.
252pub static TYPE_PEER_ID_VEC: TypeNode = TypeNode {
253    id: "peer_id_vec",
254    parent: Some("any"),
255    kind: TypeKind::Concrete,
256    ffi_name: "bb_peer_id_vec_t",
257    wire_hash: 0x0000_0000_0000_0012,
258    denotation: "bb.peer_id_vec",
259};
260
261/// Concrete `Trigger` - zero-payload signal value.
262pub static TYPE_TRIGGER: TypeNode = TypeNode {
263    id: "trigger",
264    parent: Some("any"),
265    kind: TypeKind::Concrete,
266    ffi_name: "bb_trigger_t",
267    wire_hash: 0x0000_0000_0000_000A,
268    denotation: "bb.trigger",
269};
270
271/// Concrete `Bytes` - opaque byte buffer.
272pub static TYPE_BYTES: TypeNode = TypeNode {
273    id: "bytes",
274    parent: Some("any"),
275    kind: TypeKind::Concrete,
276    ffi_name: "bb_bytes_t",
277    wire_hash: 0x0000_0000_0000_000B,
278    denotation: "ai.bytesandbrains.opaque",
279};
280
281/// Concrete `WireReqId` - correlation token returned by `g.net_out`.
282pub static TYPE_WIRE_REQ_ID: TypeNode = TypeNode {
283    id: "wire_req_id",
284    parent: Some("any"),
285    kind: TypeKind::Concrete,
286    ffi_name: "bb_wire_req_id_t",
287    wire_hash: 0x0000_0000_0000_0011,
288    denotation: "bb.wire_req_id",
289};
290
291/// Concrete `Multiaddress` - sequence of typed protocol segments
292/// describing a delivery path. The framework's canonical address
293/// type; binds to `framework::Address` in `bb-runtime`. Lives
294/// directly under `Any` (no abstract address parent — there is no
295/// second address-shaped concrete). The 0x03xx wire-hash range is
296/// reserved for address-related leaves.
297pub static TYPE_MULTIADDRESS: TypeNode = TypeNode {
298    id: "multiaddress",
299    parent: Some("any"),
300    kind: TypeKind::Concrete,
301    ffi_name: "bb_multiaddress_t",
302    wire_hash: 0x0000_0000_0000_0301,
303    denotation: "ai.bytesandbrains.multiaddress",
304};
305
306/// Concrete `Vec<Address>` - the ordered local-or-peer address list
307/// stamped on every `wire.Send` envelope, the carrier for the local
308/// address bag installed by `bb::install`, and the payload shape for
309/// the multi-address `AddressBook` syscalls. Distinct wire hash from
310/// `TYPE_MULTIADDRESS` so receivers can disambiguate single vs many.
311pub static TYPE_ADDRESS_VEC: TypeNode = TypeNode {
312    id: "address_vec",
313    parent: Some("any"),
314    kind: TypeKind::Concrete,
315    ffi_name: "bb_address_vec_t",
316    wire_hash: 0x0000_0000_0000_0303,
317    denotation: "ai.bytesandbrains.address_vec",
318};
319
320/// Concrete `Composite` - envelope holding N typed child payloads,
321/// each tagged with its source `type_hash` and bincode-encoded bytes.
322/// The DSL `g.bundle` recorder produces this on the output of a
323/// `Bundle` op; the matching `Unbundle` op decomposes it back into
324/// per-child `BytesValue` outputs whose `ValueInfoProto.denotation`
325/// is stamped from the declared child-type list. Parent is `Any`
326/// because a composite can wrap any wire-eligible child types.
327pub static TYPE_COMPOSITE: TypeNode = TypeNode {
328    id: "composite",
329    parent: Some("any"),
330    kind: TypeKind::Concrete,
331    ffi_name: "bb_composite_t",
332    wire_hash: 0x0000_0000_0000_0302,
333    denotation: "ai.bytesandbrains.composite",
334};
335
336// ---- Inventory submissions ---------------------------------------
337//
338// Every built-in type registers itself so `lookup_by_id` and the
339// `Lattice` see them at startup. Custom types follow the same
340// pattern from any downstream crate.
341
342inventory::submit! { TypeNodeReg(&TYPE_ANY) }
343inventory::submit! { TypeNodeReg(&TYPE_TENSOR) }
344inventory::submit! { TypeNodeReg(&TYPE_TENSOR_F32) }
345inventory::submit! { TypeNodeReg(&TYPE_TENSOR_F64) }
346inventory::submit! { TypeNodeReg(&TYPE_TENSOR_F16) }
347inventory::submit! { TypeNodeReg(&TYPE_TENSOR_U8) }
348inventory::submit! { TypeNodeReg(&TYPE_TENSOR_I32) }
349inventory::submit! { TypeNodeReg(&TYPE_TENSOR_BOOL) }
350inventory::submit! { TypeNodeReg(&TYPE_TENSOR_BF16) }
351inventory::submit! { TypeNodeReg(&TYPE_TENSOR_I8) }
352inventory::submit! { TypeNodeReg(&TYPE_TENSOR_I16) }
353inventory::submit! { TypeNodeReg(&TYPE_TENSOR_I64) }
354inventory::submit! { TypeNodeReg(&TYPE_TENSOR_U16) }
355inventory::submit! { TypeNodeReg(&TYPE_TENSOR_U32) }
356inventory::submit! { TypeNodeReg(&TYPE_TENSOR_U64) }
357inventory::submit! { TypeNodeReg(&TYPE_SCALAR) }
358inventory::submit! { TypeNodeReg(&TYPE_SCALAR_F32) }
359inventory::submit! { TypeNodeReg(&TYPE_SCALAR_F64) }
360inventory::submit! { TypeNodeReg(&TYPE_SCALAR_F16) }
361inventory::submit! { TypeNodeReg(&TYPE_SCALAR_U8) }
362inventory::submit! { TypeNodeReg(&TYPE_SCALAR_I32) }
363inventory::submit! { TypeNodeReg(&TYPE_PEER_ID) }
364inventory::submit! { TypeNodeReg(&TYPE_PEER_ID_VEC) }
365inventory::submit! { TypeNodeReg(&TYPE_TRIGGER) }
366inventory::submit! { TypeNodeReg(&TYPE_BYTES) }
367inventory::submit! { TypeNodeReg(&TYPE_WIRE_REQ_ID) }
368inventory::submit! { TypeNodeReg(&TYPE_MULTIADDRESS) }
369inventory::submit! { TypeNodeReg(&TYPE_ADDRESS_VEC) }
370inventory::submit! { TypeNodeReg(&TYPE_COMPOSITE) }
371
372// ---- Inverse lookup (denotation → TypeNode) ----------------------
373
374/// Map a canonical denotation string to the corresponding
375/// [`TypeNode`] static. Returns `None` for denotations the framework
376/// doesn't recognize; the solver leaves those values at
377/// [`TYPE_ANY`] (custom types can declare their own
378/// `type_relations` to seed concrete types).
379pub fn lookup_denotation(denotation: &str) -> Option<&'static TypeNode> {
380    match denotation {
381        // Tensors (bb-ir::wire `TypeNode` canonical strings).
382        "ai.bytesandbrains.tensor.f32" => Some(&TYPE_TENSOR_F32),
383        "ai.bytesandbrains.tensor.f64" => Some(&TYPE_TENSOR_F64),
384        "ai.bytesandbrains.tensor.f16" => Some(&TYPE_TENSOR_F16),
385        "ai.bytesandbrains.tensor.u8" => Some(&TYPE_TENSOR_U8),
386        "ai.bytesandbrains.tensor.i32" => Some(&TYPE_TENSOR_I32),
387        "ai.bytesandbrains.tensor.bool" => Some(&TYPE_TENSOR_BOOL),
388        "ai.bytesandbrains.tensor.bf16" => Some(&TYPE_TENSOR_BF16),
389        "ai.bytesandbrains.tensor.i8" => Some(&TYPE_TENSOR_I8),
390        "ai.bytesandbrains.tensor.i16" => Some(&TYPE_TENSOR_I16),
391        "ai.bytesandbrains.tensor.i64" => Some(&TYPE_TENSOR_I64),
392        "ai.bytesandbrains.tensor.u16" => Some(&TYPE_TENSOR_U16),
393        "ai.bytesandbrains.tensor.u32" => Some(&TYPE_TENSOR_U32),
394        "ai.bytesandbrains.tensor.u64" => Some(&TYPE_TENSOR_U64),
395
396        // Scalars.
397        "bb.f32" => Some(&TYPE_SCALAR_F32),
398        "bb.f64" => Some(&TYPE_SCALAR_F64),
399        "bb.f16" => Some(&TYPE_SCALAR_F16),
400        "bb.u8" => Some(&TYPE_SCALAR_U8),
401        "bb.i32" => Some(&TYPE_SCALAR_I32),
402
403        // Framework primitives.
404        "bb.peer_id" => Some(&TYPE_PEER_ID),
405        "bb.peer_id_vec" => Some(&TYPE_PEER_ID_VEC),
406        "bb.trigger" => Some(&TYPE_TRIGGER),
407        "bb.wire_req_id" => Some(&TYPE_WIRE_REQ_ID),
408        "ai.bytesandbrains.multiaddress" => Some(&TYPE_MULTIADDRESS),
409        "ai.bytesandbrains.address_vec" => Some(&TYPE_ADDRESS_VEC),
410        "ai.bytesandbrains.composite" => Some(&TYPE_COMPOSITE),
411
412        // Opaque placeholder — the recording-time signal that the
413        // type is a raw byte payload (no further structure beyond
414        // bytes-on-the-wire). Maps to the concrete `bytes` leaf so
415        // strict-types-by-default accepts it.
416        "ai.bytesandbrains.opaque" => Some(&TYPE_BYTES),
417
418        _ => None,
419    }
420}