mindustry logic execution, map- and schematic- parsing and rendering
add a Code struct
| -rw-r--r-- | lemu/src/code.rs | 58 | ||||
| -rw-r--r-- | lemu/src/executor/builder.rs | 5 | ||||
| -rw-r--r-- | lemu/src/executor/mod.rs | 43 | ||||
| -rw-r--r-- | lemu/src/lib.rs | 1 | ||||
| -rw-r--r-- | lemu/src/parser/mod.rs | 4 |
5 files changed, 68 insertions, 43 deletions
diff --git a/lemu/src/code.rs b/lemu/src/code.rs new file mode 100644 index 0000000..9132279 --- /dev/null +++ b/lemu/src/code.rs @@ -0,0 +1,58 @@ +use super::{ + instructions::{DrawInstr, Instr}, + lexer::Token, +}; + +#[derive(Debug)] +pub enum PInstr<'s> { + Instr(Instr<'s>), + Draw(DrawInstr<'s>), + Code(Box<[Token<'s>]>), + Comment(&'s str), +} + +impl std::fmt::Display for PInstr<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Instr(i) => write!(f, "{i}"), + Self::Draw(i) => write!(f, "{i}"), + Self::Code(c) => { + let mut toks = c.iter(); + if let Some(t) = toks.next() { + write!(f, "{t}")?; + } + for token in toks { + write!(f, " {token}")?; + } + Ok(()) + } + Self::Comment(c) => write!(f, "{c}"), + } + } +} + +impl std::fmt::Display for Code<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for instr in &*self.0 { + writeln!(f, "{instr}")?; + } + Ok(()) + } +} + +#[repr(transparent)] +pub struct Code<'s>(Box<[PInstr<'s>]>); + +// Pin requires +impl<'s> std::ops::Deref for Code<'s> { + type Target = [PInstr<'s>]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl<'s> Code<'s> { + pub(crate) fn new(code: Box<[PInstr<'s>]>) -> Self { + Self(code) + } +} diff --git a/lemu/src/executor/builder.rs b/lemu/src/executor/builder.rs index bd5b527..eae3fb2 100644 --- a/lemu/src/executor/builder.rs +++ b/lemu/src/executor/builder.rs @@ -6,6 +6,7 @@ use super::{ BANK_SIZE, CELL_SIZE, }; use crate::{ + code::Code, instructions::{DrawInstr, Instr}, lexer::Token, memory::LRegistry, @@ -111,7 +112,7 @@ impl<'s, W: Wr> ExecutorBuilderInternal<'s, W> { core::ptr::slice_from_raw_parts_mut(ptr.cast::<[f64; N]>(), len / N); unsafe { Box::from_raw(ptr) } } - let program = Pin::new( + let program = Pin::new(Code::new( self.program .into_iter() .map(|v| match v { @@ -122,7 +123,7 @@ impl<'s, W: Wr> ExecutorBuilderInternal<'s, W> { UPInstr::Code(c) => PInstr::Code(c), }) .collect::<Box<[PInstr]>>(), - ); + )); let Self { instruction_limit, iteration_limit, diff --git a/lemu/src/executor/mod.rs b/lemu/src/executor/mod.rs index 9c0553b..746ca7a 100644 --- a/lemu/src/executor/mod.rs +++ b/lemu/src/executor/mod.rs @@ -1,6 +1,7 @@ mod builder; use super::{ + code::{Code, PInstr}, instructions::{DrawInstr, DrawInstruction, Flow, Instr, LInstruction}, lexer::Token, memory::{LAddress, LRegistry, LVar}, @@ -32,7 +33,7 @@ impl Memory { } } - pub(crate) fn size(&self) -> usize { + pub(crate) const fn size(&self) -> usize { match self { Self::Bank(_) => BANK_SIZE, Self::Cell(_) => CELL_SIZE, @@ -62,7 +63,7 @@ impl Instruction { Self(n) } - pub fn get(self) -> usize { + pub const fn get(self) -> usize { self.0 } } @@ -73,33 +74,6 @@ impl std::fmt::Debug for Instruction { } } -#[derive(Debug)] -pub enum PInstr<'s> { - Instr(Instr<'s>), - Draw(DrawInstr<'s>), - Code(Box<[Token<'s>]>), - Comment(&'s str), -} - -impl std::fmt::Display for PInstr<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Instr(i) => write!(f, "{i}"), - Self::Draw(i) => write!(f, "{i}"), - Self::Code(c) => { - let mut toks = c.iter(); - if let Some(t) = toks.next() { - write!(f, "{t}")?; - } - for token in toks { - write!(f, " {token}")?; - } - Ok(()) - } - Self::Comment(c) => write!(f, "{c}"), - } - } -} #[derive(Debug, Copy, Clone)] pub enum Limit { /// limited to n @@ -134,7 +108,7 @@ pub struct Executor<'varnames, W: Write> { pub iteration_limit: Limit, pub(crate) inner: ExecutorContext<'varnames, W>, /// gets pointed to by drawbuf - pub(crate) program: Pin<Box<[PInstr<'varnames>]>>, + pub(crate) program: Pin<Code<'varnames>>, /// Counter for the number of instructions we have run so far. pub instructions_ran: usize, } @@ -191,15 +165,6 @@ impl Default for DisplayState { } } -impl<W: Write> std::fmt::Display for Executor<'_, W> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for instr in &*self.program { - writeln!(f, "{instr}")?; - } - Ok(()) - } -} - impl<'s, W: Write> ExecutorContext<'s, W> { pub fn flush(&mut self, to: Display) { let mut state = DisplayState::default(); diff --git a/lemu/src/lib.rs b/lemu/src/lib.rs index bfa2d29..ba643aa 100644 --- a/lemu/src/lib.rs +++ b/lemu/src/lib.rs @@ -11,6 +11,7 @@ clippy::dbg_macro, missing_docs )] +pub(crate) mod code; mod executor; mod instructions; mod lexer; diff --git a/lemu/src/parser/mod.rs b/lemu/src/parser/mod.rs index 31faf7f..53c2940 100644 --- a/lemu/src/parser/mod.rs +++ b/lemu/src/parser/mod.rs @@ -406,11 +406,11 @@ pub fn parse<'source, W: Wr>( let screen = take_ident!(t.clone())?; let mut out = String::new(); for ch in screen.chars() { - if matches!(ch, '0'..='9') { + if ch.is_ascii_digit() { out.push(ch); continue; } - if out.len() != 0 { + if !out.is_empty() { yeet!(InvalidDisplayType(screen)); } } |