use core::fmt;
use serde::{Deserialize, Serialize};
use crate as rune;
use crate::alloc::prelude::*;
use crate::alloc::{Box, HashMap, Vec};
use crate::ast::Span;
use crate::runtime::DebugLabel;
use crate::{Hash, ItemBuf, SourceId};
#[derive(Debug, TryClone, Default, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugInfo {
pub instructions: HashMap<usize, DebugInst>,
pub functions: HashMap<Hash, DebugSignature>,
pub functions_rev: HashMap<usize, Hash>,
pub hash_to_ident: HashMap<Hash, Box<str>>,
}
impl DebugInfo {
pub fn instruction_at(&self, ip: usize) -> Option<&DebugInst> {
self.instructions.get(&ip)
}
pub fn function_at(&self, ip: usize) -> Option<(Hash, &DebugSignature)> {
let hash = *self.functions_rev.get(&ip)?;
let signature = self.functions.get(&hash)?;
Some((hash, signature))
}
pub fn ident_for_hash(&self, hash: Hash) -> Option<&str> {
Some(self.hash_to_ident.get(&hash)?)
}
}
#[derive(Debug, TryClone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugInst {
pub source_id: SourceId,
pub span: Span,
pub comment: Option<Box<str>>,
pub labels: Vec<DebugLabel>,
}
impl DebugInst {
pub fn new(
source_id: SourceId,
span: Span,
comment: Option<Box<str>>,
labels: Vec<DebugLabel>,
) -> Self {
Self {
source_id,
span,
comment,
labels,
}
}
}
#[derive(Debug, TryClone, Serialize, Deserialize)]
pub enum DebugArgs {
EmptyArgs,
TupleArgs(usize),
Named(Box<[Box<str>]>),
}
#[derive(Debug, TryClone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugSignature {
pub path: ItemBuf,
pub args: DebugArgs,
}
impl DebugSignature {
pub fn new(path: ItemBuf, args: DebugArgs) -> Self {
Self { path, args }
}
}
impl fmt::Display for DebugSignature {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.args {
DebugArgs::EmptyArgs => {
write!(fmt, "{}", self.path)?;
}
DebugArgs::TupleArgs(args) if *args > 0 => {
write!(fmt, "{}(", self.path)?;
let mut it = 0..*args;
let last = it.next_back();
for arg in it {
write!(fmt, "{}, ", arg)?;
}
if let Some(arg) = last {
write!(fmt, "{}", arg)?;
}
write!(fmt, ")")?;
}
DebugArgs::Named(args) => {
write!(fmt, "{}(", self.path)?;
let mut it = args.iter();
let last = it.next_back();
for arg in it {
write!(fmt, "{}, ", arg)?;
}
if let Some(arg) = last {
write!(fmt, "{}", arg)?;
}
write!(fmt, ")")?;
}
_ => (),
}
Ok(())
}
}