Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'lemu/src/instructions/mop2.rs')
-rw-r--r--lemu/src/instructions/mop2.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/lemu/src/instructions/mop2.rs b/lemu/src/instructions/mop2.rs
new file mode 100644
index 0000000..7751736
--- /dev/null
+++ b/lemu/src/instructions/mop2.rs
@@ -0,0 +1,140 @@
+use super::get_num;
+use crate::{lexer::Token, memory::LVar};
+use std::f64::consts::PI;
+
+super::op_enum! { pub enum MathOp2 {
+ Angle,
+ Add,
+ Sub,
+ Mul,
+ Div,
+ IDiv,
+ Mod,
+ Pow,
+ Equal,
+ NotEqual,
+ And,
+ LessThan,
+ LessThanEq,
+ GreaterThan,
+ GreaterThanEq,
+ StrictEqual,
+ ShiftLeft,
+ ShiftRight,
+ BitOr,
+ BitAnd,
+ ExclusiveOr,
+ Max,
+ Min,
+ AngleDiff,
+ Len,
+ Noise, // unimplemented
+} }
+
+macro_rules! num {
+ ($fn:ident $closure:expr) => {
+ fn $fn<'v>(a: &LVar<'v>, b: &LVar<'v>) -> f64 {
+ f64::from($closure(get_num!(a), get_num!(b)))
+ }
+ };
+}
+macro_rules! op {
+ ($fn:ident $op:tt) => {
+ fn $fn<'v>(a: &LVar<'v>, b: &LVar<'v>) -> f64 {
+ f64::from(get_num!(a) $op get_num!(b))
+ }
+ }
+}
+macro_rules! bop {
+ ($fn: ident $op: tt) => {
+ fn $fn<'v>(a: &LVar<'v>, b:& LVar<'v>) -> f64 {
+ f64::from(((get_num!(a) as u64) $op (get_num!(b) as u64)) as f64)
+ }
+ };
+}
+macro_rules! nofun {
+ ($fn:ident $closure:expr) => {
+ fn $fn<'v>(a: &LVar<'v>, b: &LVar<'v>) -> f64 {
+ f64::from($closure(a, b))
+ }
+ };
+}
+nofun!(eq | a, b | a == b);
+nofun!(ne | a, b | a != b);
+num!(and | a, b | a != 0.0 && b != 0.0);
+#[rustfmt::skip]
+op!(add +);
+op!(sub -);
+op!(mul *);
+num!(idiv | a: f64 , b: f64 | (a / b).floor());
+op!(lt <);
+op!(le <=);
+op!(gt >);
+op!(ge >=);
+op!(div /);
+op!(rem %);
+num!(pow f64::powf);
+bop!(shl <<);
+bop!(shr >>);
+bop!(or |);
+bop!(band &);
+bop!(xor ^);
+num!(max f64::max);
+num!(min f64::min);
+#[rustfmt::skip]
+num!(angle_diff |a, b| {
+ let a = a % (360.0 * PI);
+ let b = b % (360.0 * PI);
+ f64::min(
+ if (a - b) < 0.0 { a - b + 360.0 } else { a - b },
+ if (b - a) < 0.0 { b - a + 360.0 } else { b - a },
+ )
+});
+num!(len f64::hypot);
+nofun!(noise | _, _ | 9.0);
+num!(angle |a: f64, b: f64| {
+ let mut x = a.atan2(b) * (180.0 / PI);
+ if x < 0.0 {
+ x += 360.0;
+ }
+ x
+});
+
+super::op_impl!(MathOp2, ptr type = for<'f> fn(&LVar<'f>, &LVar<'f>) -> f64 {
+ Equal => eq,
+ StrictEqual => eq,
+ NotEqual => ne,
+ And => and,
+ Add => add,
+ Sub => sub,
+ Mul => mul,
+ IDiv => idiv,
+ LessThan => lt,
+ LessThanEq => le,
+ GreaterThan => gt,
+ GreaterThanEq => ge,
+ Div => div,
+ Mod => rem,
+ Pow => pow,
+ ShiftLeft => shl,
+ ShiftRight => shr,
+ BitOr => or,
+ BitAnd => band,
+ ExclusiveOr => xor,
+ Max => max,
+ Min => min,
+ AngleDiff => angle_diff,
+ Len => len,
+ Noise => noise,
+ Angle => angle,
+});
+
+// // no macro cuz funky rem
+// impl MathOp2 {
+// pub const fn get_fn(self) -> for<'f> fn(&LVar<'f>, &LVar<'f>) -> f64 {
+// match self {
+// // we kind of interpret strings as numbers so yeah
+
+// }
+// }
+// }