mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-03-15 00:16:03 +01:00
improve debugging
This commit is contained in:
parent
c3c24c73fe
commit
7973d9f77b
8 changed files with 189 additions and 32 deletions
|
|
@ -21,6 +21,7 @@ use crate::opts::{Ir, Stmt as IrStmt, StmtKind};
|
|||
use crate::parse::Span;
|
||||
use crate::BumpVec;
|
||||
use bumpalo::Bump;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Stmt {
|
||||
|
|
@ -39,12 +40,18 @@ pub enum Stmt {
|
|||
|
||||
const _: [(); 8] = [(); std::mem::size_of::<Stmt>()];
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Code<'c> {
|
||||
stmts: BumpVec<'c, Stmt>,
|
||||
debug: BumpVec<'c, Span>,
|
||||
}
|
||||
|
||||
impl Debug for Code<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.stmts.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Code<'_> {
|
||||
pub fn stmts(&self) -> &[Stmt] {
|
||||
&self.stmts
|
||||
|
|
|
|||
|
|
@ -7,12 +7,43 @@ use bumpalo::Bump;
|
|||
use owo_colors::OwoColorize;
|
||||
use std::fmt::Display;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod codegen;
|
||||
pub mod codegen_interpreter;
|
||||
pub mod opts;
|
||||
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>;
|
||||
|
||||
pub enum UseProfile {
|
||||
|
|
@ -20,7 +51,7 @@ pub enum UseProfile {
|
|||
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
|
||||
W: Write,
|
||||
R: Read,
|
||||
|
|
@ -29,10 +60,20 @@ where
|
|||
|
||||
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 optimized_ir = opts::optimize(&ir_alloc, &parsed);
|
||||
|
||||
if let Some(DumpKind::Ir) = config.dump {
|
||||
println!("{optimized_ir:#?}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
drop(parsed);
|
||||
drop(ast_alloc);
|
||||
|
||||
|
|
@ -40,11 +81,16 @@ where
|
|||
|
||||
let code = codegen::generate(&cg_alloc, &optimized_ir);
|
||||
|
||||
if let Some(DumpKind::Code) = config.dump {
|
||||
println!("{code:#?}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
drop(optimized_ir);
|
||||
drop(ir_alloc);
|
||||
|
||||
match use_profile {
|
||||
UseProfile::Yes => {
|
||||
match config.profile {
|
||||
true => {
|
||||
let mut code_profile_count = vec![0; code.debug().len()];
|
||||
|
||||
codegen_interpreter::run(&code, stdout, stdin, |ip| unsafe {
|
||||
|
|
@ -65,7 +111,7 @@ where
|
|||
print!("{}", color_by_profile(char as char, value, max));
|
||||
}
|
||||
}
|
||||
UseProfile::No => {
|
||||
false => {
|
||||
codegen_interpreter::run(&code, stdout, stdin, |_| {});
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +136,7 @@ fn color_by_profile(char: char, value: u64, max: u64) -> impl Display {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::UseProfile;
|
||||
use crate::Args;
|
||||
|
||||
#[test]
|
||||
fn fizzbuzz() {
|
||||
|
|
@ -98,7 +144,7 @@ mod tests {
|
|||
let mut stdout = Vec::new();
|
||||
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,24 @@
|
|||
#![feature(allocator_api, let_else)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use brainfuck::UseProfile;
|
||||
use std::{env, fs, io, process};
|
||||
use brainfuck::Args;
|
||||
use clap::Parser;
|
||||
use std::{fs, io, process};
|
||||
|
||||
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 = stdout.lock();
|
||||
let stdin = io::stdin();
|
||||
let stdin = stdin.lock();
|
||||
|
||||
let profile = env::args()
|
||||
.any(|a| a == "--profile")
|
||||
.then(|| UseProfile::Yes)
|
||||
.unwrap_or(UseProfile::No);
|
||||
let args = Args::parse();
|
||||
|
||||
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");
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
use crate::parse::{Instr, Span};
|
||||
use crate::BumpVec;
|
||||
use bumpalo::Bump;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Ir<'ir> {
|
||||
pub stmts: BumpVec<'ir, Stmt<'ir>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Stmt<'ir> {
|
||||
pub kind: StmtKind<'ir>,
|
||||
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)]
|
||||
pub enum StmtKind<'ir> {
|
||||
Add(u8),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use bumpalo::Bump;
|
||||
use std::cmp;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct Span {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue