turtle/interpreter/
call_snapshot.rs1use crate::{exp, Exception, ExceptionValue as EV, Expression, Locker};
2use ansi_term::Color;
3use std::fmt;
4
5#[derive(Debug, Clone)]
6pub struct CallSnapshot {
7 parent: Option<Locker<Self>>,
8 expression: Expression,
9 depth: usize,
10}
11
12impl CallSnapshot {
13 pub fn root(exp: &Expression) -> Locker<Self> {
14 Locker::new(CallSnapshot {
15 parent: None,
16 expression: exp.clone(),
17 depth: 0,
18 })
19 }
20
21 pub fn new(exp: &Expression, parent: &Locker<Self>) -> Result<Locker<Self>, Exception> {
22 let depth = parent
24 .read()
25 .expect("could not access call snapshot parent (are threads locked?)")
26 .depth
27 + 1;
28 if depth > 1000 {
29 exp!(
30 EV::StackOverflow,
31 parent,
32 "this can happen when recursion goes too deep; verify there aren't any endless loops, or consider using `while` instead".to_string()
33 )
34 }
35
36 Ok(Locker::new(CallSnapshot {
37 parent: Some(parent.clone()),
38 expression: exp.clone(),
39 depth,
40 }))
41 }
42
43 pub fn expression(&self) -> &'_ Expression {
44 &self.expression
45 }
46}
47
48impl fmt::Display for CallSnapshot {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match &self.parent {
51 Some(parent_ref) => match parent_ref.read() {
52 Ok(parent) => {
54 match format!("{}", self.expression) == format!("{}", parent.expression) {
55 true => match &parent.parent {
56 Some(superparent_ref) => {
57 if let Ok(superparent) = superparent_ref.read() {
58 write!(f, "{}", superparent)?
59 }
60 }
61 None => {}
62 },
63 false => write!(f, "{}", parent)?,
64 }
65 }
66 Err(_) => writeln!(
67 f,
68 " {} unable to access parent call (are threads locked?)",
69 Color::Yellow.bold().paint("!")
70 )?,
71 },
72 None => {}
73 };
74 match self.expression().source() {
75 Some(source) => write!(f, "{}", source)?,
76 None => {}
77 }
78 write!(f, "")
79 }
80}