added rudimentary pretty printer. Right now utterly useless.
This commit is contained in:
parent
03668a71e8
commit
e2b7ec3e43
@ -1,3 +1,4 @@
|
||||
|
||||
/// Type alias to represent a register.
|
||||
type RegisterMem = String;
|
||||
|
||||
@ -38,3 +39,34 @@ pub enum Operation {
|
||||
/// J Type
|
||||
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)),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ mod tests;
|
||||
use encoder::CodeFormat;
|
||||
use encoder::SymbolTable;
|
||||
|
||||
pub use AST::print_op;
|
||||
|
||||
use log::{trace, debug};
|
||||
|
||||
use parser::Section;
|
||||
|
@ -1,7 +1,9 @@
|
||||
|
||||
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::fmt::Display;
|
||||
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
@ -21,6 +23,36 @@ pub enum Subc {
|
||||
|
||||
Run {filename: 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@ pub mod jit;
|
||||
pub mod loader;
|
||||
pub mod cli;
|
||||
pub mod assembler;
|
||||
pub mod pretty_printers;
|
||||
//
|
||||
|
||||
pub fn interpret_as_signed(x: u16) -> i16 {
|
||||
|
49
src/main.rs
49
src/main.rs
@ -1,10 +1,12 @@
|
||||
|
||||
use dekejit::assembler::parser;
|
||||
use dekejit::cli::{Cli, Subc::*};
|
||||
use dekejit::cpu::IOBuffer;
|
||||
use dekejit::cpu::CPU;
|
||||
use dekejit::pretty_printers::*;
|
||||
|
||||
use clap::Parser;
|
||||
use dekejit::loader::loader::prepare_memory;
|
||||
use dekejit::loader::loader::{prepare_memory, self};
|
||||
use dekejit::loader::loader::read_binary;
|
||||
use dekejit::transmute_to_vecu8_as_is;
|
||||
use log::{info, debug};
|
||||
@ -47,7 +49,7 @@ fn main() {
|
||||
|
||||
let bin = prepare_memory(sections);
|
||||
|
||||
info!("{:?}", bin);
|
||||
// trace!("{:?}", bin);
|
||||
|
||||
let mut env = IOBuffer::default();
|
||||
//
|
||||
@ -101,31 +103,46 @@ fn main() {
|
||||
};
|
||||
|
||||
}
|
||||
Some(View {filename}) => {
|
||||
Some(View {filename, format}) => {
|
||||
|
||||
info!("Trying to read {}", filename);
|
||||
|
||||
let Ok(content) = std::fs::read(&filename) else {
|
||||
println!("File {} does not exist or cannot be read.", &filename);
|
||||
let Ok(content) = std::fs::read_to_string(&filename) else {
|
||||
println!("File {} does not exist or cannot be read", &filename);
|
||||
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 => {}
|
||||
}
|
||||
|
||||
|
222
src/pretty_printers/asm.rs
Normal file
222
src/pretty_printers/asm.rs
Normal 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 {
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
// ┄
|
||||
// ┅
|
||||
// ┆
|
||||
// ┇
|
||||
// ┈
|
||||
// ┉
|
||||
// ┊
|
||||
// ┋
|
||||
// ┌
|
||||
// ┍
|
||||
// ┎
|
||||
// ┏
|
||||
// ┐
|
||||
// ┑
|
||||
// ┒
|
||||
// ┓
|
||||
// └
|
||||
// ┕
|
||||
// ┖
|
||||
// ┗
|
||||
// ┘
|
||||
// ┙
|
||||
// ┚
|
||||
// ┛
|
||||
// ├
|
||||
// ┝
|
||||
// ┞
|
||||
// ┟
|
||||
// ┠
|
||||
// ┡
|
||||
// ┢
|
||||
// ┣
|
||||
// ┤
|
||||
// ┥
|
||||
// ┦
|
||||
// ┧
|
||||
// ┨
|
||||
// ┩
|
||||
// ┪
|
||||
// ┫
|
||||
// ┬
|
||||
// ┭
|
||||
// ┮
|
||||
// ┯
|
||||
// ┰
|
||||
// ┱
|
||||
// ┲
|
||||
// ┳
|
||||
// ┴
|
||||
// ┵
|
||||
// ┶
|
||||
// ┷
|
||||
// ┸
|
||||
// ┹
|
||||
// ┺
|
||||
// ┻
|
||||
// ┼
|
||||
// ┽
|
||||
// ┾
|
||||
// ┿
|
||||
// ╀
|
||||
// ╁
|
||||
// ╂
|
||||
// ╃
|
||||
// ╄
|
||||
// ╅
|
||||
// ╆
|
||||
// ╇
|
||||
// ╈
|
||||
// ╉
|
||||
// ╊
|
||||
// ╋
|
||||
// ╌
|
||||
// ╍
|
||||
// ╎
|
||||
// ╏
|
||||
// ═
|
||||
// ║
|
||||
// ╒
|
||||
// ╓
|
0
src/pretty_printers/bin.rs
Normal file
0
src/pretty_printers/bin.rs
Normal file
49
src/pretty_printers/mod.rs
Normal file
49
src/pretty_printers/mod.rs
Normal 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!(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user