aboutsummaryrefslogtreecommitdiff
path: root/src/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lisp')
-rw-r--r--src/lisp/error.rs13
-rw-r--r--src/lisp/eval.rs20
-rw-r--r--src/lisp/std.lisp15
3 files changed, 43 insertions, 5 deletions
diff --git a/src/lisp/error.rs b/src/lisp/error.rs
index 9e9dc90..7bde872 100644
--- a/src/lisp/error.rs
+++ b/src/lisp/error.rs
@@ -1,7 +1,10 @@
1use crate::lisp::{ 1use crate::{
2 expr::{Arity, LispExpr}, 2 keybind::KeybindError,
3 lex::{Span, SpanDisplay}, 3 lisp::{
4 number::LispNumber, 4 expr::{Arity, LispExpr},
5 lex::{Span, SpanDisplay},
6 number::LispNumber,
7 },
5}; 8};
6 9
7use std::{fmt, io}; 10use std::{fmt, io};
@@ -104,6 +107,7 @@ pub enum EvalError {
104 AssertionError { expected: LispExpr, got: LispExpr }, 107 AssertionError { expected: LispExpr, got: LispExpr },
105 ScriptLoadError(io::Error), 108 ScriptLoadError(io::Error),
106 CustomInternal(&'static str), 109 CustomInternal(&'static str),
110 KeybindError(KeybindError),
107 Custom(String), 111 Custom(String),
108} 112}
109 113
@@ -134,6 +138,7 @@ impl fmt::Display for EvalError {
134 write!(f, "assertion error: expected `{}` got `{}`", expected, got) 138 write!(f, "assertion error: expected `{}` got `{}`", expected, got)
135 } 139 }
136 Self::ScriptLoadError(s) => write!(f, "error while loading script: {}", s), 140 Self::ScriptLoadError(s) => write!(f, "error while loading script: {}", s),
141 Self::KeybindError(k) => write!(f, "keybind error: {}", k),
137 Self::CustomInternal(s) => write!(f, "{}", s), 142 Self::CustomInternal(s) => write!(f, "{}", s),
138 Self::Custom(s) => write!(f, "error: {}", s), 143 Self::Custom(s) => write!(f, "error: {}", s),
139 } 144 }
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs
index 75cb5c9..677fa23 100644
--- a/src/lisp/eval.rs
+++ b/src/lisp/eval.rs
@@ -1,5 +1,6 @@
1use crate::{ 1use crate::{
2 app::AppState, 2 app::AppState,
3 keybind::Keybind,
3 lisp::{ 4 lisp::{
4 error::{EvalError, LispError}, 5 error::{EvalError, LispError},
5 expr::{Arity, Ident, LispExpr, LispFunction}, 6 expr::{Arity, Ident, LispExpr, LispFunction},
@@ -8,7 +9,7 @@ use crate::{
8 type_match, 9 type_match,
9}; 10};
10 11
11use std::convert::TryInto; 12use std::{convert::TryInto, str::FromStr};
12 13
13use log::{error, info}; 14use log::{error, info};
14 15
@@ -44,6 +45,7 @@ where
44 "for" => self.eval_for(&li[1..]), 45 "for" => self.eval_for(&li[1..]),
45 "quote" => Ok(apply_quote(&li[1])), 46 "quote" => Ok(apply_quote(&li[1])),
46 "let" => self.eval_let(&li[1..]), 47 "let" => self.eval_let(&li[1..]),
48 "bind-key" => self.eval_bind_key(&li[1..]),
47 _ => { 49 _ => {
48 let mut new_ls = vec![self.eval(&func_expr)?]; 50 let mut new_ls = vec![self.eval(&func_expr)?];
49 new_ls.extend(li[1..].to_vec()); 51 new_ls.extend(li[1..].to_vec());
@@ -302,6 +304,22 @@ where
302 } 304 }
303 } 305 }
304 } 306 }
307
308 pub fn eval_bind_key(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
309 let arity = Arity::Exact(2);
310 if !arity.check(args) {
311 Err(arity.to_error())
312 } else {
313 match args {
314 [LispExpr::StringLit(s), body] => {
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 }
321 }
322 }
305} 323}
306 324
307pub fn apply_quote(arg: &LispExpr) -> LispExpr { 325pub fn apply_quote(arg: &LispExpr) -> LispExpr {
diff --git a/src/lisp/std.lisp b/src/lisp/std.lisp
index a256125..fe09a8a 100644
--- a/src/lisp/std.lisp
+++ b/src/lisp/std.lisp
@@ -72,3 +72,18 @@
72 acc 72 acc
73 (rev-helper (cdr p) (cons (car p) acc)))) 73 (rev-helper (cdr p) (cons (car p) acc))))
74 (rev-helper ls '()))) 74 (rev-helper ls '())))
75
76(define (append l1 l2)
77 (if (null? l1)
78 l2
79 (cons (car l1)
80 (append (cdr l1) l2))))
81
82(define (cross xs ys)
83 (if (or (null? xs)
84 (null? ys))
85 '()
86 (fold '()
87 append
88 (map (lambda (x)
89 (map (lambda (y) (list x y)) ys)) xs))))