wowlab_engine_domain/rotation/
engine.rs1use wowlab_types::sim::Rotation;
4
5#[cfg(feature = "jit")]
6use super::compiler::CompiledRotation;
7use super::{
8 backend::RuntimeBackend, buffer::DenseBuffer, context::ContextSchema,
9 decision_trace::DecisionTraceTarget, error::Result, interpreter::InterpretedRotation,
10 resolver::SpecResolver, result::EvalResult,
11};
12
13#[non_exhaustive]
15pub enum RotationEngine {
16 #[cfg(feature = "jit")]
17 Jit(Box<CompiledRotation>),
18 Interpreted(Box<InterpretedRotation>),
19}
20
21impl RotationEngine {
22 pub fn compile(rotation: &Rotation, resolver: &SpecResolver) -> Result<Self> {
27 if !rotation.is_empty() {
28 super::ast::validate(rotation)?;
29 }
30
31 Self::compile_ast(rotation, resolver)
32 }
33
34 pub fn compile_json(json: &str, resolver: &SpecResolver) -> Result<Self> {
39 let rotation = super::ast::parse_and_validate(json)?;
40
41 Self::compile(&rotation, resolver)
42 }
43
44 pub fn compile_empty(resolver: &SpecResolver) -> Result<Self> {
49 let rotation = Rotation::empty();
50
51 Self::compile_ast(&rotation, resolver)
52 }
53
54 #[cfg(feature = "jit")]
59 pub fn compile_jit(json: &str, resolver: &SpecResolver) -> Result<Self> {
60 Ok(Self::Jit(Box::new(CompiledRotation::compile_json(
61 json, resolver,
62 )?)))
63 }
64
65 pub fn compile_interpreted(json: &str, resolver: &SpecResolver) -> Result<Self> {
70 Ok(Self::Interpreted(Box::new(
71 InterpretedRotation::compile_json(json, resolver)?,
72 )))
73 }
74
75 #[must_use]
77 pub fn with_decision_trace(mut self, sink: DecisionTraceTarget) -> Self {
78 self.set_decision_trace(sink);
79
80 self
81 }
82
83 #[must_use]
85 pub fn has_decision_trace(&self) -> bool {
86 match self {
87 #[cfg(feature = "jit")]
88 Self::Jit(_) => false,
89 Self::Interpreted(r) => r.has_sink(),
90 }
91 }
92
93 pub fn set_decision_trace(&mut self, sink: DecisionTraceTarget) {
95 match self {
96 #[cfg(feature = "jit")]
97 Self::Jit(jit) => {
98 let interp = InterpretedRotation::from_parts(
100 jit.rotation.clone(),
101 jit.resolver.clone(),
102 jit.schema().clone(),
103 );
104 let mut boxed = Box::new(interp);
105
106 boxed.set_sink(sink);
107 *self = Self::Interpreted(boxed);
108 }
109 Self::Interpreted(r) => {
110 r.set_sink(sink);
111 }
112 }
113 }
114
115 fn compile_ast(rotation: &Rotation, resolver: &SpecResolver) -> Result<Self> {
116 #[cfg(feature = "jit")]
117 {
118 Ok(Self::Jit(Box::new(CompiledRotation::compile(
119 rotation, resolver,
120 )?)))
121 }
122
123 #[cfg(not(feature = "jit"))]
124 {
125 Ok(Self::Interpreted(Box::new(InterpretedRotation::compile(
126 rotation, resolver,
127 )?)))
128 }
129 }
130}
131
132impl std::fmt::Debug for RotationEngine {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 match self {
135 #[cfg(feature = "jit")]
136 Self::Jit(_) => f.debug_tuple("Jit").finish(),
137 Self::Interpreted(r) => f
138 .debug_struct("Interpreted")
139 .field("has_sink", &r.has_sink())
140 .finish(),
141 }
142 }
143}
144
145impl RuntimeBackend for RotationEngine {
146 fn evaluate(&mut self, buffer: &mut DenseBuffer, now_secs: f64) -> EvalResult {
147 match self {
148 #[cfg(feature = "jit")]
149 Self::Jit(r) => r.evaluate(buffer, now_secs),
150 Self::Interpreted(r) => r.evaluate(buffer, now_secs),
151 }
152 }
153
154 fn schema(&self) -> &ContextSchema {
155 match self {
156 #[cfg(feature = "jit")]
157 Self::Jit(r) => r.schema(),
158 Self::Interpreted(r) => r.schema(),
159 }
160 }
161}