mindustry logic execution, map- and schematic- parsing and rendering
| -rw-r--r-- | lemu/src/executor/builder.rs | 2 | ||||
| -rw-r--r-- | lemu/src/executor/mod.rs | 23 | ||||
| -rw-r--r-- | lemu/src/instructions/draw.rs | 1 | ||||
| -rw-r--r-- | lemu/src/instructions/mod.rs | 19 | ||||
| -rw-r--r-- | lemu/src/parser.rs | 11 |
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)), }); |