improve debugging

This commit is contained in:
nora 2022-04-15 23:33:12 +02:00
parent c3c24c73fe
commit 7973d9f77b
8 changed files with 189 additions and 32 deletions

110
rust2/Cargo.lock generated
View file

@ -30,6 +30,7 @@ name = "brainfuck"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"clap 3.1.9",
"criterion", "criterion",
"insta", "insta",
"owo-colors", "owo-colors",
@ -75,10 +76,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"textwrap", "textwrap 0.11.0",
"unicode-width", "unicode-width",
] ]
[[package]]
name = "clap"
version = "3.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aad2534fad53df1cc12519c5cda696dd3e20e6118a027e24054aea14a0bdcbe"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"lazy_static",
"strsim",
"termcolor",
"textwrap 0.15.0",
]
[[package]]
name = "clap_derive"
version = "3.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d716edb7c26222b1b21de6e6d505b274f9f3db9e7bc2e06baf389d57ae842df8"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "console" name = "console"
version = "0.15.0" version = "0.15.0"
@ -100,7 +140,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [ dependencies = [
"atty", "atty",
"cast", "cast",
"clap", "clap 2.34.0",
"criterion-plot", "criterion-plot",
"csv", "csv",
"itertools", "itertools",
@ -219,6 +259,12 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -355,6 +401,15 @@ version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "owo-colors" name = "owo-colors"
version = "3.3.0" version = "3.3.0"
@ -389,6 +444,30 @@ dependencies = [
"plotters-backend", "plotters-backend",
] ]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.37" version = "1.0.37"
@ -548,6 +627,12 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.91" version = "1.0.91"
@ -559,6 +644,15 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "terminal_size" name = "terminal_size"
version = "0.1.17" version = "0.1.17"
@ -578,6 +672,12 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]] [[package]]
name = "tinytemplate" name = "tinytemplate"
version = "1.2.1" version = "1.2.1"
@ -600,6 +700,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.3.2" version = "2.3.2"

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
bumpalo = { version = "3.9.1", features = ["allocator_api"] } bumpalo = { version = "3.9.1", features = ["allocator_api"] }
clap = { version = "3.1.9", features = ["derive"] }
owo-colors = "3.3.0" owo-colors = "3.3.0"
[dev-dependencies] [dev-dependencies]

View file

