mindustry logic execution, map- and schematic- parsing and rendering
add select, noop
bendn 7 months ago
parent 6c2ae57 · commit 8440a11
-rw-r--r--lemu/src/instructions/mod.rs40
-rw-r--r--lemu/src/lexer.rs4
-rw-r--r--lemu/src/lib.rs1
-rw-r--r--lemu/src/parser/mod.rs23
4 files changed, 65 insertions, 3 deletions
diff --git a/lemu/src/instructions/mod.rs b/lemu/src/instructions/mod.rs
index ddca3a0..b4fc0aa 100644
--- a/lemu/src/instructions/mod.rs
+++ b/lemu/src/instructions/mod.rs
@@ -106,6 +106,7 @@ pub enum Instr {
Print(io::Print),
Stop(Stop),
PackColor(PackColor),
+ Select(Select),
End(End),
}
@@ -125,6 +126,7 @@ impl Printable for Instr {
Self::Stop(i) => i.print(info, f),
Self::End(i) => i.print(info, f),
Self::PackColor(i) => i.print(info, f),
+ Self::Select(i) => i.print(info, f),
}
}
}
@@ -441,3 +443,41 @@ impl Printable for PackColor {
)
}
}
+#[derive(Debug, Copy, Clone)]
+pub struct Select {
+ pub op: for<'v> fn(&LVar<'v>, &LVar<'v>) -> bool,
+ pub(crate) to: LAddress,
+
+ pub x: LAddress,
+ pub y: LAddress,
+
+ pub a: LAddress,
+ pub b: LAddress,
+}
+
+impl LInstruction for Select {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
+ *exec.get_mut(self.to) = if (self.op)(exec.get(self.x), exec.get(self.y)) {
+ exec.get(self.a)
+ } else {
+ exec.get(self.b)
+ }
+ .clone();
+ Flow::Continue
+ }
+}
+
+impl Printable for Select {
+ fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
+ write!(
+ f,
+ "select {} {} {} {} {} {}",
+ info[self.to],
+ ConditionOp::try_from(self.op).unwrap(),
+ info[self.x],
+ info[self.y],
+ info[self.a],
+ info[self.b]
+ )
+ }
+}
diff --git a/lemu/src/lexer.rs b/lemu/src/lexer.rs
index cc37ab6..f7a5b3d 100644
--- a/lemu/src/lexer.rs
+++ b/lemu/src/lexer.rs
@@ -7,6 +7,7 @@ macro_rules! instrs {
#[logos(skip r"[ \t]+")]
pub enum Token<'strings> {
#[token("\n")]
+ #[token(";")]
Newline,
#[regex("#[^\n]+", priority = 8)]
Comment(&'strings str),
@@ -50,6 +51,7 @@ instrs! {
"packcolor" => PackColor,
"drawflush" => DrawFlush,
"draw" => Draw,
+ "select" => Select,
"print" => Print,
"jump" => Jump,
"stop" => Stop,
@@ -97,7 +99,7 @@ instrs! {
"atan" => ATan,
}
-pub fn lex(s: &str) -> Lexer {
+pub fn lex(s: &str) -> Lexer<'_> {
Lexer {
inner: Token::lexer(s),
}
diff --git a/lemu/src/lib.rs b/lemu/src/lib.rs
index a45be20..ce81f1d 100644
--- a/lemu/src/lib.rs
+++ b/lemu/src/lib.rs
@@ -1,5 +1,4 @@
//! crate for [MLOG](https://mindustrygame.github.io/wiki/logic/0-introduction/#what-is-mindustry-logic) emulation.
-#![feature(let_chains)]
#![allow(clippy::redundant_closure_call)]
// yeah so like well you see i kinda well kinda have to yes but sorta
#![allow(clippy::fn_address_comparisons)]
diff --git a/lemu/src/parser/mod.rs b/lemu/src/parser/mod.rs
index fc87a7a..6ef5253 100644
--- a/lemu/src/parser/mod.rs
+++ b/lemu/src/parser/mod.rs
@@ -17,7 +17,7 @@ use super::{
executor::{ExecutorBuilderInternal, Instruction, UPInstr},
instructions::{
AlwaysJump, ConditionOp, DynJump, End, Instr, Jump, MathOp1, MathOp2, Op1, Op2, PackColor,
- Set, Stop,
+ Select, Set, Stop,
draw::{
Clear, Flush, Line, LinePoly, Poly, RectBordered, RectFilled, SetCol, SetColor,
SetStroke, Triangle,
@@ -493,6 +493,26 @@ pub fn parse<'source, W: Wr>(
Token::End => {
executor.add(End {});
}
+ Token::Select => {
+ let to = addr!(take_ident!(tok!()?)?)?; // =
+ // if
+ let op: ConditionOp = tok!()?.try_into().map_err(|op| err!(ExpectedOp(op)))?;
+
+ let x = take_var!(tok!()?)?;
+ let y = take_var!(tok!()?)?;
+
+ let a = take_var!(tok!()?)?; // then
+ let b = take_var!(tok!()?)?; // else
+
+ executor.add(Select {
+ op: op.get_fn(),
+ to,
+ x,
+ y,
+ a,
+ b,
+ })
+ }
// starting newline, simply skip. continue, so as not to to trigger the nextline!()
Token::Newline => continue,
// unknown instruction
@@ -623,6 +643,7 @@ pub fn parse<'source, W: Wr>(
}};
}
match i {
+ "noop" => {}
"printflush" => instr! {
(1) => |b| {
let t = tok!()?;