added rudimentary pretty printer. Right now utterly useless.

This commit is contained in:
raphy 2023-05-08 12:37:27 +02:00
parent 03668a71e8
commit e2b7ec3e43
8 changed files with 373 additions and 18 deletions

View File

@ -1,3 +1,4 @@
/// Type alias to represent a register. /// Type alias to represent a register.
type RegisterMem = String; type RegisterMem = String;
@ -38,3 +39,34 @@ pub enum Operation {
/// J Type /// J Type
JAL(RegisterMem, RegisterMem, Const), JAL(RegisterMem, RegisterMem, Const),
} }
pub fn print_op(op: Operation) -> String {
let print_const = |x : Const| {
match x {
Const::CS(i) => i,
Const::C(n) => format!("{}", n),
}
};
match op {
Operation::NOP => String::from("nop"),
Operation::HALT => String::from("halt"),
Operation::ADD(a, b, c) => format!("add {} {} {}", a, b, c),
Operation::SUB(a, b, c) => format!("sub {} {} {}", a, b, c),
Operation::AND(a, b, c) => format!("and {} {} {}", a, b, c),
Operation::XOR(a, b, c) => format!("xor {} {} {}", a, b, c),
Operation::SLL(a, b, c) => format!("sll {} {} {}", a, b, c),
Operation::BEQ(a, b, c) => format!("beq {} {} {}", a, b, c),
Operation::BGT(a, b, c) => format!("bgq {} {} {}", a, b, c),
Operation::LOAD(a, b, c) => format!("load {} {} {}", a, b, c),
Operation::STORE(a, b, c) => format!("store {} {} {}", a, b, c),
Operation::SLI(a, c) => format!("sli {} {}", a, print_const(c)),
Operation::ADDI(a, c) => format!("addi {} {}", a, print_const(c)),
Operation::CALL(a, c) => format!("call {} {}", a, print_const(c)),
Operation::JAL(a, b, c) => format!("jal {} {} {}", a, b, print_const(c)),
}
}

View File

@ -6,6 +6,8 @@ mod tests;
use encoder::CodeFormat; use encoder::CodeFormat;
use encoder::SymbolTable; use encoder::SymbolTable;
pub use AST::print_op;
use log::{trace, debug}; use log::{trace, debug};
use parser::Section; use parser::Section;

View File

@ -1,7 +1,9 @@
use clap::{Parser, Subcommand}; use std::fmt::Display;
use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -21,6 +23,36 @@ pub enum Subc {
Run {filename: String}, Run {filename: String},
Build {filename: String, output: String}, Build {filename: String, output: String},
View {filename: String}, View {
filename: String,
#[arg(short, long, default_value_t = FormatKind::FancyTable)]
format: FormatKind
},
Debug {}
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
pub enum FormatKind {
FancyTable,
Raw,
BinSections,
Serializable,
}
impl Display for FormatKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FormatKind::FancyTable => write!(f, "fancy-table"),
FormatKind::Raw => write!(f, "raw"),
FormatKind::BinSections => write!(f, "memory"),
FormatKind::Serializable => write!(f, "rust"),
}
}
}

View File

@ -5,6 +5,7 @@ pub mod jit;
pub mod loader; pub mod loader;
pub mod cli; pub mod cli;
pub mod assembler; pub mod assembler;
pub mod pretty_printers;
// //
pub fn interpret_as_signed(x: u16) -> i16 { pub fn interpret_as_signed(x: u16) -> i16 {

View File

@ -1,10 +1,12 @@
use dekejit::assembler::parser;
use dekejit::cli::{Cli, Subc::*}; use dekejit::cli::{Cli, Subc::*};
use dekejit::cpu::IOBuffer; use dekejit::cpu::IOBuffer;
use dekejit::cpu::CPU; use dekejit::cpu::CPU;
use dekejit::pretty_printers::*;
use clap::Parser; use clap::Parser;
use dekejit::loader::loader::prepare_memory; use dekejit::loader::loader::{prepare_memory, self};
use dekejit::loader::loader::read_binary; use dekejit::loader::loader::read_binary;
use dekejit::transmute_to_vecu8_as_is; use dekejit::transmute_to_vecu8_as_is;
use log::{info, debug}; use log::{info, debug};
@ -47,7 +49,7 @@ fn main() {
let bin = prepare_memory(sections); let bin = prepare_memory(sections);
info!("{:?}", bin); // trace!("{:?}", bin);
let mut env = IOBuffer::default(); let mut env = IOBuffer::default();
// //
@ -101,31 +103,46 @@ fn main() {
}; };
} }
Some(View {filename}) => { Some(View {filename, format}) => {
info!("Trying to read {}", filename); info!("Trying to read {}", filename);
let Ok(content) = std::fs::read(&filename) else { let Ok(content) = std::fs::read_to_string(&filename) else {
println!("File {} does not exist or cannot be read.", &filename); println!("File {} does not exist or cannot be read", &filename);
return; return;
}; };
let p = parser::Parser::new(content);
let bytes = dekejit::transmute_to_vecu16_as_is(content.to_vec());
info!("{:?}", bytes); let s = p.parse_sections().unwrap();
println!("{}", format_code(dekejit::pretty_printers::CodeWrapper::Asm(s), format).unwrap());
// let Ok(content) = std::fs::read(&filename) else {
// println!("File {} does not exist or cannot be read.", &filename);
// return;
// };
//
//
// let bytes = dekejit::transmute_to_vecu16_as_is(content.to_vec());
//
// info!("{:?}", bytes);
//
// info!("Begin parsing file {}", &filename);
// let sections = match read_binary(&bytes) {
// Ok(k) => k,
// Err(p) => {
// println!("Parsing error: {:?}", p);
// return;
// }
// };
//
// println!("{:?}", sections);
info!("Begin parsing file {}", &filename);
let sections = match read_binary(&bytes) {
Ok(k) => k,
Err(p) => {
println!("Parsing error: {:?}", p);
return;
}
};
println!("{:?}", sections);
} }
Some(Debug) => {},
None => {} None => {}
} }

