mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/instructions/mod.rs')
-rw-r--r--lemu/src/instructions/mod.rs500
1 files changed, 0 insertions, 500 deletions
diff --git a/lemu/src/instructions/mod.rs b/lemu/src/instructions/mod.rs
deleted file mode 100644
index 6724ed1..0000000
--- a/lemu/src/instructions/mod.rs
+++ /dev/null
@@ -1,500 +0,0 @@
-//! supported instrs
-//!
-//! ```text
-//! jump
-//! op
-//! stop
-//! end
-//! set
-//! read
-//! write
-//! print
-//! packcolor
-//!
-//! draw {color, col, flush, line, rect, lineRect, triangle, stroke, clear}
-//! ```
-mod cop;
-pub mod draw;
-pub mod io;
-mod mop;
-mod mop2;
-
-pub use cop::ConditionOp;
-pub use draw::{DrawInstr, Frozen};
-use enum_dispatch::enum_dispatch;
-pub use mop::MathOp1;
-pub use mop2::MathOp2;
-use std::{fmt, io::Write};
-
-use crate::debug::{info::DebugInfo, printable::Printable};
-
-use super::{
- executor::{ExecutorContext, Instruction},
- memory::{LAddress, LVar},
-};
-
-pub const OPS: &[&str] = &[
- "equal",
- "notEqual",
- "lessThan",
- "lessThanEq",
- "greaterThan",
- "greaterThanEq",
- "strictEqual",
- "always",
- "add",
- "sub",
- "mul",
- "div",
- "idiv",
- "mod",
- "pow",
- "land",
- "not",
- "shl",
- "shr",
- "or",
- "and",
- "xor",
- "max",
- "min",
- "angle",
- "angleDiff",
- "len",
- "noise",
- "abs",
- "log",
- "log10",
- "floor",
- "ceil",
- "sqrt",
- "rand",
- "sin",
- "cos",
- "tan",
- "asin",
- "acos",
- "atan",
-];
-
-#[must_use = "to change control flow"]
-#[derive(Default)]
-pub enum Flow {
- #[default]
- Continue,
- Stay,
- Exit,
-}
-
-#[enum_dispatch]
-pub trait LInstruction: Printable {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow;
-}
-
-#[derive(Debug, Copy, Clone)]
-#[enum_dispatch(LInstruction)]
-pub enum Instr {
- Op2(Op2),
- Jump(Jump),
- AlwaysJump(AlwaysJump),
- Set(Set),
- Op1(Op1),
- Read(io::Read),
- Write(io::Write),
- DrawFlush(draw::Flush),
- DynJump(DynJump),
- Print(io::Print),
- Stop(Stop),
- PackColor(PackColor),
- Select(Select),
- Noop(Noop),
- End(End),
-}
-
-impl Printable for Instr {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- match self {
- Self::Op2(i) => i.print(info, f),
- Self::Jump(i) => i.print(info, f),
- Self::AlwaysJump(i) => i.print(info, f),
- Self::Set(i) => i.print(info, f),
- Self::Op1(i) => i.print(info, f),
- Self::Read(i) => i.print(info, f),
- Self::Write(i) => i.print(info, f),
- Self::DrawFlush(i) => i.print(info, f),
- Self::DynJump(i) => i.print(info, f),
- Self::Print(i) => i.print(info, f),
- Self::Stop(i) => i.print(info, f),
- Self::End(i) => i.print(info, f),
- Self::PackColor(i) => i.print(info, f),
- Self::Select(i) => i.print(info, f),
- Self::Noop(i) => i.print(info, f),
- }
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct Set {
- pub(crate) from: LAddress,
- pub(crate) to: LAddress,
-}
-impl LInstruction for Set {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- exec.set(self.from, self.to);
- Flow::Continue
- }
-}
-
-impl Printable for Set {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "set {} {}", info[self.from], info[self.to])
- }
-}
-
-macro_rules! op_enum {
- ($v:vis enum $name:ident {
- $($variant:ident),+ $(,)?
- }) => {
- #[derive(Debug, Copy, Clone, Eq, PartialEq)]
- $v enum $name {
- $($variant),+
- }
-
- impl<'a> TryFrom<Token<'a>> for $name {
- type Error = Token<'a>;
- fn try_from(value: Token<'a>) -> Result<Self, Self::Error> {
- match value {
- $(Token::$variant => Ok(Self::$variant),)+
- v => Err(v)
- }
- }
- }
-
- impl std::fmt::Display for $name {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
- write!(f, "{}", Token::from(*self))
- }
- }
-
- impl<'a> From<$name> for Token<'a> {
- fn from(value: $name) -> Self {
- match value {
- $($name::$variant => Self::$variant,)+
- }
- }
- }
- }
-}
-use op_enum;
-
-// not part of op_enum due to rem
-macro_rules! op_impl {
- ($name:ident, ptr type = $ptr:ty { $($own:ident => $fn:ident,)+ }) => {
- impl $name {
- pub const fn get_fn(self) -> $ptr {
- match self {
- $(Self::$own => $fn,)+
- }
- }
- }
-
- impl TryFrom<$ptr> for $name {
- type Error = ();
- fn try_from(f:$ptr) -> Result<Self, ()> {
- match f {
- $(f if f == $fn => Ok(Self::$own),)+
- _ => Err(()),
- }
- }
- }
- }
-}
-use op_impl;
-
-macro_rules! get_num {
- ($x:expr) => {
- match $x {
- LVar::Num(x) => *x,
- _ => return Default::default(),
- }
- };
-}
-use get_num;
-
-#[derive(Debug, Copy, Clone)]
-pub struct Op1 {
- op: for<'v> fn(&LVar<'v>) -> f64,
- x: LAddress,
- out: LAddress,
-}
-impl Op1 {
- pub(crate) const fn new(op: MathOp1, x: LAddress, out: LAddress) -> Self {
- Self {
- op: op.get_fn(),
- x,
- out,
- }
- }
-}
-
-impl LInstruction for Op1 {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- let x = (self.op)(exec.get(self.x));
- *exec.get_mut(self.out) = LVar::Num(x);
- Flow::Continue
- }
-}
-
-impl Printable for Op1 {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- let op = mop::MathOp1::try_from(self.op).unwrap();
- write!(f, "op {op} {} {}", info[self.out], info[self.x])
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct Op2 {
- op: for<'v> fn(&LVar<'v>, &LVar<'v>) -> f64,
- a: LAddress,
- b: LAddress,
- out: LAddress,
-}
-impl Op2 {
- pub(crate) const fn new(op: MathOp2, a: LAddress, b: LAddress, out: LAddress) -> Self {
- Self {
- op: op.get_fn(),
- a,
- b,
- out,
- }
- }
-}
-
-impl LInstruction for Op2 {
- #[inline]
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- let x = (self.op)(exec.get(self.a), exec.get(self.b));
- exec.memory[self.out] = LVar::Num(x);
- Flow::Continue
- }
-}
-
-impl Printable for Op2 {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- let op = mop2::MathOp2::try_from(self.op).unwrap();
- write!(
- f,
- "op {op} {} {} {}",
- info[self.out], info[self.a], info[self.b]
- )
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct End {}
-
-impl LInstruction for End {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- exec.iterations += 1;
- // SAFETY: if we exist, 0 exists.
- unsafe { exec.jump(Instruction::new(0)) };
- Flow::Stay
- }
-}
-
-impl Printable for End {
- fn print(&self, _: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "end")
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct Noop {}
-
-impl LInstruction for Noop {
- fn run<W: Write>(&self, _: &mut ExecutorContext<'_, W>) -> Flow {
- Flow::Continue
- }
-}
-
-impl Printable for Noop {
- fn print(&self, _: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "noop")
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct AlwaysJump {
- pub(crate) to: Instruction,
-}
-impl LInstruction for AlwaysJump {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- exec.jump(self.to);
- Flow::Stay
- }
-}
-
-impl Printable for AlwaysJump {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "jump ")?;
- match info.label(self.to) {
- Some(l) => f.write_str(l)?,
- None => write!(f, "{}", self.to.get())?,
- }
- write!(f, " always")
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct Jump {
- op: for<'v> fn(&LVar<'v>, &LVar<'v>) -> bool,
- pub(crate) to: Instruction,
- a: LAddress,
- b: LAddress,
-}
-impl Jump {
- pub fn new(op: ConditionOp, to: Instruction, a: LAddress, b: LAddress) -> Self {
- Self {
- op: op.get_fn(),
- to,
- a,
- b,
- }
- }
-}
-
-impl LInstruction for Jump {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- if (self.op)(exec.get(self.a), exec.get(self.b)) {
- exec.jump(self.to);
- Flow::Stay
- } else {
- Flow::Continue
- }
- }
-}
-
-impl Printable for Jump {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- let op = ConditionOp::try_from(self.op).unwrap();
- write!(f, "jump {op} ")?;
- match info.label(self.to) {
- Some(l) => f.write_str(l)?,
- None => write!(f, "{}", self.to.get())?,
- };
- write!(f, " {} {}", info[self.a], info[self.b])
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct DynJump {
- pub to: LAddress,
- pub proglen: usize,
-}
-
-impl LInstruction for DynJump {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- if let &LVar::Num(n) = exec.get(self.to) {
- let i = n.round() as usize;
- if i < self.proglen {
- // SAFETY: just checked bounds
- exec.jump(unsafe { Instruction::new(i) });
- return Flow::Stay;
- }
- }
- Flow::Continue
- }
-}
-
-impl Printable for DynJump {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "set @counter {}", info[self.to])
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub struct Stop {}
-impl LInstruction for Stop {
- fn run<W: Write>(&self, _: &mut ExecutorContext<'_, W>) -> Flow {
- Flow::Exit
- }
-}
-
-impl Printable for Stop {
- fn print(&self, _: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(f, "stop")
- }
-}
-
-#[derive(Copy, Clone, Debug)]
-pub struct PackColor {
- pub out: LAddress,
- pub r: LAddress,
- pub g: LAddress,
- pub b: LAddress,
- pub a: LAddress,
-}
-
-impl LInstruction for PackColor {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- macro_rules! num {
- ($($n:ident)+) => {
- ($(match exec.memory[self.$n] {
- LVar::Num(n) => (n.clamp(0.0, 1.0) * 255.0) as u8,
- _ => 255,
- },)+)
- };
- }
- let (r, g, b, a) = num!(r g b a);
- exec.memory[self.out] = LVar::from(fimg::Pack::pack(&[r, g, b, a]) as f64);
- Flow::Continue
- }
-}
-
-impl Printable for PackColor {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(
- f,
- "packcolor {} {} {} {} {}",
- info[self.out], info[self.r], info[self.g], info[self.b], info[self.a]
- )
- }
-}
-#[derive(Debug, Copy, Clone)]
-pub struct Select {
- pub op: for<'v> fn(&LVar<'v>, &LVar<'v>) -> bool,
- pub(crate) to: LAddress,
-
- pub x: LAddress,
- pub y: LAddress,
-
- pub a: LAddress,
- pub b: LAddress,
-}
-
-impl LInstruction for Select {
- fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow {
- *exec.get_mut(self.to) = if (self.op)(exec.get(self.x), exec.get(self.y)) {
- exec.get(self.a)
- } else {
- exec.get(self.b)
- }
- .clone();
- Flow::Continue
- }
-}
-
-impl Printable for Select {
- fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result {
- write!(
- f,
- "select {} {} {} {} {} {}",
- info[self.to],
- ConditionOp::try_from(self.op).unwrap(),
- info[self.x],
- info[self.y],
- info[self.a],
- info[self.b]
- )
- }
-}