mindustry logic execution, map- and schematic- parsing and rendering
use lerr instead of yumy
| -rw-r--r-- | lemu/Cargo.toml | 6 | ||||
| -rw-r--r-- | lemu/src/executor/mod.rs | 5 | ||||
| -rw-r--r-- | lemu/src/instructions/draw.rs | 2 | ||||
| -rw-r--r-- | lemu/src/main.rs | 5 | ||||
| -rw-r--r-- | lemu/src/parser.rs | 154 |
5 files changed, 85 insertions, 87 deletions
diff --git a/lemu/Cargo.toml b/lemu/Cargo.toml index f4715bc..37465ba 100644 --- a/lemu/Cargo.toml +++ b/lemu/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lemu" -version = "0.1.5" +version = "0.2.0" edition = "2021" description = "M-LOG runner" authors = ["bend-n <[email protected]>"] @@ -14,13 +14,13 @@ thiserror = "1.0" enum_dispatch = "0.3" fimg = { version = "0.4", default-features = false } logos = "0.13.0" -yumy = { version = "0.2.1", optional = true } rust-fuzzy-search = { version = "0.1.1", optional = true } beef = "0.5" +lerr = { version = "0.1.1", optional = true } [features] bin = ["fimg/save", "diagnose"] -diagnose = ["rust-fuzzy-search", "yumy"] +diagnose = ["rust-fuzzy-search", "lerr"] __send__ = [] default = ["bin"] diff --git a/lemu/src/executor/mod.rs b/lemu/src/executor/mod.rs index 7d5fc60..f436916 100644 --- a/lemu/src/executor/mod.rs +++ b/lemu/src/executor/mod.rs @@ -9,6 +9,11 @@ use std::{collections::VecDeque, io::Write, num::NonZeroUsize, pin::Pin}; #[derive(Debug, Copy, Clone)] pub struct Display(pub usize); +impl Default for Display { + fn default() -> Self { + Self(1) + } +} #[derive(Debug, Copy, Clone)] // negative means bank, positive means cell pub struct Memory(pub(crate) i8); diff --git a/lemu/src/instructions/draw.rs b/lemu/src/instructions/draw.rs index fcd7dc6..bfeaf66 100644 --- a/lemu/src/instructions/draw.rs +++ b/lemu/src/instructions/draw.rs @@ -220,7 +220,7 @@ impl<'v> DrawInstruction<'v> for Triangle<'v> { } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Flush { pub(crate) display: Display, } diff --git a/lemu/src/main.rs b/lemu/src/main.rs index b40c8ad..b0a2022 100644 --- a/lemu/src/main.rs +++ b/lemu/src/main.rs @@ -4,7 +4,6 @@ use std::{ }; use lemu::{Executor, Output}; -use yumy::Config; fn main() -> ExitCode { let mut args = std::env::args(); @@ -15,9 +14,7 @@ fn main() -> ExitCode { match Executor::with_output(io::stdout()).display().program(&f) { Ok(x) => x, Err(e) => { - e.diagnose(&f, Some(&file)) - .eprint(&Config::default()) - .unwrap(); + eprint!("{}", e.diagnose(&f)); return ExitCode::FAILURE; } }; diff --git a/lemu/src/parser.rs b/lemu/src/parser.rs index cef379e..3290af6 100644 --- a/lemu/src/parser.rs +++ b/lemu/src/parser.rs @@ -190,125 +190,116 @@ macro_rules! tokstr { } impl Error<'_> { - /// Produces a [`Diagnostic`] from this error. + /// Produces a [`Error`](lerr::Error) from this error. #[cfg(feature = "diagnose")] - pub fn diagnose<'s>( - &self, - source: &'s str, - fname: Option<&'s str>, - ) -> yumy::Diagnostic<yumy::Source<'s>> { - use yumy::{ - owo_colors::{OwoColorize, Style}, - Diagnostic, Label, Source, SourceSpan, - }; + pub fn diagnose<'s>(&self, source: &'s str) -> lerr::Error<'s> { + use lerr::Error; - let error = "error".red(); - let note = "note".blue(); - let help = "help".green(); - let e_sty = Style::new().red(); + let error = "[1;34;31merror[0m"; + let note = "[1;34;34mnote[0m"; + let help = "[1;34;32mhelp[0m"; macro_rules! err { ($span:expr, $msg:literal $(, $args:expr)* $(,)?) => { - Label::styled(SourceSpan::new($span.start as u32, $span.end as u32), format!($msg $(, $args)*), e_sty) + (($span.clone(), format!($msg $(, $args)*))) }; } - macro_rules! dig { + let mut e = Error::new(source); + macro_rules! msg { ($ms:literal $(, $args:expr)* $(,)?) => { - Diagnostic::new(format!($ms $(, $args)*)).with_source(Source::new(source, fname)) + e.message(format!($ms $(, $args)*)) }; } - let mut d; match self { - Error::UnexpectedEof => { - d = dig!("{error}: wasnt able to finish read").with_label(err!( - source.len() - 1..source.len() - 1, + Self::UnexpectedEof => { + msg!("{error}: wasnt able to finish read").label(err!( + source.len()..source.len(), "there was supposed to be another token here" )); } - Error::ExpectedVar(_, s) => { - d = dig!("{error}: expected a variable") - .with_label(err!(s, "this was supposed to be a variable")); + Self::ExpectedVar(_, s) => { + msg!("{error}: expected a variable") + .label(err!(s, "this was supposed to be a variable")); } - Error::ExpectedIdent(_, s) => { - d = dig!("{error}: expected a identifier") - .with_label(err!(s, "this was supposed to be a identifier")); + Self::ExpectedIdent(_, s) => { + msg!("{error}: expected a identifier") + .label(err!(s, "this was supposed to be a identifier")); } - Error::ExpectedJump(t, s) => { - d = dig!("{error}: expected jump target") - .with_label(err!(s, "this was supposed to be a jump target")) - .with_footnote( + Self::ExpectedJump(t, s) => { + msg!("{error}: expected jump target") + .label(err!(s, "this was supposed to be a jump target")) + .note( format!("{note}: a jump target is a label(ident), or a line number in integer form (not a float)"), ); if let Token::Num(n) = t { - d.add_footnote(format!("{help}: remove the fractional part: {n:.0}")); + e.note(format!("{help}: remove the fractional part: {n:.0}")); } } - Error::ExpectedNum(_, s) => { - d = dig!("{error}: expected number") - .with_label(err!(s, "this was supposed to be a number")); + Self::ExpectedNum(_, s) => { + msg!("{error}: expected number").label(err!(s, "this was supposed to be a number")); } - Error::ExpectedOp(t, s) => { - d = dig!("{error}: expected operator") - .with_label(err!(s, "this was supposed to be a operator")); + Self::ExpectedOp(t, s) => { + msg!("{error}: expected operator") + .label(err!(s, "this was supposed to be a operator")); if let Some(i) = tokstr!(*t) && let Some((mat,score)) = rust_fuzzy_search::fuzzy_search_best_n(i, crate::instructions::OPS, 1).first() && *score > 0.5 { - d.add_footnote(format!("{help}: maybe you meant {mat}")); + e.note(format!("{help}: maybe you meant {mat}")); } } - Error::ExpectedInt(t, s) => { - d = dig!("{error}: expected integer") - .with_label(err!(s, "this was supposed to be a integer")); + Self::ExpectedInt(t, s) => { + msg!("{error}: expected integer") + .label(err!(s, "this was supposed to be a integer")); if let Token::Num(n) = t { - d.add_footnote(format!("{help}: remove the fractional part: {n:.0}")); + e.note(format!("{help}: remove the fractional part: {n:.0}")); } } - Error::ExpectedInstr(_, s) => { - d = dig!("{error}: expected instruction") - .with_label(err!(s, "this was supposed to be a instruction")); + Self::ExpectedInstr(_, s) => { + msg!("{error}: expected instruction") + .label(err!(s, "this was supposed to be a instruction")); // it occurs to me that this wont ever be a string, as idents are turned into `Code` // if let Some(i) = tokstr!(t.clone()) && let Some((mat,score)) = rust_fuzzy_search::fuzzy_search_best_n(i, crate::instructions::INSTRS, 1).get(0) && *score > 0.5 { - // d.add_footnote(format!("{help}: maybe you meant {mat}")); + // e.note(format!("{help}: maybe you meant {mat}")); // } } - Error::LabelNotFound(_, s) => { - d = dig!("{error}: label not found") - .with_label(err!(s, "this was supposed to be a (existing) label")); + Self::LabelNotFound(_, s) => { + msg!("{error}: label not found") + .label(err!(s, "this was supposed to be a (existing) label")); } - Error::InvalidJump(Instruction(target), s) => { - d = dig!("{error}: invalid jump") - .with_label(err!(s, "line#{target} is not in the program")) - .with_footnote(format!( + Self::InvalidJump(Instruction(target), s) => { + msg!("{error}: invalid jump") + .label(err!(s, "line#{target} is not in the program")) + .note(format!( "{help}: there are 0..{} available lines", source.lines().count() )); } - Error::MemoryTooFar(b, s) => { - d = dig!("{error}: invalid memory cell/bank") - .with_label(err!(s, "cant get cell/bank#{b}")) - .with_footnote(format!("{note}: only 126 cells/banks are allowed")); + Self::MemoryTooFar(b, s) => { + msg!("{error}: invalid memory cell/bank") + .label(err!(s, "cant get cell/bank#{b}")) + .note(format!("{note}: only 126 cells/banks are allowed")); } - Error::InvalidMemoryType(t, s) => { - d = dig!("{error}: invalid memory type") - .with_label(err!(s, "cant get {t}")) - .with_footnote(format!("{note}: only banks/cells are allowed")); + Self::InvalidMemoryType(t, s) => { + msg!("{error}: invalid memory type") + .label(err!(s, "cant get {t}")) + .note(format!("{note}: only banks/cells are allowed")); } - Error::InvalidDisplayType(disp, s) => { - d = dig!("{error}: invalid display type") - .with_label(err!(s, "cant get {disp}")) - .with_footnote(format!("{help}: change this to 'display'")); + Self::InvalidDisplayType(disp, s) => { + msg!("{error}: invalid display type") + .label(err!(s, "cant get {disp}")) + .note(format!("{help}: change this to 'display'")); } - Error::UnsupportedImageOp(op, s) => { - d = dig!("{error}: invalid image op").with_label(err!( + Self::UnsupportedImageOp(op, s) => { + msg!("{error}: invalid image op").label(err!( s, "must be one of {{clear, color, col, stroke, line, rect, lineRect, triangle}}" )); if let Some((mat,score)) = rust_fuzzy_search::fuzzy_search_best_n(op, crate::instructions::draw::INSTRS, 1).first() && *score > 0.5 { - d.add_footnote(format!("{help}: you may have meant {mat}")); + e.note(format!("{help}: you may have meant {mat}")); } } - Error::NoDisplay(disp, s) => { - d = dig!("{error}: no display allocated").with_label(err!(s, "display#{disp} has not been created")).with_footnote(format!("{note}: it is impossible for me to dynamically allocate displays, as 'display1' could be large or small")); + Self::NoDisplay(disp, s) => { + msg!("{error}: no display allocated").label(err!(s, "display#{disp} has not been created")).note(format!("{note}: it is impossible for me to dynamically allocate displays, as 'display1' could be large or small")); } }; - d + e } } @@ -591,14 +582,19 @@ pub fn parse<'source, W: Wr>( } } Token::DrawFlush => { - let screen = take_ident!(tok!()?)?; - if screen != "display" { - yeet!(InvalidDisplayType(screen)); + let t = tok!(); + if let Ok(t) = t { + let screen = take_ident!(t)?; + if screen != "display" { + yeet!(InvalidDisplayType(screen)); + } + let display = executor + .display(take_int!(tok!()?)?) + .map_err(|n| err!(NoDisplay(n)))?; + executor.add(Flush { display }); + } else { + executor.add(Flush::default()) } - let display = executor - .display(take_int!(tok!()?)?) - .map_err(|n| err!(NoDisplay(n)))?; - executor.add(Flush { display }); } // end Token::End => { |