mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/instructions/mod.rs')
-rw-r--r--lemu/src/instructions/mod.rs148
1 files changed, 96 insertions, 52 deletions
diff --git a/lemu/src/instructions/mod.rs b/lemu/src/instructions/mod.rs
index e684a64..f4d6565 100644
--- a/lemu/src/instructions/mod.rs
+++ b/lemu/src/instructions/mod.rs
@@ -23,10 +23,9 @@ pub use draw::{DrawInstr, DrawInstruction};
use enum_dispatch::enum_dispatch;
pub use mop::MathOp1;
pub use mop2::MathOp2;
-use std::{
- fmt::{self, Display, Formatter},
- io::Write,
-};
+use std::{fmt, io::Write};
+
+use crate::debug::{info::DebugInfo, printable::Printable};
use super::{
executor::{ExecutorContext, Instruction},
@@ -87,8 +86,8 @@ pub enum Flow {
}
#[enum_dispatch]
-pub trait LInstruction: Display {
- fn run<'v, W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow;
+pub trait LInstruction: Printable {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow;
}
#[derive(Debug, Copy, Clone)]
@@ -107,21 +106,22 @@ pub enum Instr {
Stop(Stop),
End(End),
}
-impl Display for Instr {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+
+impl Printable for Instr {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
match self {
- Self::Op2(i) => write!(f, "{i}"),
- Self::Jump(i) => write!(f, "{i}"),
- Self::AlwaysJump(i) => write!(f, "{i}"),
- Self::Set(i) => write!(f, "{i}"),
- Self::Op1(i) => write!(f, "{i}"),
- Self::Read(i) => write!(f, "{i}"),
- Self::Write(i) => write!(f, "{i}"),
- Self::DrawFlush(i) => write!(f, "{i}"),
- Self::DynJump(i) => write!(f, "{i}"),
- Self::Print(i) => write!(f, "{i}"),
- Self::Stop(i) => write!(f, "{i}"),
- Self::End(i) => write!(f, "{i}"),
+ Self::Op2(i) => i.print(info, f),
+ Self::Jump(i) => i.print(info, f),
+ Self::AlwaysJump(i) => i.print(info, f),
+ Self::Set(i) => i.print(info, f),
+ Self::Op1(i) => i.print(info, f),
+ Self::Read(i) => i.print(info, f),
+ Self::Write(i) => i.print(info, f),
+ Self::DrawFlush(i) => i.print(info, f),
+ Self::DynJump(i) => i.print(info, f),
+ Self::Print(i) => i.print(info, f),
+ Self::Stop(i) => i.print(info, f),
+ Self::End(i) => i.print(info, f),
}
}
}
@@ -132,15 +132,15 @@ pub struct Set {
pub(crate) to: LAddress,
}
impl LInstruction for Set {
- fn run<'v, W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow {
- exec.set(self.from, self.to.clone());
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
+ exec.set(self.from, self.to);
Flow::Continue
}
}
-impl Display for Set {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "set {} {}", self.from, self.to)
+impl Printable for Set {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ write!(f, "set {} {}", info[self.from], info[self.to])
}
}
@@ -163,6 +163,12 @@ macro_rules! op_enum {
}
}
+ impl std::fmt::Display for $name {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ write!(f, "{}", Token::from(*self))
+ }
+ }
+
impl<'a> From<$name> for Token<'a> {
fn from(value: $name) -> Self {
match value {
@@ -174,6 +180,30 @@ macro_rules! op_enum {
}
use op_enum;
+// not part of op_enum due to rem
+macro_rules! op_impl {
+ ($name:ident, ptr type = $ptr:ty { $($own:ident => $fn:ident,)+ }) => {
+ impl $name {
+ pub const fn get_fn(self) -> $ptr {
+ match self {
+ $(Self::$own => $fn,)+
+ }
+ }
+ }
+
+ impl TryFrom<$ptr> for $name {
+ type Error = ();
+ fn try_from(f:$ptr) -> Result<Self, ()> {
+ match f {
+ $(f if f == $fn => Ok(Self::$own),)+
+ _ => Err(()),
+ }
+ }
+ }
+ }
+}
+use op_impl;
+
macro_rules! get_num {
($x:expr) => {
match $x {
@@ -190,7 +220,7 @@ pub struct Op1 {
x: LAddress,
out: LAddress,
}
-impl<'v> Op1 {
+impl Op1 {
pub(crate) const fn new(op: MathOp1, x: LAddress, out: LAddress) -> Self {
Self {
op: op.get_fn(),
@@ -201,17 +231,17 @@ impl<'v> Op1 {
}
impl LInstruction for Op1 {
- fn run<'s, W: Write>(&self, exec: &mut ExecutorContext<'s, W>) -> Flow {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
let x = (self.op)(exec.get(self.x));
*exec.get_mut(self.out) = LVar::Num(x);
Flow::Continue
}
}
-impl Display for Op1 {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- let Self { x, out, .. } = self;
- write!(f, "op .. {out} {x}")
+impl Printable for Op1 {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ let op = mop::MathOp1::try_from(self.op).unwrap();
+ write!(f, "op {op} {} {}", info[self.out], info[self.x])
}
}
@@ -235,17 +265,21 @@ impl Op2 {
impl LInstruction for Op2 {
#[inline]
- fn run<'v, W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
let x = (self.op)(exec.get(self.a), exec.get(self.b));
exec.memory[self.out] = LVar::Num(x);
Flow::Continue
}
}
-impl Display for Op2 {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- let Self { a, b, out, .. } = self;
- write!(f, "op .. {out} {a} {b}")
+impl Printable for Op2 {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ let op = mop2::MathOp2::try_from(self.op).unwrap();
+ write!(
+ f,
+ "op {op} {} {} {}",
+ info[self.out], info[self.a], info[self.b]
+ )
}
}
@@ -261,8 +295,8 @@ impl LInstruction for End {
}
}
-impl Display for End {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+impl Printable for End {
+ fn print(&self, _: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
write!(f, "end")
}
}
@@ -278,9 +312,14 @@ impl LInstruction for AlwaysJump {
}
}
-impl Display for AlwaysJump {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "jump {} always", self.to.get())
+impl Printable for AlwaysJump {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ write!(f, "jump ")?;
+ match info.label(self.to) {
+ Some(l) => f.write_str(l)?,
+ None => write!(f, "{}", self.to.get())?,
+ }
+ write!(f, " always")
}
}
@@ -303,7 +342,7 @@ impl Jump {
}
impl LInstruction for Jump {
- fn run<'v, W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
if (self.op)(exec.get(self.a), exec.get(self.b)) {
exec.jump(self.to);
Flow::Stay
@@ -313,10 +352,15 @@ impl LInstruction for Jump {
}
}
-impl Display for Jump {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- let Self { to, a, b, .. } = self;
- write!(f, "jump .. {} {a} {b}", to.get())
+impl Printable for Jump {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ let op = ConditionOp::try_from(self.op).unwrap();
+ write!(f, "jump {op} ")?;
+ match info.label(self.to) {
+ Some(l) => f.write_str(l)?,
+ None => write!(f, "{}", self.to.get())?,
+ };
+ write!(f, " {} {}", info[self.a], info[self.b])
}
}
@@ -327,7 +371,7 @@ pub struct DynJump {
}
impl LInstruction for DynJump {
- fn run<'v, W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
if let &LVar::Num(n) = exec.get(self.to) {
let i = n.round() as usize;
if i < self.proglen {
@@ -340,9 +384,9 @@ impl LInstruction for DynJump {
}
}
-impl Display for DynJump {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "set @counter {}", self.to)
+impl Printable for DynJump {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ write!(f, "set @counter {}", info[self.to])
}
}
@@ -354,8 +398,8 @@ impl LInstruction for Stop {
}
}
-impl Display for Stop {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+impl Printable for Stop {
+ fn print(&self, _: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
write!(f, "stop")
}
}