222
src/pretty_printers/asm.rs Normal file
View File

@ -0,0 +1,222 @@
use crate::assembler::{self, print_op};
use super::{Section, SectionContent};
/// Aaaand we don't know the size of the terminal.
/// We'll just pretend it is 80 characters.
/// It would be wise to be able to change it with
/// a parameter. Later! #TODO
pub const TERMSIZE : u8 = 80;
pub fn to_table(secs: Vec<Section>) -> String {
let mut res = String::new();
let mut header = String::from("");
for _ in 2..TERMSIZE {
header.push('─');
}
header.push('┐');
header.push('\n');
// ┏
// ┐
//
res.push_str(&header);
let sections_strings : Vec<String> = secs.into_iter().map(|x| draw_section(x)).collect();
let cont = sections_strings.join(&draw_separator(TERMSIZE));
res.push_str(&cont);
let mut footer = String::from("");
for _ in 2..TERMSIZE {
footer.push('─');
}
footer.push('┘');
res.push_str(&footer);
// for i in -40..40 {
// let p : i32 = (c as u32).try_into().unwrap();
// res.push_str(&format!("{}\n", char::from_u32((p + i).try_into().unwrap()).unwrap()));
// }
return res;
}
fn draw_section(sec: Section) -> String {
let mut res = String::new();
res.push_str(&format_line(&format!("{}", sec.name), 4, TERMSIZE));
res.push_str(&draw_separator(TERMSIZE));
match sec.content {
SectionContent::Code(ops) => {
// we just print ops again.
// we could make this prettier.
for op in ops {
res.push_str(&format_line(&print_op(op), 8, TERMSIZE));
}
},
SectionContent::CString(s) => res.push_str(&s),
SectionContent::CVec() => todo!(),
}
return res;
}
/// Formats a line in a box, with said indendation.
fn format_line(s: &str, indentation: u8, len: u8) -> String {
let mut res = String::from("");
// TODO: UTF8 GRAPHEMES???;
for _ in 1..indentation {
res.push(' ');
}
res.push_str(s);
// if ASCII, or even extended ascii are concerned,
// this works. But we need to get the number of graphemes, which can be tricky
// in utf-8.
for _ in res.len()..(len + 1) as usize {
res.push(' ');
}
res.push_str("\n");
return res;
}
/// Draws a horizontal line of specified length.
///
fn draw_separator(len: u8) -> String {
let mut res = String::from("");
for _ in 2..len {
res.push('─');
}
res.push('┤');
res.push('\n');
return res;
}
// fn wrap_in_bars(&str, indentation: u8) -> String {
//
//
//
// }
// ┄
// ┅
// ┆
// ┇
// ┈
// ┉
// ┊
// ┋
// ┌
// ┍
// ┎
// ┏
// ┐
// ┑
// ┒
// ┓
// └
// ┕
// ┖
// ┗
// ┘
// ┙
// ┚
// ┛
// ├
// ┝
// ┞
// ┟
// ┠
// ┡
// ┢
// ┣
// ┤
// ┥
// ┦
// ┧
// ┨
// ┩
// ┪
// ┫
// ┬
// ┭
// ┮
// ┯
// ┰
// ┱
// ┲
// ┳
// ┴
// ┵
// ┶
// ┷
// ┸
// ┹
// ┺
// ┻
// ┼
// ┽
// ┾
// ┿
// ╀
// ╁
// ╂
// ╃
// ╄
// ╅
// ╆
// ╇
// ╈
// ╉
// ╊
// ╋
// ╌
// ╍
// ╎
// ╏
// ═
// ║
// ╒
// ╓

View File

View File

@ -0,0 +1,49 @@
mod asm;
mod bin;
use asm::*;
use bin::*;
use crate::loader::loader::read_binary;
// We'll use the Cli to dictate which format kinds are available.
use super::cli::FormatKind;
use super::assembler::parser::{*};
pub enum CodeWrapper {
Bin(Vec<u16>),
Asm(Vec<Section>)
}
pub fn format_code(c: CodeWrapper, k: FormatKind) -> Result<String, crate::loader::loader::ParseError> {
match k {
FormatKind::FancyTable => match c {
CodeWrapper::Bin(_) => todo!(),
CodeWrapper::Asm(sections) => {
return Ok(to_table(sections))},
},
FormatKind::Raw => match c {
CodeWrapper::Bin(_) => todo!(),
CodeWrapper::Asm(_) => todo!(),
},
FormatKind::BinSections => match c {
CodeWrapper::Bin(_) => todo!(),
CodeWrapper::Asm(_) => todo!(),
},
FormatKind::Serializable => match c {
CodeWrapper::Bin(_) => todo!(),
CodeWrapper::Asm(_) => todo!(),
},
}
}