Skip to main content

wowlab_engine_domain/rotation/
backend.rs

1//! Backend traits for rotation evaluation.
2
3use wowlab_types::sim::{Condition, RotationAction};
4
5use super::{
6    buffer::DenseBuffer, context::ContextSchema, decision_trace::ActionRecord, result::EvalResult,
7};
8
9/// Runtime dispatch trait for evaluating a compiled rotation.
10pub(crate) trait RuntimeBackend {
11    fn evaluate(&mut self, buffer: &mut DenseBuffer, now_secs: f64) -> EvalResult;
12
13    fn schema(&self) -> &ContextSchema;
14}
15
16/// Lowering trait of primitive ops both rotation backends must support, with bit-identical numeric semantics.
17// docref:start rotation-compiler-backend-trait
18pub(crate) trait RotationBackend {
19    type Bool: Copy;
20    type Int: Copy;
21    type Float: Copy;
22    type AndChain;
23    type OrChain;
24    #[cfg(feature = "rotation-optimizations")]
25    type CastGuard;
26    // docref:end rotation-compiler-backend-trait
27
28    fn const_bool(&mut self, v: bool) -> Self::Bool;
29    fn const_i32(&mut self, v: i32) -> Self::Int;
30    fn const_i64(&mut self, v: i64) -> Self::Int;
31    fn const_f64(&mut self, v: f64) -> Self::Float;
32
33    fn load_bool(&mut self, offset: usize) -> Self::Bool;
34    fn load_i32(&mut self, offset: usize) -> Self::Int;
35    fn load_f64(&mut self, offset: usize) -> Self::Float;
36
37    fn store_bool(&mut self, offset: usize, v: Self::Bool);
38    fn store_i32(&mut self, offset: usize, v: Self::Int);
39    fn store_f64(&mut self, offset: usize, v: Self::Float);
40
41    fn now(&mut self) -> Self::Float;
42
43    fn add_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
44    fn sub_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
45    fn mul_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
46    /// Returns 0.0 for any /0 (mirrors [`wowlab_types::numeric::safe_div`]).
47    fn safe_div_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
48    /// Mirrors [`wowlab_types::numeric::true_mod`].
49    fn true_mod_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
50    fn min_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
51    fn max_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Float;
52    fn floor_f(&mut self, v: Self::Float) -> Self::Float;
53    fn ceil_f(&mut self, v: Self::Float) -> Self::Float;
54    fn abs_f(&mut self, v: Self::Float) -> Self::Float;
55
56    fn cmp_gt_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
57    fn cmp_gte_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
58    fn cmp_lt_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
59    fn cmp_lte_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
60    /// Epsilon-aware (mirrors [`wowlab_types::numeric::float_eq`]).
61    fn cmp_eq_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
62    /// Epsilon-aware (mirrors [`wowlab_types::numeric::float_ne`]).
63    fn cmp_ne_f(&mut self, a: Self::Float, b: Self::Float) -> Self::Bool;
64    fn cmp_eq_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
65    fn cmp_ne_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
66    fn cmp_gt_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
67    fn cmp_gte_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
68    fn cmp_lt_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
69    fn cmp_lte_i(&mut self, a: Self::Int, b: Self::Int) -> Self::Bool;
70
71    fn and_b(&mut self, a: Self::Bool, b: Self::Bool) -> Self::Bool;
72    fn or_b(&mut self, a: Self::Bool, b: Self::Bool) -> Self::Bool;
73    fn not_b(&mut self, a: Self::Bool) -> Self::Bool;
74
75    fn begin_and(&mut self, first: Self::Bool) -> Self::AndChain;
76    fn push_and(&mut self, chain: &mut Self::AndChain, value: Self::Bool);
77    fn finish_and(&mut self, chain: Self::AndChain) -> Self::Bool;
78
79    fn begin_or(&mut self, first: Self::Bool) -> Self::OrChain;
80    fn push_or(&mut self, chain: &mut Self::OrChain, value: Self::Bool);
81    fn finish_or(&mut self, chain: Self::OrChain) -> Self::Bool;
82
83    #[cfg(feature = "rotation-optimizations")]
84    fn begin_cast_guard(&mut self, first: Self::Bool) -> Self::CastGuard;
85    #[cfg(feature = "rotation-optimizations")]
86    fn push_cast_guard(&mut self, guard: &mut Self::CastGuard, value: Self::Bool);
87    #[cfg(feature = "rotation-optimizations")]
88    fn finish_cast_guard(
89        &mut self,
90        guard: Self::CastGuard,
91        spell_id: u32,
92        empower_rank: u8,
93    ) -> Self::Bool;
94
95    fn bool_to_float(&mut self, v: Self::Bool) -> Self::Float;
96    fn bool_to_int(&mut self, v: Self::Bool) -> Self::Int;
97    fn int_to_float(&mut self, v: Self::Int) -> Self::Float;
98    fn int_to_bool(&mut self, v: Self::Int) -> Self::Bool;
99    /// Exact `v != 0.0`.
100    fn float_to_bool(&mut self, v: Self::Float) -> Self::Bool;
101    /// `v as i64` (truncates).
102    fn float_to_int(&mut self, v: Self::Float) -> Self::Int;
103
104    // Select is eager: both branches evaluated; safe as branches are side-effect-free buffer reads.
105    fn select_f(&mut self, cond: Self::Bool, t: Self::Float, f: Self::Float) -> Self::Float;
106    fn select_i(&mut self, cond: Self::Bool, t: Self::Int, f: Self::Int) -> Self::Int;
107    fn select_b(&mut self, cond: Self::Bool, t: Self::Bool, f: Self::Bool) -> Self::Bool;
108
109    fn return_cast_if(&mut self, cond: Self::Bool, spell_id: u32, empower_rank: u8);
110    fn return_wait_if(&mut self, cond: Self::Bool, seconds: f32);
111    fn return_pool_if(&mut self, cond: Self::Bool, target: f32);
112    fn return_use_item_if(&mut self, cond: Self::Bool, gear_slot: u8, empower_rank: u8);
113
114    fn return_none(&mut self);
115
116    #[inline]
117    fn record_action(&mut self, _record: ActionRecord<'_>) {}
118
119    #[inline]
120    fn record_action_guarded(
121        &mut self,
122        _list_id: &str,
123        _action_index: usize,
124        _action: &RotationAction,
125        _is_terminator: bool,
126        _guard_held: Self::Bool,
127        _failing: &Condition,
128    ) {
129    }
130
131    #[inline]
132    fn begin_list_recording(&mut self, _list_id: &str) {}
133
134    #[inline]
135    fn end_list_recording(&mut self) {}
136}