mindustry logic execution, map- and schematic- parsing and rendering
fix `end`
bendn 2023-09-17
parent 04bf09e · commit cce5625
-rw-r--r--lemu/src/executor/builder.rs2
-rw-r--r--lemu/src/executor/mod.rs23
-rw-r--r--lemu/src/instructions/draw.rs1
-rw-r--r--lemu/src/instructions/mod.rs19
-rw-r--r--lemu/src/parser.rs11
5 files changed, 37 insertions, 19 deletions
diff --git a/lemu/src/executor/builder.rs b/lemu/src/executor/builder.rs
index 44f8df2..f14f4c8 100644
--- a/lemu/src/executor/builder.rs
+++ b/lemu/src/executor/builder.rs
@@ -131,6 +131,7 @@ impl<'s, W: Wr> ExecutorBuilderInternal<'s, W> {
banks: cst::<BANK_SIZE>(banks),
memory: LRegistry::new(mem),
counter: 0,
+ iterations: 0,
display: Drawing {
displays: displays.into(),
buffer: VecDeque::new(),
@@ -153,7 +154,6 @@ impl<'s, W: Wr> ExecutorBuilderInternal<'s, W> {
.collect::<Box<[PInstr]>>(),
),
instructions_ran: 0,
- iterations: 0,
}
}
}
diff --git a/lemu/src/executor/mod.rs b/lemu/src/executor/mod.rs
index 991c09f..41d6696 100644
--- a/lemu/src/executor/mod.rs
+++ b/lemu/src/executor/mod.rs
@@ -33,7 +33,19 @@ pub const BANK_SIZE: usize = 512;
pub const CELL_SIZE: usize = 64;
#[derive(Copy, Clone)]
-pub struct Instruction(pub usize);
+pub struct Instruction(usize);
+
+impl Instruction {
+ /// # Safety
+ /// verify n is valid.
+ pub unsafe fn new(n: usize) -> Self {
+ Self(n)
+ }
+
+ pub fn get(self) -> usize {
+ self.0
+ }
+}
impl std::fmt::Debug for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -86,8 +98,6 @@ pub struct Executor<'varnames, W: Write> {
pub(crate) program: Pin<Box<[PInstr<'varnames>]>>,
/// Counter for the number of instructions we have run so far.
pub instructions_ran: usize,
- /// Counter for the number of iterations we have run so far.
- pub iterations: usize,
}
pub enum UPInstr<'s> {
@@ -118,6 +128,8 @@ pub struct ExecutorContext<'varnames, W: Write> {
pub counter: usize,
pub display: Drawing<'varnames>,
pub output: Option<W>,
+ /// Counter for the number of iterations we have run so far.
+ pub iterations: usize,
}
pub struct DisplayState {
@@ -171,7 +183,6 @@ impl<'s, W: Write> ExecutorContext<'s, W> {
self.memory.get_mut(a)
}
- // please verify n is valid
pub fn jump(&mut self, Instruction(n): Instruction) {
self.counter = n;
}
@@ -229,7 +240,7 @@ impl<'s, W: Write> Executor<'s, W> {
/// Begin code execution.
pub fn run(&mut self) {
while !self.instruction_limit.reached(self.instructions_ran)
- && !self.iteration_limit.reached(self.iterations)
+ && !self.iteration_limit.reached(self.inner.iterations)
{
// SAFETY: we have a check
match unsafe { self.run_current() } {
@@ -244,7 +255,7 @@ impl<'s, W: Write> Executor<'s, W> {
self.inner.counter += 1;
if self.inner.counter >= self.program.len() {
self.inner.counter = 0;
- self.iterations += 1;
+ self.inner.iterations += 1;
self.inner.memory.clear();
}
}
diff --git a/lemu/src/instructions/draw.rs b/lemu/src/instructions/draw.rs
index b090215..405d40b 100644
--- a/lemu/src/instructions/draw.rs
+++ b/lemu/src/instructions/draw.rs
@@ -12,7 +12,6 @@ pub const INSTRS: &[&str] = &[
#[enum_dispatch]
pub trait DrawInstruction<'v> {
- #[allow(unused_variables)]
fn draw(
&self,
mem: &mut LRegistry<'v>,
diff --git a/lemu/src/instructions/mod.rs b/lemu/src/instructions/mod.rs
index a6bd3ba..36fc84d 100644
--- a/lemu/src/instructions/mod.rs
+++ b/lemu/src/instructions/mod.rs
@@ -100,10 +100,7 @@ pub enum Flow {
#[enum_dispatch]
pub trait LInstruction<'v> {
- #[allow(unused_variables)]
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow {
- Flow::Continue
- }
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'v, W>) -> Flow;
}
#[derive(Debug)]
@@ -228,7 +225,16 @@ impl<'v> LInstruction<'v> for Op2<'v> {
#[derive(Debug)]
pub struct End {}
-impl LInstruction<'_> for End {}
+
+impl LInstruction<'_> for End {
+ fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
+ exec.memory.clear();
+ exec.iterations += 1;
+ // SAFETY: if we exist, 0 exists.
+ unsafe { exec.jump(Instruction::new(0)) };
+ Flow::Stay
+ }
+}
#[derive(Debug)]
pub struct AlwaysJump {
@@ -270,7 +276,8 @@ impl<'v> LInstruction<'v> for DynJump<'v> {
if let &LVar::Num(n) = exec.get(&self.to) {
let i = n.round() as usize;
if i < self.proglen {
- exec.jump(Instruction(i));
+ // SAFETY: just checked bounds
+ exec.jump(unsafe { Instruction::new(i) });
return Flow::Stay;
}
}
diff --git a/lemu/src/parser.rs b/lemu/src/parser.rs
index b524bce..4bf85e0 100644
--- a/lemu/src/parser.rs
+++ b/lemu/src/parser.rs
@@ -266,9 +266,9 @@ impl Error<'_> {
msg!("{error}: label not found")
.label(err!(s, "this was supposed to be a (existing) label"));
}
- Self::InvalidJump(Instruction(target), s) => {
+ Self::InvalidJump(target, s) => {
msg!("{error}: invalid jump")
- .label(err!(s, "line#{target} is not in the program"))
+ .label(err!(s, "line#{} is not in the program", target.get()))
.note(format!(
"{help}: there are 0..{} available lines",
source.lines().count()
@@ -471,7 +471,8 @@ pub fn parse<'source, W: Wr>(
unfinished_jumps.push((UJump::Sometimes { a, b, op }, i, executor.last()));
}
} else if let Ok(n) = take_int!(tok.clone()) {
- let to = Instruction(n);
+ // SAFETY: we check at the end of the block that it is valid
+ let to = unsafe { Instruction::new(n) };
let op = tok!()?;
if op == Token::Always {
executor.add(AlwaysJump { to });
@@ -641,13 +642,13 @@ pub fn parse<'source, W: Wr>(
nextline!();
}
- for (j, l, Instruction(i)) in unfinished_jumps {
+ for (j, l, i) in unfinished_jumps {
let to = labels
.iter()
.find(|(v, _)| v == &l)
.ok_or_else(|| err!(LabelNotFound(l)))?
.1;
- executor.program[i] = UPInstr::Instr(match j {
+ executor.program[i.get()] = UPInstr::Instr(match j {
UJump::Always => Instr::from(AlwaysJump { to }),
UJump::Sometimes { a, b, op } => Instr::from(Jump::new(op, to, a, b)),
});