Skip to main content

wowlab_engine_domain/rotation/lower/action/
vars.rs

1use 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}