microcad_lang/eval/symbols/
stack_frame.rs1use crate::{eval::*, model::*};
5
6pub enum StackFrame {
19 Source(Identifier, SymbolMap),
21 Module(Identifier, SymbolMap),
23 Init(SymbolMap),
25 Workbench(Model, Identifier, SymbolMap),
27 Body(SymbolMap),
29 Function(SymbolMap),
31 Call {
33 symbol: Symbol,
35 args: ArgumentValueList,
37 src_ref: SrcRef,
39 },
40}
41
42impl StackFrame {
43 pub fn id(&self) -> Option<Identifier> {
45 match self {
46 StackFrame::Source(id, _) | StackFrame::Module(id, _) => Some(id.clone()),
47 _ => None,
48 }
49 }
50
51 pub fn symbol(&self) -> Option<Symbol> {
53 match &self {
54 StackFrame::Call { symbol, .. } => Some(symbol.clone()),
55 _ => None,
56 }
57 }
58
59 pub fn kind_str(&self) -> &'static str {
61 match self {
62 StackFrame::Source(_, _) => "source",
63 StackFrame::Module(_, _) => "module",
64 StackFrame::Init(_) => "init",
65 StackFrame::Workbench(_, _, _) => "workbench",
66 StackFrame::Body(_) => "body",
67 StackFrame::Function(_) => "function",
68 StackFrame::Call {
69 symbol: _,
70 args: _,
71 src_ref: _,
72 } => "call",
73 }
74 }
75
76 pub fn print_locals(
78 &self,
79 f: &mut std::fmt::Formatter<'_>,
80 idx: usize,
81 mut depth: usize,
82 ) -> std::fmt::Result {
83 let locals = match self {
84 StackFrame::Source(id, locals) => {
85 writeln!(f, "{:depth$}[{idx}] Source: {id:?}", "")?;
86 locals
87 }
88 StackFrame::Module(id, locals) => {
89 writeln!(f, "{:depth$}[{idx}] Module: {id:?}", "")?;
90 locals
91 }
92 StackFrame::Init(locals) => {
93 writeln!(f, "{:depth$}[{idx}] Init", "")?;
94 locals
95 }
96 StackFrame::Workbench(_, id, locals) => {
97 writeln!(f, "{:depth$}[{idx}] Workbench: {id:?}", "")?;
98 locals
99 }
100 StackFrame::Body(locals) => {
101 writeln!(f, "{:depth$}[{idx}] Body:", "")?;
102 locals
103 }
104 StackFrame::Function(locals) => {
105 writeln!(f, "{:depth$}[{idx}] Function:", "")?;
106 locals
107 }
108 StackFrame::Call {
109 symbol,
110 args,
111 src_ref: _,
112 } => {
113 return writeln!(
114 f,
115 "{:depth$}[{idx}] Call: {name:?}({args})",
116 "",
117 args = args,
118 name = symbol.full_name()
119 );
120 }
121 };
122
123 depth += 4;
124
125 for (id, symbol) in locals.iter() {
126 let full_name = symbol.full_name();
127 let full_name = if full_name != id.into() {
128 format!(" [{full_name}]")
129 } else {
130 String::new()
131 };
132 match &symbol.borrow().def {
133 SymbolDefinition::Constant(visibility, id, value) => writeln!(
134 f,
135 "{:depth$}- {visibility}{id:?} = {value}{full_name} (constant)",
136 ""
137 )?,
138 SymbolDefinition::Argument(id, value) => {
139 writeln!(f, "{:depth$}- {id:?} = {value}{full_name} (argument)", "")?
140 }
141 SymbolDefinition::SourceFile(source) => {
142 writeln!(f, "{:depth$}- {:?} (source)", "", source.filename())?
143 }
144 SymbolDefinition::Module(def) => {
145 writeln!(f, "{:depth$}- {:?}{full_name} (module)", "", def.id)?
146 }
147 SymbolDefinition::Workbench(def) => {
148 writeln!(f, "{:depth$}- {:?}{full_name} (workbench)", "", def.id)?
149 }
150 SymbolDefinition::Function(def) => {
151 writeln!(f, "{:depth$}- {:?}{full_name} (function)", "", def.id)?
152 }
153 SymbolDefinition::Builtin(builtin) => {
154 writeln!(f, "{:depth$}- {:?}{full_name} (builtin)", "", builtin.id)?
155 }
156 SymbolDefinition::Alias(visibility, id, name) => writeln!(
157 f,
158 "{:depth$}- {visibility}{id:?}{full_name} -> {name} (alias)",
159 ""
160 )?,
161 SymbolDefinition::UseAll(visibility, name) => {
162 writeln!(f, "{:depth$}- {visibility}{name}{full_name} (use all)", "")?
163 }
164 #[cfg(test)]
165 SymbolDefinition::Tester(id) => writeln!(f, "{:depth$}- {id} (tester)", "")?,
166 }
167 }
168
169 Ok(())
170 }
171
172 pub fn print_stack(
174 &self,
175 f: &mut dyn std::fmt::Write,
176 source_by_hash: &impl GetSourceByHash,
177 idx: usize,
178 ) -> std::fmt::Result {
179 match self {
180 StackFrame::Source(_identifier, _locals) => todo!(),
181 StackFrame::Module(_identifier, _locals) => todo!(),
182 StackFrame::Init(_locals) => todo!(),
183 StackFrame::Workbench(_kind, _identifier, _locals) => todo!(),
184 StackFrame::Body(_locals) => todo!(),
185 StackFrame::Function(_locals) => todo!(),
186 StackFrame::Call {
187 symbol,
188 args,
189 src_ref,
190 } => {
191 writeln!(f, "{:>4}: {name}({args})", idx, name = symbol.full_name())?;
192
193 if let Some(line_col) = src_ref.at() {
194 let source_file = source_by_hash.get_by_hash(src_ref.source_hash());
195 writeln!(
196 f,
197 " at {filename}:{line_col}",
198 filename = source_file
199 .as_ref()
200 .map(|sf| sf.filename_as_str())
201 .unwrap_or(crate::invalid!(FILE)),
202 )?;
203 }
204 }
205 }
206
207 Ok(())
208 }
209}