Add vm:📦:Package, instruction disassembly

* Code is compiled into a vm:📦:Package which contains the
  executable code, the constants, and the local name mappings.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-09-18 15:45:54 -07:00
parent 321fe8e1ea
commit cb5689c513
6 changed files with 136 additions and 105 deletions

View File

@@ -1,5 +1,4 @@
use crate::{obj::prelude::*, vm::consts::*};
use std::fmt::{self, Display, Formatter};
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Inst {
@@ -145,90 +144,3 @@ impl Inst {
}
}
}
pub fn dump_inst_body(insts: &Vec<Inst>, const_pool: &ConstPool) {
println!("{}", InstFormatter::new(insts, const_pool))
}
//
// struct InstFormatter
//
pub struct InstFormatter<'i, 'c> {
insts: &'i Vec<Inst>,
const_pool: &'c ConstPool,
}
impl<'i, 'c> InstFormatter<'i, 'c> {
pub fn new(insts: &'i Vec<Inst>, const_pool: &'c ConstPool) -> Self {
Self { insts, const_pool, }
}
}
impl Display for InstFormatter<'_, '_> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
// column widths
let addr_w = num_digits(self.insts.len(), 16).max(4);
let inst_col = 16 - addr_w;
let inst_w = 16;
for (addr, inst) in self.insts.iter().enumerate() {
let (param_val, mut param_name) = match inst {
Inst::PushSym(sym) | Inst::GetAttr(sym) | Inst::SetAttr(sym) => (
sym.index().to_string(),
global_sym_lookup(*sym).unwrap().to_string(),
),
Inst::PushConst(hdl) => (
hdl.index().to_string(),
{
let obj_ref = self.const_pool.get(*hdl);
read_obj!(let obj = obj_ref);
// XXX weirdness with coercion, can't deref as a &dyn Obj because
// RwReadLockGuard is not Obj - but using Deref::deref works
let obj: &dyn Obj = std::ops::Deref::deref(obj);
format!("{:?}", obj)
},
),
Inst::LoadName(local) => (
local.index().to_string(),
"TODO: local name".to_string(),
),
Inst::Pop(local) => (
format!("{:?}", local),
"TODO: local name".to_string(),
),
Inst::Jump(addr) | Inst::JumpTrue(addr) => (
addr.to_string(),
String::new(),
),
Inst::Call(argc) => (
argc.to_string(),
String::new(),
),
_ => (String::new(), String::new()),
};
if !param_name.is_empty() {
param_name = format!("({})", param_name);
}
writeln!(
fmt,
"{:0addr_w$x}{space: >inst_col$}{: <inst_w$}{} {}",
addr,
inst.name(),
param_val,
param_name,
space = "",
addr_w = addr_w,
inst_w = inst_w,
inst_col = inst_col,
)?;
}
Ok(())
}
}
fn num_digits(n: usize, radix: usize) -> usize {
((n as f64) + 1.0).log(radix as f64).ceil() as usize
}