mindustry logic execution, map- and schematic- parsing and rendering
add a Code struct
bendn 2023-10-05
parent d7dc1ad · commit 10968c7
-rw-r--r--lemu/src/code.rs58
-rw-r--r--lemu/src/executor/builder.rs5
-rw-r--r--lemu/src/executor/mod.rs43
-rw-r--r--lemu/src/lib.rs1
-rw-r--r--lemu/src/parser/mod.rs4
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));
}
}