talc/talc-lang/src/value/function.rs

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(())
}