reactor_rt/
assembly.rs

1//! Module containing the API to initialize a reactor program.
2
3use AssemblyErrorImpl::*;
4
5pub use crate::ids::GlobalReactionId;
6// this is where most of the stuff is implemented
7pub use crate::scheduler::assembly_impl::*;
8pub use crate::triggers::{TriggerId, TriggerLike};
9use crate::{DebugInfoRegistry, LocalReactionId, ReactorBehavior};
10pub(crate) type PortId = TriggerId;
11
12/// Wrapper around the user struct for safe dispatch.
13///
14/// Fields are
15/// 1. the user struct,
16/// 2. ctor parameters of the reactor, and
17/// 3. every logical action and port declared by the reactor.
18///
19pub trait ReactorInitializer: ReactorBehavior {
20    /// Type of the user struct, which contains state variables of the reactor.
21    /// Used by the runtime to produce debug information.
22    type Wrapped;
23    /// Type of the construction parameters.
24    type Params;
25    /// Exclusive maximum value of the `local_rid` parameter of [ReactorBehavior.react].
26    const MAX_REACTION_ID: LocalReactionId;
27
28    /// Assemble this reactor. This initializes state variables,
29    /// produces internal components, assembles children reactor
30    /// instances, and declares dependencies between them.
31    fn assemble(args: Self::Params, assembler: AssemblyCtx<Self>) -> AssemblyResult<FinishedReactor<Self>>
32    where
33        Self: Sized;
34}
35
36pub type AssemblyResult<T = ()> = Result<T, AssemblyError>;
37
38/// An error occurring during initialization of the reactor program.
39/// Should never occur unless the graph is built by hand, and not
40/// by a Lingua Franca compiler.
41pub struct AssemblyError(pub(crate) AssemblyErrorImpl);
42
43impl AssemblyError {
44    pub(crate) fn lift(self, debug: &DebugInfoRegistry) -> String {
45        self.display(debug)
46    }
47}
48
49pub(crate) enum AssemblyErrorImpl {
50    CyclicDependency(PortId, PortId),
51    CyclicDependencyGraph,
52    CannotBind(PortId, PortId),
53    IdOverflow,
54}
55
56impl AssemblyError {
57    fn display(&self, debug: &DebugInfoRegistry) -> String {
58        match self.0 {
59            CyclicDependency(upstream, downstream) => format!(
60                "Port {} is already in the downstream of port {}",
61                debug.fmt_component(upstream),
62                debug.fmt_component(downstream)
63            ),
64            CyclicDependencyGraph => "Cyclic dependency graph".to_string(),
65            CannotBind(upstream, downstream) => format!(
66                "Cannot bind {} to {}, downstream is already bound",
67                debug.fmt_component(upstream),
68                debug.fmt_component(downstream)
69            ),
70            IdOverflow => "Overflow when allocating component ID".to_string(),
71        }
72    }
73}
74
75/// Kind of a port.
76#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
77pub enum PortKind {
78    Input,
79    Output,
80    ChildInputReference,
81    ChildOutputReference,
82}