Skip to main content

tenferro_runtime/program/
mod.rs

1//! Immutable backend-neutral semantic programs.
2//!
3//! Semantic structure freezes separately from tensor defaults and large
4//! constants. Builder-issued values and binding keys are opaque and scoped to
5//! one builder/program.
6//!
7//! # Build, bind, freeze, query, and import
8//!
9//! ```
10//! use std::sync::Arc;
11//! use tenferro_ops::dim_expr::DimExpr;
12//! use tenferro_runtime::program::{
13//!     CoreSemanticOp, ProgramInputSpec, ProgramQueryError, ProgramImport,
14//!     SemanticProgramBuilder,
15//! };
16//! use tenferro_tensor::{DType, Tensor};
17//!
18//! let mut builder = SemanticProgramBuilder::new();
19//! let input = builder.input(ProgramInputSpec::new(
20//!     DType::F64,
21//!     [DimExpr::Const(2)],
22//! ))?;
23//! let key = builder.bind_input(
24//!     input,
25//!     Arc::new(Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0])?),
26//! )?;
27//! let output = builder.add_op(CoreSemanticOp::Neg, &[input])?[0];
28//! let frozen = builder.finish(&[output])?;
29//! assert_eq!(frozen.bindings.iter().count(), 1);
30//! assert!(frozen.bindings.get(key).is_some());
31//! assert_eq!(frozen.program.semantic_fingerprint().as_bytes().len(), 16);
32//!
33//! let mut other = SemanticProgramBuilder::new();
34//! let foreign = other.input(ProgramInputSpec::new(
35//!     DType::F64,
36//!     [DimExpr::Const(2)],
37//! ))?;
38//! assert_eq!(
39//!     frozen.program.value_metadata(foreign),
40//!     Err(ProgramQueryError::ForeignValue),
41//! );
42//!
43//! let mut destination = SemanticProgramBuilder::new();
44//! let imported = destination.import(ProgramImport {
45//!     program: frozen.program.as_ref(),
46//!     bindings: &frozen.bindings,
47//!     roots: frozen.program.outputs(),
48//! })?;
49//! let roundtrip = destination.finish(imported.roots())?;
50//! assert!(frozen.program.semantic_eq(roundtrip.program.as_ref()));
51//! assert_eq!(roundtrip.bindings.len(), 1);
52//! # Ok::<(), Box<dyn std::error::Error>>(())
53//! ```
54//!
55//! # Opaque identities
56//!
57//! Raw slots and builder nonces are deliberately inaccessible.
58//!
59//! ```compile_fail
60//! use tenferro_runtime::program::ProgramValue;
61//! fn raw_slot(value: ProgramValue) -> u32 {
62//!     value.slot
63//! }
64//! ```
65//!
66//! ```compile_fail
67//! use tenferro_runtime::program::BindingKey;
68//! fn raw_slot(key: BindingKey) -> u32 {
69//!     key.slot
70//! }
71//! ```
72//!
73//! Frozen operation views expose immutable slices only.
74//!
75//! ```compile_fail
76//! use tenferro_runtime::program::SemanticOperationView;
77//! fn mutate(view: SemanticOperationView<'_>) {
78//!     view.outputs()[0] = view.inputs()[0];
79//! }
80//! ```
81//!
82//! Structured control flow is a typed unsupported case until the reserved
83//! region/block model is implemented.
84//!
85//! ```
86//! use tenferro_runtime::program::ProgramBuildError;
87//! let error = ProgramBuildError::UnsupportedControlFlow { construct: "while" };
88//! assert!(matches!(
89//!     error,
90//!     ProgramBuildError::UnsupportedControlFlow { construct: "while" }
91//! ));
92//! ```
93
94mod bindings;
95mod builder;
96mod error;
97mod identity;
98mod import;
99mod metadata;
100mod op;
101mod semantic;
102mod transform;
103mod value;
104
105pub use bindings::ProgramBindings;
106pub use builder::SemanticProgramBuilder;
107pub use error::{
108    EffectResourceError, ProgramBindingError, ProgramBuildError, ProgramFinishError,
109    ProgramQueryError, ProgramStructuralError, SemanticTransformError,
110};
111pub use identity::SemanticFingerprint;
112pub use import::{ImportedProgramValues, ProgramImport};
113pub use metadata::{
114    Alias, AliasKind, Effect, EffectAccess, EffectResource, ProgramInputSpec, ProgramShapeRelation,
115    ProgramValueMetadata, SemanticPlacementConstraint, SemanticPlacementKind,
116    SemanticProvenanceKind, SemanticProvenanceView, ShapeGuard,
117};
118pub use op::{CoreSemanticOp, CoreSemanticOpConversionError, SemanticOpRef, SemanticOperationView};
119pub use semantic::{FrozenProgram, SemanticProgram};
120pub use transform::{SemanticTransform, SemanticTransformContext, TransformIdentity};
121pub use value::{BindingKey, ProgramValue};
122
123#[cfg(test)]
124mod tests;