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 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)),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
51
src/main.rs
51
src/main.rs
@ -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
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