add pretty print

This commit is contained in:
nora 2022-01-04 23:09:18 +01:00
parent 1a77e710d5
commit 76af14a9f4
11 changed files with 114 additions and 5 deletions

34
Cargo.lock generated
View file

@ -27,11 +27,33 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "debug2"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e70062ea3df6318129246273f4b1748900752293d47e7610b5e8a84bc14c44c"
dependencies = [
"debug2-derive",
]
[[package]]
name = "debug2-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77b37e8941dd632993cf5b4ea33a630faa132fdc42481a8c2621dede631e871a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]] [[package]]
name = "dilaria" name = "dilaria"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"debug2",
"insta", "insta",
"rustc-hash", "rustc-hash",
] ]
@ -187,6 +209,18 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]] [[package]]
name = "terminal_size" name = "terminal_size"
version = "0.1.17" version = "0.1.17"

View file

@ -7,11 +7,16 @@ edition = "2021"
[dependencies] [dependencies]
bumpalo = { version = "3.8.0", features = ["collections", "boxed"] } bumpalo = { version = "3.8.0", features = ["collections", "boxed"] }
debug2 = { version = "0.1.0", optional = true }
rustc-hash = { version = "1.1.0", optional = true } rustc-hash = { version = "1.1.0", optional = true }
[features] [features]
fxhash = ["rustc-hash"] fxhash = ["rustc-hash"]
pretty = ["debug2"]
# todo: we don't actually want this as a default feature
default = ["pretty"]
[dev-dependencies] [dev-dependencies]
insta = "1.9.0" insta = "1.9.0"

View file

@ -18,6 +18,7 @@
use crate::errors::Span; use crate::errors::Span;
use crate::vm::Value; use crate::vm::Value;
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use debug2::Formatter;
/// This struct contains all data for a function. /// This struct contains all data for a function.
#[derive(Debug)] #[derive(Debug)]
@ -34,8 +35,21 @@ pub struct FnBlock<'bc> {
pub arity: u8, pub arity: u8,
} }
#[cfg(feature = "pretty")]
impl debug2::Debug for FnBlock<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FnBlock")
.field("code", &self.code.as_slice())
.field("stack_sizes", &self.stack_sizes.as_slice())
.field("spans", &self.spans.as_slice())
.field("arity", &self.arity)
.finish()
}
}
/// A bytecode instruction. For more details on the structure of the bytecode, read the module level docs [`bytecode`](`self`) /// A bytecode instruction. For more details on the structure of the bytecode, read the module level docs [`bytecode`](`self`)
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
pub enum Instr { pub enum Instr {
/// An operation that does nothing. /// An operation that does nothing.
Nop, Nop,

View file

@ -62,7 +62,7 @@ pub fn compile<'ast, 'bc, 'gc>(
ast: &'ast Program, ast: &'ast Program,
bytecode_bump: &'bc Bump, bytecode_bump: &'bc Bump,
rt: &'gc mut RtAlloc, rt: &'gc mut RtAlloc,
) -> Result<Vec<'bc, FnBlock<'bc>>, CompilerError> { ) -> Result<&'bc [FnBlock<'bc>], CompilerError> {
let mut compiler = Compiler { let mut compiler = Compiler {
blocks: Vec::new_in(bytecode_bump), blocks: Vec::new_in(bytecode_bump),
current_block: 0, current_block: 0,
@ -73,7 +73,7 @@ pub fn compile<'ast, 'bc, 'gc>(
compiler.compile(ast)?; compiler.compile(ast)?;
Ok(compiler.blocks) Ok(compiler.blocks.into_bump_slice())
} }
impl<'bc, 'gc> Compiler<'bc, 'gc> { impl<'bc, 'gc> Compiler<'bc, 'gc> {

View file

@ -13,6 +13,7 @@ pub use span::Span;
mod span { mod span {
#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)] #[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
pub struct Span { pub struct Span {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,

View file

@ -30,6 +30,21 @@ impl<T: ?Sized> Deref for Gc<T> {
} }
} }
#[cfg(feature = "pretty")]
impl<T: debug2::Debug> debug2::Debug for Gc<T> {
fn fmt(&self, f: &mut debug2::Formatter<'_>) -> std::fmt::Result {
T::fmt(&*self, f)
}
}
#[cfg(feature = "pretty")]
impl debug2::Debug for Gc<str> {
fn fmt(&self, f: &mut debug2::Formatter<'_>) -> std::fmt::Result {
let str = self.deref();
debug2::Debug::fmt(&str, f)
}
}
impl<T: Debug + ?Sized> Debug for Gc<T> { impl<T: Debug + ?Sized> Debug for Gc<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
T::fmt(self, f) T::fmt(self, f)
@ -46,6 +61,7 @@ impl<T: ?Sized> Copy for Gc<T> {}
/// An reference to an interned String. Hashing and Equality are O(1) and just look at the pointer address /// An reference to an interned String. Hashing and Equality are O(1) and just look at the pointer address
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
pub struct Symbol { pub struct Symbol {
gc: Gc<str>, gc: Gc<str>,
} }
@ -58,17 +74,20 @@ type ObjectMap = HashMap<Symbol, Value>;
/// ``` /// ```
/// This is inside the local x now. /// This is inside the local x now.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
pub struct Object { pub struct Object {
gc: Gc<HeapObject>, gc: Gc<HeapObject>,
} }
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
struct HeapObject { struct HeapObject {
kind: HeapObjectKind, kind: HeapObjectKind,
} }
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
enum HeapObjectKind { enum HeapObjectKind {
String(Gc<str>), String(Gc<str>),
Object(ObjectMap), Object(ObjectMap),

View file

@ -63,7 +63,14 @@ fn process_ast(program: &str, ast: &Program, mut runtime: RtAlloc, cfg: &mut Con
match bytecode { match bytecode {
Ok(code) => { Ok(code) => {
if cfg.debug { if cfg.debug {
println!("Bytecode:\n{:#?}\n", code); #[cfg(feature = "pretty")]
{
println!("Bytecode:\n{}\n", debug2::pprint(code));
}
#[cfg(not(feature = "pretty"))]
{
println!("Bytecode:\n{:#?}\n", code);
}
} }
let result = vm::execute(&code, runtime, cfg.stdout); let result = vm::execute(&code, runtime, cfg.stdout);

View file

@ -24,6 +24,7 @@ pub fn execute<'bc>(
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "pretty", derive(debug2::Debug))]
pub enum Value { pub enum Value {
Null, Null,
Bool(bool), Bool(bool),
@ -63,6 +64,8 @@ impl<'bc> Vm<'bc, '_> {
None => return Ok(()), None => return Ok(()),
} }
self.pc += 1; self.pc += 1;
// debug stack size assertion
todo!()
} }
} }

View file

@ -1,7 +1,6 @@
let i = 0; let i = 0;
while i < 100 { while i < 100000 {
print i;
i = i + 1; i = i + 1;
} }

View file

@ -120,3 +120,23 @@ if not_run {
} }
"# "#
); );
run_test!(
fizzbuzz,
r#"
let i = 1;
while i < 100 {
if i % 15 == 0 {
print "FizzBuzz";
} else if i % 5 == 0 {
print "Buzz";
} else if i % 3 == 0 {
print "Fizz";
} else {
print i;
}
i = i + 1;
}
"#
);

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 124
expression: output
---
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\n"