ryna/
debug.rs

1use std::sync::Arc;
2
3use colored::Colorize;
4use derive_builder::Builder;
5use rustc_hash::FxHashSet;
6use serde::{Deserialize, Serialize};
7
8use crate::{context::RynaContext, operations::Operator, parser::RynaExpr, types::Type};
9
10// Instruction-level debug information
11
12#[derive(Clone, Debug, Default, PartialEq, Builder, Serialize, Deserialize)]
13pub struct DebugInfo {
14    #[builder(default)]
15    pub comment: String,
16    
17    #[builder(default)]
18    pub var_type: Option<Type>,
19    
20    #[builder(default)]
21    pub labels: FxHashSet<usize>,
22    
23    #[builder(default)]
24    pub functions: FxHashSet<String>,
25    
26    #[builder(default)]
27    pub lines: FxHashSet<(Arc<String>, usize)> // (Module, line)
28}
29
30impl DebugInfo {
31    pub fn merge_with(&mut self, other: &DebugInfo) {
32        self.functions.extend(other.functions.iter().cloned());
33        self.lines.extend(other.lines.iter().cloned());
34        self.labels.extend(&other.labels);
35
36        if self.comment.is_empty() && !other.comment.is_empty() {
37            self.comment = other.comment.clone();
38        }
39    }
40
41    pub fn set_line(&mut self, module: Arc<String>, line: usize) {
42        self.lines.insert((module, line));
43    }
44}
45
46// Expression printing
47
48impl RynaContext {
49    pub fn to_string(&self, expr: &RynaExpr) -> String  {
50        match expr {
51            RynaExpr::NameReference(_, n) |
52            RynaExpr::Variable(_, _, n, _, _) => n.clone().cyan().to_string(),
53            RynaExpr::CompiledVariableDefinition(_, _, n, t, e, _) => format!("let {}: {} = {}", n.cyan(), t.get_name(self), self.to_string(e)),
54            RynaExpr::CompiledVariableAssignment(_, _, n, _, e, _) => format!("{} = {}", n.cyan(), self.to_string(e)),
55
56            RynaExpr::Literal(_, obj) => obj.to_debug_string().magenta().to_string(),
57            RynaExpr::Tuple(_, args) => format!("({})", args.iter().map(|i| self.to_string(i)).collect::<Vec<_>>().join(", ")),
58
59            RynaExpr::FunctionCall(_, id, t, args) => {
60                let temp = if t.is_empty() {
61                    String::new()
62
63                } else {
64                    format!("<{}>", t.iter().map(|t| t.get_name(self)).collect::<Vec<_>>().join(", "))
65                };
66
67                format!(
68                    "{}{}({})", 
69                    self.functions[*id].name.green(), 
70                    temp,
71                    args.iter().map(|i| self.to_string(i)).collect::<Vec<_>>().join(", ")
72                )
73            },
74
75            RynaExpr::UnaryOperation(_, id, t, expr) => {
76                let temp = if t.is_empty() {
77                    String::new()
78
79                } else {
80                    format!("<{}>", t.iter().map(|t| t.get_name(self)).collect::<Vec<_>>().join(", "))
81                };
82
83                if let Operator::Unary { representation, prefix, .. } = &self.unary_ops[*id] {
84                    if *prefix {
85                        return format!("{}{}{}", representation, temp, self.to_string(expr))
86
87                    } else {
88                        return format!("{}{}{}", self.to_string(expr), temp, representation)
89                    }
90                }
91
92                unreachable!()
93            },
94
95            RynaExpr::BinaryOperation(_, id, t, a, b) => {
96                let temp = if t.is_empty() {
97                    String::new()
98
99                } else {
100                    format!("<{}>", t.iter().map(|t| t.get_name(self)).collect::<Vec<_>>().join(", "))
101                };
102
103                format!("{} {}{} {}", self.to_string(a), temp, self.binary_ops[*id].get_repr(), self.to_string(b))
104            },
105
106            RynaExpr::NaryOperation(_, id, t, a, b) => {
107                let temp = if t.is_empty() {
108                    String::new()
109
110                } else {
111                    format!("<{}>", t.iter().map(|t| t.get_name(self)).collect::<Vec<_>>().join(", "))
112                };
113
114                if let Operator::Nary { open_rep, close_rep, .. } = &self.nary_ops[*id] {
115                    return format!("{}{}{}{}{}", self.to_string(a), temp, open_rep, b.iter().map(|i| self.to_string(i)).collect::<Vec<_>>().join(", "), close_rep)
116                }
117
118                unreachable!()
119            },
120
121            RynaExpr::Return(_, expr) => format!("return {}", self.to_string(expr)),
122
123            _ => todo!("Unable to convert {:?} to pretty string", expr)
124        }
125    }
126}