vyre_driver/registry/dialect.rs
1//! Frozen dialect + op registration surface.
2//!
3//! **Single registration path.** Every op known to any vyre backend is
4//! registered exactly once by submitting an [`OpDefRegistration`] via
5//! `inventory::submit!`. There is no legacy registry shim, no parallel macro-generated
6//! catalog, no alternative discovery mechanism. If an op isn't in the
7//! `DialectRegistry` it doesn't exist; the wire decoder returns
8//! [`vyre_foundation::error::Error::UnknownOp`] for it.
9//!
10//! Dialects register themselves via [`DialectRegistration`]. The per-op
11//! [`OpBackendTarget`] rows are a pure metadata index so the coverage
12//! matrix can answer "does this op have a primary-text path declared" without
13//! loading every backend's lowering table.
14//!
15//! Extension crates adding new ops do not edit this module. They submit
16//! their own `OpDefRegistration` from their own `inventory::submit!` macro
17//! call at link time. Vision doc ยง2 (Open hierarchies) enforces this.
18
19use super::op_def::OpDef;
20
21/// Metadata for a versioned dialect of ops (e.g. `pattern`, `crypto`).
22pub struct Dialect {
23 /// Stable dialect id (e.g. `"primitive"`, `"hash"`).
24 pub id: &'static str,
25 /// Dialect schema version.
26 pub version: u32,
27 /// Optional parent dialect this one extends.
28 pub parent: Option<&'static str>,
29 /// Op ids this dialect publishes.
30 pub ops: &'static [&'static str],
31 /// Pass/fail predicate run at registration time.
32 pub validator: fn() -> bool,
33 /// Backends this dialect requires for conformance claims.
34 pub backends_required: &'static [vyre_spec::Backend],
35}
36
37/// Default `Dialect::validator` that always succeeds.
38pub fn default_validator() -> bool {
39 true
40}
41
42/// Advertises that a named backend target publishes a lowering for a
43/// specific op. This is distinct from [`crate::backend::BackendRegistration`]
44/// (which registers a full `VyreBackend` implementation): it is a compact
45/// (op, target) pair used by the coverage-matrix introspection path to list
46/// "this op has a concrete lowering path declared".
47pub struct OpBackendTarget {
48 /// Op id (e.g. `primitive.math.add`).
49 pub op: &'static str,
50 /// Backend-target id.
51 pub target: &'static str,
52}
53
54/// **The single op registration path.**
55///
56/// Every op a vyre backend can execute is published by submitting one of
57/// these through `inventory::submit!` at link time. The closure is called
58/// once during registry freeze to build the stable [`OpDef`] record.
59pub struct OpDefRegistration {
60 /// Factory returning the op's frozen [`OpDef`].
61 pub op: fn() -> OpDef,
62}
63
64impl OpDefRegistration {
65 /// Construct a registration from an op-factory function.
66 pub const fn new(op: fn() -> OpDef) -> Self {
67 Self { op }
68 }
69}
70
71/// Register a dialect (op id namespace + version) via `inventory::submit!`.
72pub struct DialectRegistration {
73 /// Factory returning the dialect's frozen record.
74 pub dialect: fn() -> Dialect,
75}
76
77inventory::collect!(OpDefRegistration);
78inventory::collect!(DialectRegistration);
79inventory::collect!(OpBackendTarget);