wowlab_engine_domain/rotation/lower/action/
vars.rs1use wowlab_types::sim::{Condition, VarOp};
2
3use super::{
4 super::{
5 super::backend::RotationBackend,
6 EvalValueAbstract, Lowerer,
7 condition::{load_user_var, lower_condition},
8 typed_load, typed_select, typed_store,
9 },
10 LowerCtx, lower_optional_guard, record_guarded,
11};
12
13pub(super) struct ModifyVarArgs<'a> {
14 pub(super) name: &'a str,
15 pub(super) op: VarOp,
16 pub(super) value: &'a Condition,
17 pub(super) condition: Option<&'a Condition>,
18}
19
20pub(super) fn lower_set_var<B>(
21 ctx: &mut LowerCtx<'_, '_, '_, B>,
22 name: &str,
23 value: &Condition,
24 condition: Option<&Condition>,
25) where
26 B: RotationBackend,
27{
28 let guard = lower_optional_guard(ctx.lo, ctx.b, condition);
29 let guard_opt = (!guard.is_unconditional).then_some(guard.bool_val);
30
31 conditional_store_user_var(ctx.lo, ctx.b, name, value, guard_opt);
32 record_guarded(ctx, &guard, condition);
33}
34
35pub(super) fn lower_modify_var<B>(ctx: &mut LowerCtx<'_, '_, '_, B>, args: &ModifyVarArgs<'_>)
36where
37 B: RotationBackend,
38{
39 let guard = lower_optional_guard(ctx.lo, ctx.b, args.condition);
40 let guard_opt = (!guard.is_unconditional).then_some(guard.bool_val);
41
42 modify_user_var(ctx.lo, ctx.b, args.name, args.op, args.value, guard_opt);
43 record_guarded(ctx, &guard, args.condition);
44}
45
46pub(crate) fn store_user_var<B>(lo: &mut Lowerer<'_>, b: &mut B, name: &str, expr: &Condition)
47where
48 B: RotationBackend,
49{
50 let (Some(offset), Some(field_type)) = (
51 lo.schema.user_var_offset(name),
52 lo.schema.user_var_type(name),
53 ) else {
54 return;
55 };
56 let value = lower_condition(lo, b, expr);
57
58 typed_store(b, offset, field_type, value);
59}
60
61fn conditional_store_user_var<B>(
62 lo: &mut Lowerer<'_>,
63 b: &mut B,
64 name: &str,
65 expr: &Condition,
66 guard: Option<B::Bool>,
67) where
68 B: RotationBackend,
69{
70 let (Some(offset), Some(field_type)) = (
71 lo.schema.user_var_offset(name),
72 lo.schema.user_var_type(name),
73 ) else {
74 return;
75 };
76 let new_val = lower_condition(lo, b, expr);
77 let final_val = match guard {
78 None => new_val,
79 Some(g) => {
80 let cur = typed_load(b, offset, field_type);
81
82 typed_select(b, field_type, g, new_val, cur)
83 }
84 };
85
86 typed_store(b, offset, field_type, final_val);
87}
88
89fn modify_user_var<B>(
90 lo: &mut Lowerer<'_>,
91 b: &mut B,
92 name: &str,
93 op: VarOp,
94 value: &Condition,
95 guard: Option<B::Bool>,
96) where
97 B: RotationBackend,
98{
99 let (Some(offset), Some(field_type)) = (
100 lo.schema.user_var_offset(name),
101 lo.schema.user_var_type(name),
102 ) else {
103 return;
104 };
105 let cur = load_user_var(lo, b, name).into_float(b);
106 let rhs_val = lower_condition(lo, b, value).into_float(b);
107 let new_f = match op {
108 VarOp::Add => b.add_f(cur, rhs_val),
109 VarOp::Sub => b.sub_f(cur, rhs_val),
110 VarOp::Mul => b.mul_f(cur, rhs_val),
111 VarOp::Div => b.safe_div_f(cur, rhs_val),
112 VarOp::Mod => b.true_mod_f(cur, rhs_val),
113 VarOp::Min => b.min_f(cur, rhs_val),
114 VarOp::Max => b.max_f(cur, rhs_val),
115 VarOp::Floor => b.floor_f(cur),
116 VarOp::Ceil => b.ceil_f(cur),
117 VarOp::Reset => match lo.variables.get(name).cloned() {
118 Some(init) => lower_condition(lo, b, &init).into_float(b),
119 None => b.const_f64(0.0),
120 },
121 _ => unreachable!("rotation validation rejects unsupported variable operators"),
122 };
123 let final_val = match guard {
124 None => EvalValueAbstract::Float(new_f),
125 Some(g) => {
126 let cur = typed_load(b, offset, field_type);
127
128 typed_select(b, field_type, g, EvalValueAbstract::Float(new_f), cur)
129 }
130 };
131
132 typed_store(b, offset, field_type, final_val);
133}