diff --git a/Cargo.lock b/Cargo.lock index 0731014..ebf14b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + [[package]] name = "cc" version = "1.1.13" @@ -247,6 +253,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dot-writer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1b11bd5e7e98406c6ff39fbc94d6e910a489b978ce7f17c19fce91a1195b7a" + [[package]] name = "either" version = "1.13.0" @@ -259,12 +271,29 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "equidistributed-colors" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c50ea7fb7cbfcbd6ee5cc861b13efee77a4e64a1ac61b5f21fa30c5dd9a9" +dependencies = [ + "hsl", + "oklab", + "rgb", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fnv" version = "1.0.7" @@ -289,6 +318,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hsl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575fb7f1167f3b88ed825e90eb14918ac460461fdeaa3965c6a50951dee1c970" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -403,6 +438,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oklab" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e35ab3c8efa6bc97d651abe7fb051aebb30c925a450ff6722cf9c797a938cc" +dependencies = [ + "fast-srgb8", + "rgb", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -462,6 +507,15 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -547,6 +601,8 @@ dependencies = [ "ariadne", "clap", "deku", + "dot-writer", + "equidistributed-colors", "itertools", "test-files", "tifloats", diff --git a/ti-basic-optimizer/Cargo.toml b/ti-basic-optimizer/Cargo.toml index 8beb26d..dd8abdb 100644 --- a/ti-basic-optimizer/Cargo.toml +++ b/ti-basic-optimizer/Cargo.toml @@ -10,9 +10,13 @@ tifloats = { git = "https://github.com/TI-Toolkit/tifloats_lib_rs.git" } itertools = "0.13.0" ariadne = "0.4.1" deku = "0.17.0" +dot-writer = { version = "0.1.3", optional = true } +equidistributed-colors = { version = "0.1.0", optional = true } +test-files = { path = "../test-files", optional = true } [dev-dependencies] test-files = { path = "../test-files" } [features] -round-trip = [] \ No newline at end of file +round-trip = [] +debug-tools = ["test-files", "dot-writer", "equidistributed-colors"] \ No newline at end of file diff --git a/ti-basic-optimizer/src/analyze/control_flow/graph/graphviz.rs b/ti-basic-optimizer/src/analyze/control_flow/graph/graphviz.rs new file mode 100644 index 0000000..cc412cc --- /dev/null +++ b/ti-basic-optimizer/src/analyze/control_flow/graph/graphviz.rs @@ -0,0 +1,47 @@ +use std::fmt::Debug; + +use dot_writer::{DotWriter, Scope}; + +use equidistributed_colors::EquiColor; + +static mut COLORS: Option = None; + +pub fn next_color() -> String { + let color = unsafe { + if COLORS.is_none() { + COLORS = Some(EquiColor::new(0.5, 0.5)) + } + + COLORS.unwrap().next().unwrap() + }; + + format!("#{:02X}{:02X}{:02X}", color.r, color.g, color.b) +} + +pub trait Visualize { + fn visualize(&self, context: &mut Scope, config: T); +} + +pub trait Graphviz { + fn graphviz(&self, writer: &mut DotWriter); +} + +impl Debug for dyn Graphviz { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut output_bytes = Vec::new(); + { + let mut writer = DotWriter::from(&mut output_bytes); + + self.graphviz(&mut writer); + } + + f.write_str(&String::from_utf8(output_bytes).unwrap()) + } +} + +pub fn escape(string: &str) -> String { + string + .replace('\\', "\\\\") + .replace('\n', "\\n") + .replace('"', "\\\"") +} diff --git a/ti-basic-optimizer/src/parse/mod.rs b/ti-basic-optimizer/src/parse/mod.rs index 9dc3eb8..bc5ef7f 100644 --- a/ti-basic-optimizer/src/parse/mod.rs +++ b/ti-basic-optimizer/src/parse/mod.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use titokens::{Token, Tokens}; pub mod commands; @@ -16,3 +17,30 @@ pub(crate) trait Parse: Sized { pub(crate) trait Reconstruct { fn reconstruct(&self, config: &Config) -> Vec; } + +#[cfg(feature = "debug-tools")] +pub trait Stringify { + fn stringify(&self, config: Option<&titokens::Tokenizer>) -> String; +} + +#[cfg(feature = "debug-tools")] +impl Stringify for T +where + T: Reconstruct, +{ + fn stringify(&self, config: Option<&titokens::Tokenizer>) -> String { + match config { + Some(tokenizer) => tokenizer + .stringify(&self.reconstruct(&test_files::test_version!().into())) + .to_string(), + None => self + .reconstruct(&test_files::test_version!().into()) + .iter() + .map(|token| match token { + Token::OneByte(b) => format!("{:02X}", b), + Token::TwoByte(a, b) => format!("{:02X}{:02X}", a, b), + }) + .join("\u{202f}"), // NNBSP + } + } +}