mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/memory.rs')
-rw-r--r--lemu/src/memory.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/lemu/src/memory.rs b/lemu/src/memory.rs
new file mode 100644
index 0000000..9dd0828
--- /dev/null
+++ b/lemu/src/memory.rs
@@ -0,0 +1,135 @@
+#[derive(Copy, Clone, Debug)]
+pub enum LVar<'string> {
+ Num(f64),
+ String(&'string str),
+}
+
+impl PartialEq for LVar<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::Num(a), Self::Num(b)) => (a - b).abs() < 0.000_001,
+ (Self::String(l0), Self::String(r0)) => l0 == r0,
+ _ => false,
+ }
+ }
+}
+
+impl LVar<'_> {
+ // get null
+ pub const fn null() -> LVar<'static> {
+ LVar::Num(0.0)
+ }
+}
+
+#[derive(Copy, Clone)]
+pub enum LAddress<'str> {
+ Const(LVar<'str>),
+ Address(usize, Priv),
+}
+
+impl<'v> LAddress<'v> {
+ /// # Safety
+ ///
+ /// you must make sure that addr is in bounds of the memory.
+ pub(crate) const unsafe fn addr(addr: usize) -> Self {
+ LAddress::Address(addr, Priv { _priv: () })
+ }
+
+ pub(crate) fn cnst(c: impl Into<LVar<'v>>) -> Self {
+ Self::Const(c.into())
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct Priv {
+ _priv: (),
+}
+
+impl std::fmt::Debug for LAddress<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Const(c) => write!(f, "LAddress {c}"),
+ Self::Address(n, ..) => write!(f, "LAddress {n:x}"),
+ }
+ }
+}
+
+impl std::fmt::Display for LVar<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Num(n) => write!(f, "{n}"),
+ Self::String(s) => write!(f, r#""{s}""#),
+ }
+ }
+}
+
+impl From<f64> for LVar<'_> {
+ fn from(value: f64) -> Self {
+ Self::Num(value)
+ }
+}
+
+impl From<bool> for LVar<'_> {
+ fn from(value: bool) -> Self {
+ Self::Num(value.into())
+ }
+}
+
+impl<'s> From<&'s str> for LVar<'s> {
+ fn from(value: &'s str) -> Self {
+ Self::String(value)
+ }
+}
+
+/// cleared every loop
+#[derive(Default, Debug)]
+pub struct LRegistry<'str>(Box<[LVar<'str>]>);
+
+impl<'s> LRegistry<'s> {
+ pub fn new(size: usize) -> Self {
+ Self(vec![LVar::null(); size].into_boxed_slice())
+ }
+
+ pub fn clear(&mut self) {
+ for var in &mut *self.0 {
+ *var = LVar::null();
+ }
+ }
+
+ pub fn get(&self, a: LAddress<'s>) -> LVar<'s> {
+ match a {
+ // SAFETY: addr constructor requires bounds
+ LAddress::Address(n, ..) => unsafe { *self.0.get_unchecked(n) },
+ LAddress::Const(n) => n,
+ }
+ }
+
+ pub fn set(&mut self, a: LAddress<'s>, b: LAddress<'s>) -> bool {
+ match a {
+ LAddress::Const(_) => false,
+ LAddress::Address(v, ..) => {
+ match b {
+ LAddress::Const(n) => {
+ // SAFETY: v comes from Address, therefore safe
+ *unsafe { self.0.get_unchecked_mut(v) } = n;
+ }
+ LAddress::Address(n, ..) => {
+ // SAFETY: n comes from Address, therefore safe
+ let b = *unsafe { self.0.get_unchecked(n) };
+ // SAFETY: v comes from Addr, therefore safe
+ *unsafe { self.0.get_unchecked_mut(v) } = b;
+ }
+ };
+ true
+ }
+ }
+ }
+
+ pub fn get_mut(&mut self, a: LAddress<'s>) -> Option<&mut LVar<'s>> {
+ match a {
+ LAddress::Const(_) => None,
+ // SAFETY: addr constructor requires bounds
+ LAddress::Address(n, ..) => Some(unsafe { self.0.get_unchecked_mut(n) }),
+ }
+ }
+}