Skip to main content

wowlab_engine_domain/rotation/lower/
value.rs

1use super::super::{backend::RotationBackend, expr::FieldType};
2
3pub(in crate::rotation) enum EvalValueAbstract<B>
4where
5    B: RotationBackend,
6{
7    Bool(B::Bool),
8    Int(B::Int),
9    Float(B::Float),
10}
11
12/// `FieldType` is `#[non_exhaustive]`, so width dispatch keeps a mandatory wildcard arm.
13#[cold]
14#[inline(never)]
15fn unexpected_field_type(context: &str, field_type: FieldType) {
16    tracing::error!(
17        ?field_type,
18        context,
19        "unexpected FieldType discriminant in width dispatch, defaulting to Float"
20    );
21}
22
23pub(crate) fn typed_load<B>(b: &mut B, offset: usize, field_type: FieldType) -> EvalValueAbstract<B>
24where
25    B: RotationBackend,
26{
27    match field_type {
28        FieldType::Bool => EvalValueAbstract::Bool(b.load_bool(offset)),
29        FieldType::Int => EvalValueAbstract::Int(b.load_i32(offset)),
30        FieldType::Float => EvalValueAbstract::Float(b.load_f64(offset)),
31        other => {
32            unexpected_field_type("typed_load", other);
33
34            EvalValueAbstract::Float(b.load_f64(offset))
35        }
36    }
37}
38
39pub(crate) fn typed_store<B>(
40    b: &mut B,
41    offset: usize,
42    field_type: FieldType,
43    value: EvalValueAbstract<B>,
44) where
45    B: RotationBackend,
46{
47    match field_type {
48        FieldType::Bool => {
49            let v = value.into_bool(b);
50
51            b.store_bool(offset, v);
52        }
53        FieldType::Int => {
54            let v = value.into_int(b);
55
56            b.store_i32(offset, v);
57        }
58        FieldType::Float => {
59            let v = value.into_float(b);
60
61            b.store_f64(offset, v);
62        }
63        other => {
64            unexpected_field_type("typed_store", other);
65            let v = value.into_float(b);
66
67            b.store_f64(offset, v);
68        }
69    }
70}
71
72pub(crate) fn typed_select<B>(
73    b: &mut B,
74    field_type: FieldType,
75    cond: B::Bool,
76    on_true: EvalValueAbstract<B>,
77    on_false: EvalValueAbstract<B>,
78) -> EvalValueAbstract<B>
79where
80    B: RotationBackend,
81{
82    match field_type {
83        FieldType::Bool => {
84            let t = on_true.into_bool(b);
85            let f = on_false.into_bool(b);
86
87            EvalValueAbstract::Bool(b.select_b(cond, t, f))
88        }
89        FieldType::Int => {
90            let t = on_true.into_int(b);
91            let f = on_false.into_int(b);
92
93            EvalValueAbstract::Int(b.select_i(cond, t, f))
94        }
95        FieldType::Float => {
96            let t = on_true.into_float(b);
97            let f = on_false.into_float(b);
98
99            EvalValueAbstract::Float(b.select_f(cond, t, f))
100        }
101        other => {
102            unexpected_field_type("typed_select", other);
103            let t = on_true.into_float(b);
104            let f = on_false.into_float(b);
105
106            EvalValueAbstract::Float(b.select_f(cond, t, f))
107        }
108    }
109}
110
111impl<B> EvalValueAbstract<B>
112where
113    B: RotationBackend,
114{
115    pub(crate) fn into_bool(self, b: &mut B) -> B::Bool {
116        match self {
117            Self::Bool(v) => v,
118            Self::Int(v) => b.int_to_bool(v),
119            Self::Float(v) => b.float_to_bool(v),
120        }
121    }
122
123    pub(crate) fn into_int(self, b: &mut B) -> B::Int {
124        match self {
125            Self::Bool(v) => b.bool_to_int(v),
126            Self::Int(v) => v,
127            Self::Float(v) => b.float_to_int(v),
128        }
129    }
130
131    pub(crate) fn into_float(self, b: &mut B) -> B::Float {
132        match self {
133            Self::Bool(v) => b.bool_to_float(v),
134            Self::Int(v) => b.int_to_float(v),
135            Self::Float(v) => v,
136        }
137    }
138}