101 lines
2.3 KiB
Rust
101 lines
2.3 KiB
Rust
use std::rc::Rc;
|
|
|
|
use crate::{chunk::Chunk, Vm, exception::Result};
|
|
|
|
use super::Value;
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
pub struct FuncAttrs {
|
|
pub arity: usize,
|
|
pub variadic: bool,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Function {
|
|
pub attrs: FuncAttrs,
|
|
pub chunk: Rc<Chunk>,
|
|
}
|
|
|
|
impl Function {
|
|
pub fn new(chunk: Rc<Chunk>, arity: usize) -> Self {
|
|
Self { chunk, attrs: FuncAttrs { arity, variadic: false } }
|
|
}
|
|
pub fn new_variadic(chunk: Rc<Chunk>, arity: usize) -> Self {
|
|
Self { chunk, attrs: FuncAttrs { arity, variadic: true } }
|
|
}
|
|
}
|
|
|
|
type FnNative = Box<dyn Fn(&mut Vm, Vec<Value>) -> Result<Value>>;
|
|
|
|
pub struct NativeFunc {
|
|
pub attrs: FuncAttrs,
|
|
pub func: FnNative,
|
|
}
|
|
|
|
impl NativeFunc {
|
|
pub fn new(func: FnNative, arity: usize) -> Self {
|
|
Self { func, attrs: FuncAttrs { arity, variadic: false } }
|
|
}
|
|
pub fn new_variadic(func: FnNative, arity: usize) -> Self {
|
|
Self { func, attrs: FuncAttrs { arity, variadic: true } }
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for NativeFunc {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("NativeFunc")
|
|
.field("attrs", &self.attrs)
|
|
.finish_non_exhaustive()
|
|
}
|
|
}
|
|
|
|
pub fn disasm_recursive(f: &Rc<Function>, w: &mut impl std::io::Write) -> std::io::Result<()> {
|
|
writeln!(w, "{} ({}{})",
|
|
Value::Function(f.clone()),
|
|
f.attrs.arity,
|
|
if f.attrs.variadic { ".." } else { "" })?;
|
|
if !f.chunk.consts.is_empty() {
|
|
writeln!(w, "constants")?;
|
|
for (i, c) in f.chunk.consts.iter().enumerate() {
|
|
writeln!(w, " {i:04}: {c}")?;
|
|
}
|
|
}
|
|
if !f.chunk.try_tables.is_empty() {
|
|
writeln!(w, "catch tables")?;
|
|
for (i, n) in f.chunk.try_tables.iter().enumerate() {
|
|
write!(w, " {i:04}: ")?;
|
|
if n.catches.is_empty() {
|
|
writeln!(w)?;
|
|
}
|
|
for (i, catch) in n.catches.iter().enumerate() {
|
|
if i != 0 {
|
|
write!(w, " : ")?;
|
|
}
|
|
if let Some(types) = &catch.types {
|
|
write!(w, "{:04} [", catch.addr)?;
|
|
for (i, ty) in types.iter().enumerate() {
|
|
if i != 0 { write!(w, ", ")?; }
|
|
write!(w, "{}", ty.name())?;
|
|
}
|
|
writeln!(w, "]")?;
|
|
} else {
|
|
writeln!(w, "{:04} *", catch.addr)?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
writeln!(w, "instructions")?;
|
|
for (i, n) in f.chunk.instrs.iter().enumerate() {
|
|
writeln!(w, " {i:04}: {n}")?;
|
|
}
|
|
writeln!(w)?;
|
|
|
|
for c in &f.chunk.consts {
|
|
if let Value::Function(f) = c {
|
|
disasm_recursive(f, w)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|