@ -21,6 +21,7 @@ use crate::opts::{Ir, Stmt as IrStmt, StmtKind};
use crate::parse::Span; use crate::parse::Span;
use crate::BumpVec; use crate::BumpVec;
use bumpalo::Bump; use bumpalo::Bump;
use std::fmt::{Debug, Formatter};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Stmt { pub enum Stmt {
@ -39,12 +40,18 @@ pub enum Stmt {
const _: [(); 8] = [(); std::mem::size_of::<Stmt>()]; const _: [(); 8] = [(); std::mem::size_of::<Stmt>()];
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct Code<'c> { pub struct Code<'c> {
stmts: BumpVec<'c, Stmt>, stmts: BumpVec<'c, Stmt>,
debug: BumpVec<'c, Span>, debug: BumpVec<'c, Span>,
} }
impl Debug for Code<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.stmts.fmt(f)
}
}
impl Code<'_> { impl Code<'_> {
pub fn stmts(&self) -> &[Stmt] { pub fn stmts(&self) -> &[Stmt] {
&self.stmts &self.stmts

View file

@ -7,12 +7,43 @@ use bumpalo::Bump;
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
use std::fmt::Display; use std::fmt::Display;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::PathBuf;
use std::str::FromStr;
pub mod codegen; pub mod codegen;
pub mod codegen_interpreter; pub mod codegen_interpreter;
pub mod opts; pub mod opts;
pub mod parse; pub mod parse;
#[derive(clap::Parser, Default)]
#[clap(author, about)]
pub struct Args {
#[clap(short, long)]
pub profile: bool,
#[clap(long)]
pub dump: Option<DumpKind>,
pub file: PathBuf,
}
pub enum DumpKind {
Ast,
Ir,
Code,
}
impl FromStr for DumpKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ast" => Ok(Self::Ast),
"ir" => Ok(Self::Ir),
"code" => Ok(Self::Code),
other => Err(format!("Invalid IR level: '{other}'")),
}
}
}
type BumpVec<'a, T> = Vec<T, &'a Bump>; type BumpVec<'a, T> = Vec<T, &'a Bump>;
pub enum UseProfile { pub enum UseProfile {
@ -20,7 +51,7 @@ pub enum UseProfile {
No, No,
} }
pub fn run<R, W>(src: &str, stdout: W, stdin: R, use_profile: UseProfile) -> Result<(), ParseError> pub fn run<R, W>(src: &str, stdout: W, stdin: R, config: &Args) -> Result<(), ParseError>
where where
W: Write, W: Write,
R: Read, R: Read,
@ -29,10 +60,20 @@ where
let parsed = parse::parse(&ast_alloc, src.bytes().enumerate())?; let parsed = parse::parse(&ast_alloc, src.bytes().enumerate())?;
if let Some(DumpKind::Ast) = config.dump {
println!("{parsed:#?}");
return Ok(());
}
let ir_alloc = Bump::new(); let ir_alloc = Bump::new();
let optimized_ir = opts::optimize(&ir_alloc, &parsed); let optimized_ir = opts::optimize(&ir_alloc, &parsed);
if let Some(DumpKind::Ir) = config.dump {
println!("{optimized_ir:#?}");
return Ok(());
}
drop(parsed); drop(parsed);
drop(ast_alloc); drop(ast_alloc);
@ -40,11 +81,16 @@ where
let code = codegen::generate(&cg_alloc, &optimized_ir); let code = codegen::generate(&cg_alloc, &optimized_ir);
if let Some(DumpKind::Code) = config.dump {
println!("{code:#?}");
return Ok(());
}
drop(optimized_ir); drop(optimized_ir);
drop(ir_alloc); drop(ir_alloc);
match use_profile { match config.profile {
UseProfile::Yes => { true => {
let mut code_profile_count = vec![0; code.debug().len()]; let mut code_profile_count = vec![0; code.debug().len()];
codegen_interpreter::run(&code, stdout, stdin, |ip| unsafe { codegen_interpreter::run(&code, stdout, stdin, |ip| unsafe {
@ -65,7 +111,7 @@ where
print!("{}", color_by_profile(char as char, value, max)); print!("{}", color_by_profile(char as char, value, max));
} }
} }
UseProfile::No => { false => {
codegen_interpreter::run(&code, stdout, stdin, |_| {}); codegen_interpreter::run(&code, stdout, stdin, |_| {});
} }
} }
@ -90,7 +136,7 @@ fn color_by_profile(char: char, value: u64, max: u64) -> impl Display {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::UseProfile; use crate::Args;
#[test] #[test]
fn fizzbuzz() { fn fizzbuzz() {
@ -98,7 +144,7 @@ mod tests {
let mut stdout = Vec::new(); let mut stdout = Vec::new();
let stdin = []; let stdin = [];
super::run(str, &mut stdout, stdin.as_slice(), UseProfile::No).unwrap(); super::run(str, &mut stdout, stdin.as_slice(), &Args::default()).unwrap();
insta::assert_debug_snapshot!(String::from_utf8(stdout)); insta::assert_debug_snapshot!(String::from_utf8(stdout));
} }

View file

@ -1,31 +1,24 @@
#![feature(allocator_api, let_else)] #![feature(allocator_api, let_else)]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
use brainfuck::UseProfile; use brainfuck::Args;
use std::{env, fs, io, process}; use clap::Parser;
use std::{fs, io, process};
fn main() { fn main() {
let Some(path) = env::args().nth(1) else {
eprintln!("error: Provide a path as input.");
process::exit(1);
};
let file = fs::read_to_string(path).unwrap_or_else(|err| {
eprintln!("error: Failed to read file: {err}");
process::exit(1);
});
let stdout = io::stdout(); let stdout = io::stdout();
let stdout = stdout.lock(); let stdout = stdout.lock();
let stdin = io::stdin(); let stdin = io::stdin();
let stdin = stdin.lock(); let stdin = stdin.lock();
let profile = env::args() let args = Args::parse();
.any(|a| a == "--profile")
.then(|| UseProfile::Yes)
.unwrap_or(UseProfile::No);
brainfuck::run(&file, stdout, stdin, profile).unwrap_or_else(|_| { let src = fs::read_to_string(&args.file).unwrap_or_else(|err| {
eprintln!("error: Failed to read file: {err}");
process::exit(1);
});
brainfuck::run(&src, stdout, stdin, &args).unwrap_or_else(|_| {
eprintln!("error: Failed to parse brainfuck code"); eprintln!("error: Failed to parse brainfuck code");
process::exit(1); process::exit(1);
}); });

View file

@ -1,13 +1,14 @@
use crate::parse::{Instr, Span}; use crate::parse::{Instr, Span};
use crate::BumpVec; use crate::BumpVec;
use bumpalo::Bump; use bumpalo::Bump;
use std::fmt::{Debug, Formatter};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Ir<'ir> { pub struct Ir<'ir> {
pub stmts: BumpVec<'ir, Stmt<'ir>>, pub stmts: BumpVec<'ir, Stmt<'ir>>,
} }
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct Stmt<'ir> { pub struct Stmt<'ir> {
pub kind: StmtKind<'ir>, pub kind: StmtKind<'ir>,
pub span: Span, pub span: Span,
@ -23,6 +24,12 @@ impl<'ir> Stmt<'ir> {
} }
} }
impl Debug for Stmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Stmt").field(&self.kind).finish()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum StmtKind<'ir> { pub enum StmtKind<'ir> {
Add(u8), Add(u8),

View file

@ -1,5 +1,6 @@
use bumpalo::Bump; use bumpalo::Bump;
use std::cmp; use std::cmp;
use std::fmt::Debug;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Span { pub struct Span {

View file

@ -1,5 +1 @@
Benchmark brainf*ck program ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
++++++++[>++++++++++[>++++++++++[>++++++++++[>+
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.