aboutsummaryrefslogtreecommitdiff
path: root/src/lisp
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-05-13 16:20:17 +0100
committerAkshay <[email protected]>2021-05-13 16:20:17 +0100
commit09ee8cc84251d1758766dedff9e25497eebb88d8 (patch)
treedc837f785ad64d6c284235aa6c53fa533a3efbf1 /src/lisp
parent41c50e4c324b19183d1c36c185878d4fa500662a (diff)
rework arity errors
Diffstat (limited to 'src/lisp')
-rw-r--r--src/lisp/eval.rs198
-rw-r--r--src/lisp/expr.rs12
2 files changed, 91 insertions, 119 deletions
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs
index 677fa23..b39730b 100644
--- a/src/lisp/eval.rs
+++ b/src/lisp/eval.rs
@@ -93,10 +93,7 @@ where
93 } 93 }
94 94
95 pub fn define_var(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 95 pub fn define_var(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
96 let arity = Arity::Exact(2); 96 (Arity::Exact(2)).check(args)?;
97 if !arity.check(args) {
98 return Err(arity.to_error());
99 }
100 match args { 97 match args {
101 [LispExpr::Ident(id), expr] => { 98 [LispExpr::Ident(id), expr] => {
102 let value = self.eval(&expr)?; 99 let value = self.eval(&expr)?;
@@ -111,7 +108,6 @@ where
111 } 108 }
112 [LispExpr::List(shorthand), body] => { 109 [LispExpr::List(shorthand), body] => {
113 // (define (func arg) <body>) shorthand 110 // (define (func arg) <body>) shorthand
114
115 let id = shorthand[0].unwrap_ident(); 111 let id = shorthand[0].unwrap_ident();
116 let params = if shorthand.len() > 1 { 112 let params = if shorthand.len() > 1 {
117 &shorthand[1..] 113 &shorthand[1..]
@@ -144,10 +140,7 @@ where
144 } 140 }
145 141
146 pub fn set_var(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 142 pub fn set_var(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
147 let arity = Arity::Exact(2); 143 (Arity::Exact(2)).check(args)?;
148 if !arity.check(args) {
149 return Err(arity.to_error());
150 }
151 match args { 144 match args {
152 [LispExpr::Ident(id), expr] => { 145 [LispExpr::Ident(id), expr] => {
153 let value = self.eval(&expr)?; 146 let value = self.eval(&expr)?;
@@ -168,53 +161,45 @@ where
168 } 161 }
169 162
170 pub fn eval_if(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 163 pub fn eval_if(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
171 let arity = Arity::Exact(3); 164 (Arity::Exact(3)).check(args)?;
172 if !arity.check(args) { 165 match args {
173 Err(arity.to_error()) 166 [predicate, then, else_] => {
174 } else { 167 let predicate = self.eval(&predicate)?;
175 match args { 168 if matches!(predicate, LispExpr::BoolLit(false)) {
176 [predicate, then, else_] => { 169 self.eval(&else_)
177 let predicate = self.eval(&predicate)?; 170 } else {
178 if matches!(predicate, LispExpr::BoolLit(false)) { 171 self.eval(&then)
179 self.eval(&else_)
180 } else {
181 self.eval(&then)
182 }
183 }
184 _ => {
185 panic!("panicked at `if` expression")
186 } 172 }
187 } 173 }
174 _ => {
175 panic!("panicked at `if` expression")
176 }
188 } 177 }
189 } 178 }
190 179
191 pub fn eval_cond(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 180 pub fn eval_cond(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
192 let arity = Arity::Atleast(1); 181 Arity::Atleast(1).check(args)?;
193 let valid_cond_stmt = |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2); 182 let valid_cond_stmt = |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2);
194 if !arity.check(args) { 183 for cond_stmt in args {
195 Err(arity.to_error()) 184 if valid_cond_stmt(cond_stmt) {
196 } else { 185 match &cond_stmt.unwrap_list()[..] {
197 for cond_stmt in args { 186 [predicate, then] => {
198 if valid_cond_stmt(cond_stmt) { 187 if self.eval(&predicate)?.cast_bool() {
199 match &cond_stmt.unwrap_list()[..] { 188 return self.eval(&then);
200 [predicate, then] => {
201 if self.eval(&predicate)?.cast_bool() {
202 return self.eval(&then);
203 }
204 } 189 }
205 _ => return Err(EvalError::BadForm.into()),
206 } 190 }
207 } else { 191 _ => return Err(EvalError::BadForm.into()),
208 error!("bad `cond` form");
209 return Err(EvalError::BadForm.into());
210 } 192 }
193 } else {
194 error!("bad `cond` form");
195 return Err(EvalError::BadForm.into());
211 } 196 }
212 Ok(LispExpr::Unit)
213 } 197 }
198 Ok(LispExpr::Unit)
214 } 199 }
215 200
216 pub fn eval_for(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 201 pub fn eval_for(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
217 let arity = Arity::Exact(2); 202 Arity::Exact(2).check(args)?;
218 let valid_binding_stmt = |expr: &LispExpr| { 203 let valid_binding_stmt = |expr: &LispExpr| {
219 matches!( 204 matches!(
220 expr, 205 expr,
@@ -223,101 +208,89 @@ where
223 && matches!(v[0], LispExpr::Ident(_))) 208 && matches!(v[0], LispExpr::Ident(_)))
224 }; 209 };
225 210
226 if !arity.check(args) { 211 let nested_env = Environment::new();
227 Err(arity.to_error()) 212 self.app.lisp_env.push(nested_env);
228 } else { 213 match args {
229 let nested_env = Environment::new(); 214 [binding, body] => {
230 self.app.lisp_env.push(nested_env); 215 if valid_binding_stmt(binding) {
231 match args { 216 let binding = binding.unwrap_list();
232 [binding, body] => { 217 let binding_name = binding[0].unwrap_ident();
233 if valid_binding_stmt(binding) { 218 let binding_ls = self.eval(&binding[1])?;
234 let binding = binding.unwrap_list(); 219 if matches!(binding_ls, LispExpr::List(_)) {
235 let binding_name = binding[0].unwrap_ident(); 220 let binding_ls = binding_ls.unwrap_list();
236 let binding_ls = self.eval(&binding[1])?; 221 let mut result = vec![];
237 if matches!(binding_ls, LispExpr::List(_)) { 222 for bind_val in binding_ls.iter() {
238 let binding_ls = binding_ls.unwrap_list(); 223 let value = self.eval(&bind_val)?;
239 let mut result = vec![]; 224 if let Some(env) = self.app.lisp_env.last_mut() {
240 for bind_val in binding_ls.iter() { 225 env.insert(binding_name.clone(), value);
241 let value = self.eval(&bind_val)?;
242 if let Some(env) = self.app.lisp_env.last_mut() {
243 env.insert(binding_name.clone(), value);
244 }
245 result.push(self.eval(body)?);
246 } 226 }
247 self.app.lisp_env.pop(); 227 result.push(self.eval(body)?);
248 Ok(LispExpr::List(result))
249 } else {
250 error!("invalid binding form");
251 Err(EvalError::BadForm.into())
252 } 228 }
229 self.app.lisp_env.pop();
230 Ok(LispExpr::List(result))
253 } else { 231 } else {
254 error!("invalid binding form"); 232 error!("invalid binding form");
255 Err(EvalError::BadForm.into()) 233 Err(EvalError::BadForm.into())
256 } 234 }
257 } 235 } else {
258 _ => { 236 error!("invalid binding form");
259 error!("invalid for loop args");
260 Err(EvalError::BadForm.into()) 237 Err(EvalError::BadForm.into())
261 } 238 }
262 } 239 }
240 _ => {
241 error!("invalid for loop args");
242 Err(EvalError::BadForm.into())
243 }
263 } 244 }
264 } 245 }
265 246
266 pub fn eval_let(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 247 pub fn eval_let(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
267 let arity = Arity::Exact(2); 248 Arity::Exact(2).check(args)?;
268 let valid_binding_stmt = 249 let valid_binding_stmt =
269 |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2); 250 |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2);
270 if !arity.check(args) { 251 let nested_env = Environment::new();
271 Err(arity.to_error()) 252 self.app.lisp_env.push(nested_env);
272 } else { 253 match args {
273 let nested_env = Environment::new(); 254 [LispExpr::List(bindings), body] => {
274 self.app.lisp_env.push(nested_env); 255 for binding_stmt in bindings {
275 match args { 256 if valid_binding_stmt(binding_stmt) {
276 [LispExpr::List(bindings), body] => { 257 match &binding_stmt.unwrap_list()[..] {
277 for binding_stmt in bindings { 258 [LispExpr::Ident(id), bind_val] => {
278 if valid_binding_stmt(binding_stmt) { 259 let value = self.eval(&bind_val)?;
279 match &binding_stmt.unwrap_list()[..] { 260 if let Some(env) = self.app.lisp_env.last_mut() {
280 [LispExpr::Ident(id), bind_val] => { 261 env.insert(id.into(), value);
281 let value = self.eval(&bind_val)?;
282 if let Some(env) = self.app.lisp_env.last_mut() {
283 env.insert(id.into(), value);
284 }
285 }
286 _ => {
287 error!("bad let binding form");
288 return Err(EvalError::BadForm.into());
289 } 262 }
290 } 263 }
291 } else { 264 _ => {
292 error!("bad `let` form"); 265 error!("bad let binding form");
293 return Err(EvalError::BadForm.into()); 266 return Err(EvalError::BadForm.into());
267 }
294 } 268 }
269 } else {
270 error!("bad `let` form");
271 return Err(EvalError::BadForm.into());
295 } 272 }
296 let result = self.eval(&body);
297 self.app.lisp_env.pop();
298 result
299 }
300 _ => {
301 error!("bad `let` form");
302 Err(EvalError::BadForm.into())
303 } 273 }
274 let result = self.eval(&body);
275 self.app.lisp_env.pop();
276 result
277 }
278 _ => {
279 error!("bad `let` form");
280 Err(EvalError::BadForm.into())
304 } 281 }
305 } 282 }
306 } 283 }
307 284
308 pub fn eval_bind_key(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 285 pub fn eval_bind_key(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
309 let arity = Arity::Exact(2); 286 Arity::Exact(2).check(args)?;
310 if !arity.check(args) { 287 match args {
311 Err(arity.to_error()) 288 [LispExpr::StringLit(s), body] => {
312 } else { 289 let bind = Keybind::from_str(&s).map_err(EvalError::KeybindError)?;
313 match args { 290 self.app.keybinds.insert(bind, body.clone());
314 [LispExpr::StringLit(s), body] => { 291 Ok(LispExpr::Unit)
315 let bind = Keybind::from_str(&s).map_err(EvalError::KeybindError)?;
316 self.app.keybinds.insert(bind, body.clone());
317 Ok(LispExpr::Unit)
318 }
319 _ => Err(EvalError::BadForm.into()),
320 } 292 }
293 _ => Err(EvalError::BadForm.into()),
321 } 294 }
322 } 295 }
323} 296}
@@ -336,10 +309,7 @@ pub fn apply_quote(arg: &LispExpr) -> LispExpr {
336} 309}
337 310
338pub fn create_lambda(cdr: &[LispExpr]) -> Result<LispExpr, LispError> { 311pub fn create_lambda(cdr: &[LispExpr]) -> Result<LispExpr, LispError> {
339 let arity: Arity = Arity::Exact(2); 312 Arity::Exact(2).check(cdr)?;
340 if !arity.check(cdr) {
341 return Err(arity.to_error());
342 }
343 match cdr { 313 match cdr {
344 [LispExpr::List(params), body] if type_match!(params, (..) => LispExpr::Ident(_)) => { 314 [LispExpr::List(params), body] if type_match!(params, (..) => LispExpr::Ident(_)) => {
345 Ok(LispExpr::Function(LispFunction { 315 Ok(LispExpr::Function(LispFunction {
diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs
index 045991e..6f5b139 100644
--- a/src/lisp/expr.rs
+++ b/src/lisp/expr.rs
@@ -26,13 +26,17 @@ pub enum Arity {
26} 26}
27 27
28impl Arity { 28impl Arity {
29 pub fn check<T>(self, args: &[T]) -> bool { 29 pub fn check<T>(self, args: &[T]) -> Result<(), LispError> {
30 match self { 30 if !match self {
31 Arity::Exact(a) => args.len() == a, 31 Arity::Exact(a) => args.len() == a,
32 Arity::Atleast(a) => args.len() >= a, 32 Arity::Atleast(a) => args.len() >= a,
33 Arity::Atmost(a) => args.len() <= a, 33 Arity::Atmost(a) => args.len() <= a,
34 Arity::Range(low, high) => args.len() >= low && args.len() <= high, 34 Arity::Range(low, high) => args.len() >= low && args.len() <= high,
35 Arity::None => true, 35 Arity::None => true,
36 } {
37 Err(self.to_error())
38 } else {
39 Ok(())
36 } 40 }
37 } 41 }
38 pub fn to_error(self) -> LispError { 42 pub fn to_error(self) -> LispError {
@@ -49,9 +53,7 @@ pub struct PrimitiveFunc {
49 53
50impl PrimitiveFunc { 54impl PrimitiveFunc {
51 pub fn call(&self, args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> { 55 pub fn call(&self, args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> {
52 if !self.arity.check(args) { 56 self.arity.check(args)?;
53 return Err(EvalError::ArgumentCount(self.arity).into());
54 }
55 (self.closure)(args, app) 57 (self.closure)(args, app)
56 } 58 }
57} 59}