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//!     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: Some(&frozen.bindings),
47//!     roots: frozen.program.outputs(),
48//!     input_map: &[],
49//! })?;
50//! let roundtrip = destination.finish(imported.roots())?;
51//! assert!(frozen.program.semantic_eq(roundtrip.program.as_ref()));
52//! assert_eq!(roundtrip.bindings.len(), 1);
53//! # Ok::<(), Box<dyn std::error::Error>>(())
54//! ```
55//!
56//! # Opaque identities
57//!
58//! Raw slots and builder nonces are deliberately inaccessible.
59//!
60//! ```compile_fail
61//! use tenferro_runtime::program::ProgramValue;
62//! fn raw_slot(value: ProgramValue) -> u32 {
63//!     value.slot
64//! }
65//! ```
66//!
67//! ```compile_fail
68//! use tenferro_runtime::program::BindingKey;
69//! fn raw_slot(key: BindingKey) -> u32 {
70//!     key.slot
71//! }
72//! ```
73//!
74//! Frozen operation views expose immutable slices only.
75//!
76//! ```compile_fail
77//! use tenferro_runtime::program::SemanticOperationView;
78//! fn mutate(view: SemanticOperationView<'_>) {
79//!     view.outputs()[0] = view.inputs()[0];
80//! }
81//! ```
82//!
83//! Structured control flow is a typed unsupported case until the reserved
84//! region/block model is implemented.
85//!
86//! ```
87//! use tenferro_runtime::program::ProgramBuildError;
88//! let error = ProgramBuildError::UnsupportedControlFlow { construct: "while" };
89//! assert!(matches!(
90//!     error,
91//!     ProgramBuildError::UnsupportedControlFlow { construct: "while" }
92//! ));
93//! ```
94
95mod bindings;
96mod builder;
97mod error;
98mod identity;
99mod import;
100mod metadata;
101mod op;
102mod semantic;
103mod transform;
104mod value;
105
106pub use bindings::ProgramBindings;
107pub use builder::SemanticProgramBuilder;
108pub use error::{
109    EffectResourceError, ProgramBindingError, ProgramBuildError, ProgramFinishError,
110    ProgramQueryError, ProgramStructuralError, SemanticTransformError,
111};
112pub use identity::SemanticFingerprint;
113pub use import::{ImportedProgramValues, ProgramImport};
114pub use metadata::{
115    Alias, AliasKind, Effect, EffectAccess, EffectResource, ProgramInputSpec, ProgramShapeRelation,
116    ProgramValueMetadata, SemanticPlacementConstraint, SemanticPlacementKind,
117    SemanticProvenanceKind, SemanticProvenanceView, ShapeGuard,
118};
119pub use op::{CoreSemanticOp, CoreSemanticOpConversionError, SemanticOpRef, SemanticOperationView};
120pub use semantic::{FrozenProgram, SemanticProgram};
121pub use transform::{SemanticTransform, SemanticTransformContext, TransformIdentity};
122pub use value::{BindingKey, ProgramValue};
123
124#[cfg(test)]
125mod tests;