use crate::ast::Span;
use crate::collections::HashMap;
use crate::compile::Item;
use crate::runtime::DebugLabel;
use crate::{Hash, SourceId};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugInfo {
pub instructions: Vec<DebugInst>,
pub functions: HashMap<Hash, DebugSignature>,
pub functions_rev: HashMap<usize, Hash>,
}
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))
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugInst {
pub source_id: SourceId,
pub span: Span,
pub comment: Option<Box<str>>,
pub label: Option<DebugLabel>,
}
impl DebugInst {
pub fn new(
source_id: SourceId,
span: Span,
comment: Option<Box<str>>,
label: Option<DebugLabel>,
) -> Self {
Self {
source_id,
span,
comment,
label,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DebugArgs {
EmptyArgs,
TupleArgs(usize),
Named(Box<[Box<str>]>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct DebugSignature {
pub path: Item,
pub args: DebugArgs,
}
impl DebugSignature {
pub fn new(path: Item, 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(())
}
}