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#[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)> }
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
46impl 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}