wowlab_engine_domain/rotation/
engine.rs1use wowlab_types::sim::Rotation;
4
5#[cfg(feature = "jit")]
6use super::compiler::CompiledRotation;
7use super::{
8 backend::RuntimeBackend,
9 buffer::{BufferRequirements, DenseBuffer},
10 bytecode::PortableRotation,
11 context::ContextSchema,
12 decision_trace::DecisionTraceTarget,
13 error::Result,
14 prepared::{PreparedRotation, RotationPreparation},
15 resolver::SpecResolver,
16 result::EvalResult,
17};
18
19#[non_exhaustive]
21pub enum RotationEngine {
22 Portable(Box<PortableRotation>),
23 #[cfg(feature = "jit")]
24 Jit(Box<CompiledRotation>),
25}
26
27impl RotationEngine {
28 #[must_use]
30 pub fn portable(prepared: PreparedRotation) -> Self {
31 Self::Portable(Box::new(PortableRotation::compile(prepared)))
32 }
33
34 pub fn compile(rotation: &Rotation, resolver: &SpecResolver) -> Result<Self> {
39 let prepared =
40 RotationPreparation::prepare(rotation, resolver)?.bind(&BufferRequirements::new())?;
41
42 Ok(Self::portable(prepared))
43 }
44
45 pub fn compile_json(json: &str, resolver: &SpecResolver) -> Result<Self> {
50 let rotation = super::ast::parse_and_validate(json)?;
51
52 Self::compile(&rotation, resolver)
53 }
54
55 pub fn compile_empty(resolver: &SpecResolver) -> Result<Self> {
60 Self::compile(&Rotation::empty(), resolver)
61 }
62
63 #[cfg(feature = "jit")]
68 pub fn compile_jit(json: &str, resolver: &SpecResolver) -> Result<Self> {
69 let rotation = super::ast::parse_and_validate(json)?;
70 let prepared =
71 RotationPreparation::prepare(&rotation, resolver)?.bind(&BufferRequirements::new())?;
72
73 Self::jit(prepared)
74 }
75
76 #[cfg(feature = "jit")]
81 pub fn jit(prepared: PreparedRotation) -> Result<Self> {
82 Ok(Self::Jit(Box::new(CompiledRotation::compile(prepared)?)))
83 }
84
85 #[must_use]
87 pub fn with_decision_trace(mut self, sink: DecisionTraceTarget) -> Self {
88 self.set_decision_trace(sink);
89
90 self
91 }
92
93 #[must_use]
95 pub fn has_decision_trace(&self) -> bool {
96 match self {
97 Self::Portable(rotation) => rotation.has_trace(),
98 #[cfg(feature = "jit")]
99 Self::Jit(rotation) => rotation.has_trace(),
100 }
101 }
102
103 pub fn set_decision_trace(&mut self, sink: DecisionTraceTarget) {
105 match self {
106 Self::Portable(rotation) => rotation.set_trace(sink),
107 #[cfg(feature = "jit")]
108 Self::Jit(rotation) => rotation.set_trace(sink),
109 }
110 }
111
112 #[must_use]
114 pub fn prepared(&self) -> &PreparedRotation {
115 match self {
116 Self::Portable(rotation) => rotation.prepared(),
117 #[cfg(feature = "jit")]
118 Self::Jit(rotation) => rotation.prepared(),
119 }
120 }
121
122 pub fn evaluate(&mut self, buffer: &mut DenseBuffer, now_secs: f64) -> EvalResult {
124 RuntimeBackend::evaluate(self, buffer, now_secs)
125 }
126
127 #[must_use]
129 pub fn schema(&self) -> &ContextSchema {
130 RuntimeBackend::schema(self)
131 }
132}
133
134impl std::fmt::Debug for RotationEngine {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 Self::Portable(rotation) => f
138 .debug_struct("Portable")
139 .field("has_trace", &rotation.has_trace())
140 .finish(),
141 #[cfg(feature = "jit")]
142 Self::Jit(rotation) => f
143 .debug_struct("Jit")
144 .field("has_trace", &rotation.has_trace())
145 .finish(),
146 }
147 }
148}
149
150impl RuntimeBackend for RotationEngine {
151 fn evaluate(&mut self, buffer: &mut DenseBuffer, now_secs: f64) -> EvalResult {
152 match self {
153 Self::Portable(rotation) => rotation.evaluate(buffer, now_secs),
154 #[cfg(feature = "jit")]
155 Self::Jit(rotation) => rotation.evaluate(buffer, now_secs),
156 }
157 }
158
159 fn schema(&self) -> &ContextSchema {
160 match self {
161 Self::Portable(rotation) => rotation.schema(),
162 #[cfg(feature = "jit")]
163 Self::Jit(rotation) => rotation.schema(),
164 }
165 }
166}