mindustry logic execution, map- and schematic- parsing and rendering
| -rw-r--r-- | lemu/src/instructions/mod.rs | 40 | ||||
| -rw-r--r-- | lemu/src/lexer.rs | 4 | ||||
| -rw-r--r-- | lemu/src/lib.rs | 1 | ||||
| -rw-r--r-- | lemu/src/parser/mod.rs | 23 |
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!()?; |