1use crate::calc::Calc;
2
3#[macro_export]
4macro_rules! var {
5 ($var:ident,$val:literal) => {
6 const $var: Var = Var::new(stringify!($var), stringify!($val), false);
7 };
8 ($var:ident,$val:literal,$comment:literal) => {
9 #[doc = $comment]
10 const $var: Var = Var::commented(stringify!($var), $comment, stringify!($val), false);
11 };
12}
13#[macro_export]
14macro_rules! calc {
15 ($var:ident,$val:expr) => {
16 const $var: Var = Var::new(stringify!($var), stringify!($val), true);
17 };
18 ($var:ident,$val:expr,$comment:literal) => {
19 #[doc = $comment]
20 const $var: Var = Var::commented(stringify!($var), $comment, stringify!($val), true);
21 };
22}
23
24pub trait Arg: Sized {
25 fn val(self) -> Val;
26}
27
28impl Arg for Var {
29 fn val(self) -> Val {
30 Val::Var(self)
31 }
32}
33impl Arg for Val {
34 fn val(self) -> Val {
35 self
36 }
37}
38impl Arg for Calc {
39 fn val(self) -> Val {
40 Val::Calc(self)
41 }
42}
43impl Arg for f32 {
44 fn val(self) -> Val {
45 Val::Val(self)
46 }
47}
48impl Arg for i32 {
49 #[allow(clippy::cast_precision_loss)]
50 fn val(self) -> Val {
51 Val::Val(self as f32)
52 }
53}
54#[derive(Clone, Copy)]
55pub struct Var {
56 name: &'static str,
57 comment: &'static str,
58 val: &'static str,
59 calc: bool,
60}
61impl Var {
62 #[must_use]
63 pub const fn new(name: &'static str, val: &'static str, calc: bool) -> Var {
64 Self {
65 name,
66 comment: "",
67 val,
68 calc,
69 }
70 }
71 #[must_use]
72 pub const fn commented(
73 name: &'static str,
74 comment: &'static str,
75 val: &'static str,
76 calc: bool,
77 ) -> Var {
78 Self {
79 name,
80 comment,
81 val,
82 calc,
83 }
84 }
85 pub(crate) fn get_comment(&self) -> &'static str {
86 self.comment
87 }
88 pub(crate) fn get_name(&self) -> &'static str {
89 self.name
90 }
91 pub(crate) fn get_val(&self) -> &'static str {
92 self.val
93 }
94
95 pub(crate) fn is_clac(&self) -> bool {
96 self.calc
97 }
98}
99
100#[derive(Clone)]
101pub enum Val {
102 Val(f32),
103 Var(Var),
104 Calc(Calc),
105}
106impl std::fmt::Display for Val {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 match self {
109 Val::Val(val) => f.write_str(val.to_string().as_str()),
110 Val::Var(var) => f.write_str(var.name),
111 Val::Calc(calc) => calc.fmt(f),
112 }
113 }
114}
115
116impl std::ops::Neg for Val {
117 type Output = Calc;
118
119 fn neg(self) -> Self::Output {
120 Calc::neg(self)
121 }
122}
123impl std::ops::Neg for Var {
124 type Output = Calc;
125
126 fn neg(self) -> Self::Output {
127 Calc::neg(Val::Var(self))
128 }
129}
130
131macro_rules! impl_op {
132 ($op:ident,$func:ident,$t:ty) => {
133 impl<RHS: Arg> std::ops::$op<RHS> for $t {
134 type Output = Calc;
135
136 fn $func(self, rhs: RHS) -> Self::Output {
137 Calc::$func(self.val(), rhs.val())
138 }
139 }
140 };
141}
142
143impl_op!(Add, add, Val);
144impl_op!(Sub, sub, Val);
145impl_op!(Mul, mul, Val);
146impl_op!(Div, div, Val);
147
148impl_op!(Add, add, Calc);
149impl_op!(Sub, sub, Calc);
150impl_op!(Mul, mul, Calc);
151impl_op!(Div, div, Calc);
152
153impl_op!(Add, add, Var);
154impl_op!(Sub, sub, Var);
155impl_op!(Mul, mul, Var);
156impl_op!(Div, div, Var);