turtle/interpreter/
expression.rs1use std::fmt;
2use std::sync::mpsc;
3
4use crate::Locker;
5use std::thread;
6
7use crate::{
8 exp, exp_assert, CallSnapshot, Environment, Exception, ExceptionValue as EV, SourcePosition,
9 Value,
10};
11
12#[derive(Debug, Clone)]
13pub struct Expression {
14 value: Value,
15 source: Option<SourcePosition>,
16}
17
18impl PartialEq for Expression {
19 fn eq(&self, other: &Self) -> bool {
20 self.value == other.value
22 }
23}
24
25impl Expression {
26 pub fn new(value: Value) -> Self {
27 Self {
28 value,
29 source: None,
30 }
31 }
32
33 pub fn with_source(mut self, source_position: SourcePosition) -> Self {
34 self.source = Some(source_position);
35 self
36 }
37
38 pub fn nil() -> Self {
39 Self {
40 value: Value::List(vec![]),
41 source: None,
42 }
43 }
44
45 pub fn t() -> Self {
46 Self {
47 value: Value::True,
48 source: None,
49 }
50 }
51
52 pub fn get_value(&self) -> &Value {
53 &self.value
54 }
55
56 pub fn into_value(self) -> Value {
57 self.value
58 }
59
60 pub fn source(&self) -> &'_ Option<SourcePosition> {
61 &self.source
62 }
63
64 pub fn eval_async(
65 self,
66 parent_snapshot: Locker<CallSnapshot>,
67 env: Locker<Environment>,
68 ) -> Result<mpsc::Receiver<Result<Self, Exception>>, Exception> {
69 let exp = self;
70 let snap = parent_snapshot.clone();
71 let (sender, receiver) = mpsc::channel::<Result<Self, Exception>>();
73 if let Ok(th) = thread::Builder::new()
74 .stack_size(64 * 1024 * 1024)
75 .spawn(move || {
76 sender.send(exp.eval(snap, env)).unwrap();
77 })
78 {
79 match th.join() {
80 Ok(_) => {}
81 Err(_) => {
82 return Err(Exception::new(
83 EV::Concurrency,
84 Some(parent_snapshot),
85 Some("could not wait for thread to finish executing".to_string()),
86 ))
87 }
88 }
89 };
90 Ok(receiver)
91 }
92
93 pub fn eval(
94 &self,
95 parent_snapshot: Locker<CallSnapshot>,
96 env: Locker<Environment>,
97 ) -> Result<Self, Exception> {
98 use Value::*;
99
100 let snapshot = CallSnapshot::new(&self, &parent_snapshot)?;
101
102 let snap = || snapshot.clone();
103
104 match &self.value {
105 List(vals) => {
106 if !vals.is_empty() {
107 let operator = vals.get(0).unwrap();
108 let arguments: Vec<&Expression> = vals.iter().skip(1).collect();
109 match &operator.value {
110 Operator(operand) => operand.apply(snapshot, arguments, self, env),
111 List(_) | Symbol(_) => {
112 let evaled_operator = operator.eval(snap(), env.clone())?;
113 let mut new_list = vec![evaled_operator];
114 for arg in arguments {
115 new_list.push(arg.clone());
116 }
117 Expression::new(Value::List(new_list)).eval(snap(), env)
118 }
119 Lambda(function) | Macro(function) => {
120 let mut scoped_env = match &operator.value {
121 Lambda(_) => Environment::root()
122 .with_parent(function.lexical_scope.clone(), None),
123 Macro(_) => {
124 let mut env =
125 Environment::root().with_parent(env.clone(), None);
126 env.add_parent(function.lexical_scope.clone(), None);
127 env
128 }
129 _ => unreachable!(),
130 };
131
132 if function.collapse_input {
133 let sym = function.params.get(0).unwrap(); let args_evaled = {
135 let mut list = Vec::new();
136 for arg_expr in arguments {
137 list.push(match &operator.value {
138 Lambda { .. } => arg_expr.eval(snap(), env.clone())?,
139 Macro { .. } => arg_expr.clone(),
140 _ => unreachable!(),
141 });
142 }
143 list
144 };
145 let arg = Expression::new(Value::List(args_evaled));
146 scoped_env.assign(sym.clone(), arg, true, snap())?;
147 } else {
148 exp_assert!(
149 function.params.len() == arguments.len(),
150 EV::ArgumentMismatch(
151 arguments.len(),
152 format!("{}", function.params.len())
153 ),
154 snap()
155 );
156 for (symbol, arg_expr) in
157 function.params.iter().zip(arguments.into_iter())
158 {
159 let arg_evaled = match &operator.value {
160 Lambda { .. } => arg_expr.eval(snap(), env.clone())?,
161 Macro { .. } => arg_expr.clone(),
162 _ => unreachable!(),
163 };
164 scoped_env.assign(symbol.clone(), arg_evaled, true, snap())?;
165 }
166 }
167 if let Macro { .. } = &operator.value {
168 scoped_env = scoped_env.shadow();
169 };
170 let mut result = Expression::nil();
171 let scoped_env_lock = Locker::new(scoped_env);
172 for exp in &function.expressions {
173 result = exp.eval(snap(), scoped_env_lock.clone())?;
174 }
175 Ok(result)
176 }
177 val => exp!(EV::InvalidOperator(val.clone()), snapshot),
178 }
179 } else {
180 Ok(self.clone())
181 }
182 }
183 Symbol(sym) => match env
184 .read()
185 .expect("unable to access environment (are threads locked?)")
186 .lookup(&sym)
187 {
188 Some(exp) => Ok(exp.read().unwrap().clone()), None => exp!(EV::UndefinedSymbol(sym.clone()), snapshot),
190 },
191 _ => Ok(self.clone()),
192 }
193 }
194}
195
196impl fmt::Display for Expression {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 write!(f, "{}", self.value)
199 }
200}
201
202impl PartialOrd for Expression {
203 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
204 self.value.partial_cmp(&other.value)
205 }
206}