mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/executor/mod.rs')
-rw-r--r--lemu/src/executor/mod.rs320
1 files changed, 0 insertions, 320 deletions
diff --git a/lemu/src/executor/mod.rs b/lemu/src/executor/mod.rs
deleted file mode 100644
index 0989bc0..0000000
--- a/lemu/src/executor/mod.rs
+++ /dev/null
@@ -1,320 +0,0 @@
-mod builder;
-const COUNTER: LAddress = unsafe { LAddress::addr(0) };
-use crate::{
- debug::{info::DebugInfo, printable::Printable},
- instructions::draw::Drawn,
-};
-
-use super::{
- code::{Code, PInstr},
- instructions::{DrawInstr, Flow, Frozen, Instr, LInstruction},
- lexer::Token,
- memory::{LAddress, LRegistry, LVar},
-};
-pub use builder::ExecutorBuilderInternal;
-use fimg::Image;
-use std::{collections::VecDeque, io::Write, num::NonZeroUsize};
-
-#[derive(Debug, Copy, Clone, Default)]
-pub struct Display(pub usize);
-
-impl std::fmt::Display for Display {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "display{}", self.0 + 1)
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum Memory {
- Cell(u8),
- Bank(u8),
-}
-
-impl Memory {
- pub(crate) const fn fits(self, i: usize) -> bool {
- match self {
- Self::Bank(_) => i < BANK_SIZE,
- Self::Cell(_) => i < CELL_SIZE,
- }
- }
-
- pub(crate) const fn size(&self) -> usize {
- match self {
- Self::Bank(_) => BANK_SIZE,
- Self::Cell(_) => CELL_SIZE,
- }
- }
-}
-
-impl std::fmt::Display for Memory {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Bank(n) => write!(f, "bank{}", n + 1),
- Self::Cell(n) => write!(f, "cell{}", n + 1),
- }
- }
-}
-
-pub const BANK_SIZE: usize = 512;
-pub const CELL_SIZE: usize = 64;
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub struct Instruction(usize);
-
-impl Instruction {
- /// # Safety
- /// verify n is valid.
- pub const unsafe fn new(n: usize) -> Self {
- Self(n)
- }
-
- pub const fn get(self) -> usize {
- self.0
- }
-}
-
-impl std::fmt::Debug for Instruction {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "Instruction#{}", self.0)
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum Limit {
- /// limited to n
- Limited(NonZeroUsize),
- /// unlimited
- Unlimited,
-}
-
-impl Limit {
- /// panics if n != 0
- pub fn limited(n: usize) -> Self {
- Self::Limited(n.try_into().expect("nonzero"))
- }
-}
-
-impl Limit {
- pub(crate) const fn reached(self, n: usize) -> bool {
- match self {
- Self::Limited(v) => v.get() <= n,
- Self::Unlimited => false,
- }
- }
-}
-
-/// One time use logic executor.
-pub struct Executor<'varnames, W: Write> {
- /// if limited, will run n instructions before exiting.
- pub instruction_limit: Limit,
- /// if limtited, will loop(go from a end to the start) n times before exiting
- /// both unlimited does not mean this function will never return;
- /// a `Stop` instruction will break the loop.
- pub iteration_limit: Limit,
- pub(crate) inner: ExecutorContext<'varnames, W>,
- /// gets pointed to by drawbuf (pls no move)
- pub(crate) program: Code<'varnames>,
- /// Counter for the number of instructions we have run so far.
- pub instructions_ran: usize,
- debug_info: DebugInfo<'varnames>,
-}
-
-impl<W: Write> std::fmt::Display for Executor<'_, W> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.program.print(&self.debug_info, f)
- }
-}
-
-#[derive(Debug)]
-pub enum UPInstr<'s> {
- Instr(Instr),
- Draw(DrawInstr),
- UnfinishedJump,
- Code(Box<[Token<'s>]>),
- Comment(&'s str),
-}
-
-pub struct Drawing {
- pub displays: Box<[(fimg::Image<Vec<u8>, 4>, DisplayState)]>,
- pub buffer: VecDeque<Drawn>,
-}
-
-impl Drawing {
- fn buffer(&mut self, i: Drawn) {
- self.buffer.push_back(i);
- }
-}
-pub struct ExecutorContext<'strings, W: Write> {
- // maximum of 128 elements, so can use ~60KB
- pub cells: Box<[[f64; CELL_SIZE]]>, // screw world cells
- // maximum of 127 elements, so can use ~500KB
- pub banks: Box<[[f64; BANK_SIZE]]>,
- pub memory: LRegistry<'strings>,
- pub display: Drawing,
- pub output: Option<W>,
- /// Counter for the number of iterations we have run so far.
- pub iterations: usize,
-}
-
-/// State of a display.
-#[derive(Debug)]
-pub struct DisplayState {
- /// Color to draw
- pub color: (u8, u8, u8, u8),
- /// Stroke to draw
- pub stroke: f64,
-}
-
-impl DisplayState {
- pub const fn col(&self) -> [u8; 4] {
- [self.color.0, self.color.1, self.color.2, self.color.3]
- }
-}
-
-impl Default for DisplayState {
- fn default() -> Self {
- Self {
- color: Default::default(),
- stroke: 5.0,
- }
- }
-}
-
-impl<'s, W: Write> ExecutorContext<'s, W> {
- pub fn flush(&mut self, to: Display) {
- let (img, state) = &mut self.display.displays[to.0];
- while let Some(d) = self.display.buffer.pop_front() {
- use crate::instructions::draw::Apply;
- #[cfg(feature = "debug")]
- comat::cprintln!("{d:blue}");
- d.apply(img.as_mut(), state);
- }
- }
-
- pub fn mem(&mut self, m: Memory) -> &mut [f64] {
- match m {
- Memory::Bank(m) => &mut self.banks[m as usize],
- Memory::Cell(m) => &mut self.cells[m as usize],
- }
- }
-
- pub fn set(&mut self, a: LAddress, b: LAddress) {
- self.memory[a] = self.memory[b].clone();
- }
-
- pub fn get_mut(&mut self, a: LAddress) -> &mut LVar<'s> {
- &mut self.memory[a]
- }
-
- pub fn jump(&mut self, Instruction(n): Instruction) {
- *self.counter() = n as f64;
- }
-
- pub fn counter(&mut self) -> &mut f64 {
- unsafe {
- self.memory
- .0
- .get_unchecked_mut(0)
- .num_mut()
- .unwrap_unchecked()
- }
- }
-
- pub fn get<'a>(&'a self, a: LAddress) -> &LVar<'s> {
- &self.memory[a]
- }
-}
-
-/// Returned by the [`output`](Executor::output).function.
-pub struct Output<W: Write> {
- /// Everything created by a `print` instruction.
- pub output: Option<W>,
- /// Logic displays that were drawn with `draw` instructions.
- pub displays: Box<[(Image<Vec<u8>, 4>, DisplayState)]>,
- /// Memory banks, written to with the `write`/`read` instructions
- pub cells: Box<[[f64; CELL_SIZE]]>,
- /// Memory cells, written to with the `write`/`read` instructions
- pub banks: Box<[[f64; BANK_SIZE]]>,
-}
-
-impl<'s, W: Write> Executor<'s, W> {
- /// Consume this executor, returning all output.
- pub fn output(mut self) -> Output<W> {
- for (display, _) in &mut *self.inner.display.displays {
- // TODO make the instructions draw flipped-ly
- display.flip_v();
- }
- Output {
- output: self.inner.output,
- displays: self.inner.display.displays,
- cells: self.inner.cells,
- banks: self.inner.banks,
- }
- }
-
- /// # Safety
- ///
- /// `counter` *must* be in bounds.
- unsafe fn run_current(&mut self) -> Flow {
- // SAFETY: yee
- let c = self.inner.counter();
- let i = unsafe { self.program.get_unchecked(*c as usize) };
- *c += 1.0;
- match i {
- PInstr::Instr(i) => {
- #[cfg(feature = "debug")]
- {
- let mut instr = String::new();
- i.print(&self.debug_info, &mut instr).unwrap();
- let mut mem = String::new();
- self.inner.memory.print(&self.debug_info, &mut mem).unwrap();
- comat::cprintln!(
- "{black}{:0<2} | {green}{instr} {black}({mem}){reset}",
- self.inner.counter(),
- );
- }
-
- i.run(&mut self.inner)
- }
- PInstr::Draw(i) => {
- if let Some(i) = i.freeze(&self.inner.memory) {
- #[cfg(feature = "debug")]
- {
- let mut mem = String::new();
- self.inner.memory.print(&self.debug_info, &mut mem).unwrap();
- comat::cprintln!(
- "{black}{:0<2} | {magenta}{i} {black}({mem}){reset}",
- self.inner.counter()
- );
- }
- self.inner.display.buffer(i)
- }
- Flow::Continue
- }
- _ => Flow::Continue,
- }
- }
-
- /// Begin code execution.
- pub fn run(&mut self) {
- while !self.instruction_limit.reached(self.instructions_ran)
- && !self.iteration_limit.reached(self.inner.iterations)
- {
- // SAFETY: we have a check
- match unsafe { self.run_current() } {
- Flow::Continue => {}
- Flow::Exit => break,
- Flow::Stay => {
- self.instructions_ran += 1;
- continue;
- }
- };
- self.instructions_ran += 1;
- let c = self.inner.counter();
- if *c as usize >= self.program.len() {
- *c = 0.0;
- self.inner.iterations += 1;
- }
- }
- }
-}