aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-03-29 07:42:46 +0100
committerAkshay <[email protected]>2021-03-29 07:42:46 +0100
commitdadbf350405967c0bf967eed6686b02c2cf6a048 (patch)
tree88128dabd280e319b4a6fa84d0382b22f476bcbf
parentf6e89e13d6b4db769f30b64408fc4b5995ab6cbb (diff)
more list primitives, add type_match macro
-rw-r--r--src/lisp/expr.rs11
-rw-r--r--src/lisp/prelude.rs47
2 files changed, 49 insertions, 9 deletions
diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs
index 059113b..934bb4a 100644
--- a/src/lisp/expr.rs
+++ b/src/lisp/expr.rs
@@ -150,11 +150,13 @@ impl fmt::Display for LispExpr {
150 LispExpr::Unit => write!(f, "()")?, 150 LispExpr::Unit => write!(f, "()")?,
151 LispExpr::Number(n) => write!(f, "{}", n)?, 151 LispExpr::Number(n) => write!(f, "{}", n)?,
152 LispExpr::List(l) => { 152 LispExpr::List(l) => {
153 for expr in l.iter() { 153 write!(
154 write!(f, " {} ", expr)? 154 f,
155 } 155 "({})",
156 &l.iter().map(|expr| format!("{}", expr)).collect::<Vec<_>>()[..].join(" ")
157 )?;
156 } 158 }
157 LispExpr::StringLit(s) => write!(f, "{}", s)?, 159 LispExpr::StringLit(s) => write!(f, "{:?}", s)?,
158 LispExpr::Char(c) => write!(f, "{}", c)?, 160 LispExpr::Char(c) => write!(f, "{}", c)?,
159 LispExpr::BoolLit(b) => { 161 LispExpr::BoolLit(b) => {
160 if *b { 162 if *b {
@@ -243,6 +245,7 @@ impl TryFrom<LispExpr> for String {
243 fn try_from(value: LispExpr) -> Result<Self, Self::Error> { 245 fn try_from(value: LispExpr) -> Result<Self, Self::Error> {
244 match value { 246 match value {
245 LispExpr::StringLit(i) => Ok(i), 247 LispExpr::StringLit(i) => Ok(i),
248 LispExpr::Ident(i) => Ok(i),
246 _ => Err(LispError::Eval(EvalError::TypeMismatch)), 249 _ => Err(LispError::Eval(EvalError::TypeMismatch)),
247 } 250 }
248 } 251 }
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs
index 3b8f151..d8a930b 100644
--- a/src/lisp/prelude.rs
+++ b/src/lisp/prelude.rs
@@ -2,6 +2,7 @@ use crate::{
2 brush::Brush, 2 brush::Brush,
3 lisp::{ 3 lisp::{
4 error::{EvalError, LispError}, 4 error::{EvalError, LispError},
5 eval::eval,
5 expr::{is_ident, Arity, LispExpr}, 6 expr::{is_ident, Arity, LispExpr},
6 number::LispNumber, 7 number::LispNumber,
7 Environment, 8 Environment,
@@ -24,6 +25,19 @@ macro_rules! primitive {
24 }; 25 };
25} 26}
26 27
28#[macro_export]
29macro_rules! type_match {
30 ($args:expr, $($range:expr => $kind:pat),+) => {
31 {
32 let mut temp_vec = vec![];
33 $(
34 temp_vec.push(matches!(&$args[$range], $kind));
35 )+
36 temp_vec.iter().all(|&t| t)
37 }
38 }
39}
40
27pub fn new_env() -> Environment { 41pub fn new_env() -> Environment {
28 let mut env = Environment::new(); 42 let mut env = Environment::new();
29 43
@@ -172,15 +186,18 @@ pub fn new_env() -> Environment {
172 }); 186 });
173 187
174 primitive!(env, Arity::Exact(1), "string-len", |args, _| { 188 primitive!(env, Arity::Exact(1), "string-len", |args, _| {
175 match &args[0] { 189 if type_match!(args, 0 => LispExpr::StringLit(_)) {
176 LispExpr::StringLit(s) => Ok(LispExpr::Number(LispNumber::Integer(s.len() as i64))), 190 Ok(LispExpr::Number(LispNumber::Integer(
177 _ => Err(EvalError::TypeMismatch.into()), 191 args[0].as_ref().len() as i64,
192 )))
193 } else {
194 Err(EvalError::TypeMismatch.into())
178 } 195 }
179 }); 196 });
180 197
181 primitive!(env, Arity::Atmost(1), "save", |args, app| { 198 primitive!(env, Arity::Atmost(1), "save", |args, app| {
182 let image = app.export().encode().unwrap(); 199 let image = app.export().encode().unwrap();
183 if args.len() == 1 && matches!(&args[0], LispExpr::StringLit(_)) { 200 if type_match!(args, 0 => LispExpr::StringLit(_)) {
184 let mut buffer = File::create(&args[0].as_ref()).unwrap(); 201 let mut buffer = File::create(&args[0].as_ref()).unwrap();
185 buffer.write_all(&image[..]).unwrap(); 202 buffer.write_all(&image[..]).unwrap();
186 } else if let Some(p) = app.file_name { 203 } else if let Some(p) = app.file_name {
@@ -195,7 +212,6 @@ pub fn new_env() -> Environment {
195 }); 212 });
196 213
197 primitive!(env, Arity::Atmost(1), "brush", |args, app| { 214 primitive!(env, Arity::Atmost(1), "brush", |args, app| {
198 info!("brush {}", &args[0]);
199 let old_size = if matches!(app.brush, Brush::Line { .. } | Brush::Circle { .. }) { 215 let old_size = if matches!(app.brush, Brush::Line { .. } | Brush::Circle { .. }) {
200 app.brush.size().unwrap() 216 app.brush.size().unwrap()
201 } else { 217 } else {
@@ -217,5 +233,26 @@ pub fn new_env() -> Environment {
217 return Ok(LispExpr::Unit); 233 return Ok(LispExpr::Unit);
218 }); 234 });
219 235
236 primitive!(env, Arity::Exact(2), "map", |args, app| {
237 let mut apply_map =
238 |func: &LispExpr, ls: &Vec<LispExpr>| -> Result<Vec<LispExpr>, LispError> {
239 ls.into_iter()
240 .map(|arg| eval(&LispExpr::List(vec![func.clone(), arg.clone()]), app))
241 .collect()
242 };
243 if matches!(&args[0], LispExpr::Function(_) | LispExpr::PrimitiveFunc(_)) {
244 match &args[1] {
245 LispExpr::List(ls) => return Ok(LispExpr::List(apply_map(&args[0], ls)?)),
246 _ => return Err(EvalError::TypeMismatch.into()),
247 }
248 } else {
249 return Err(EvalError::TypeMismatch.into());
250 }
251 });
252
253 primitive!(env, Arity::Atleast(1), "list", |args, _| {
254 return Ok(LispExpr::List(args.to_vec()));
255 });
256
220 env 257 env
221} 258}