aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-03-31 12:23:09 +0100
committerAkshay <[email protected]>2021-03-31 12:23:09 +0100
commit92b532e70f7650d7a5fc942cc3a56bc838e57f8c (patch)
tree901a6c89cea67c39f468556ca4cb1d3b88a0259c
parentdbc0ab93141784dc07a7e193024fc5716dd34214 (diff)
add save and save-as procedures
-rw-r--r--src/lisp/prelude.rs93
1 files changed, 54 insertions, 39 deletions
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs
index 27e7ad2..54c831f 100644
--- a/src/lisp/prelude.rs
+++ b/src/lisp/prelude.rs
@@ -2,7 +2,6 @@ use crate::{
2 brush::Brush, 2 brush::Brush,
3 lisp::{ 3 lisp::{
4 error::{EvalError, LispError}, 4 error::{EvalError, LispError},
5 eval::Evaluator,
6 expr::{Arity, LispExpr}, 5 expr::{Arity, LispExpr},
7 number::LispNumber, 6 number::LispNumber,
8 Environment, 7 Environment,
@@ -11,9 +10,7 @@ use crate::{
11 utils::load_script, 10 utils::load_script,
12}; 11};
13 12
14use std::{convert::TryInto, fs::File, io::Write}; 13use std::convert::TryInto;
15
16use log::info;
17 14
18#[macro_export] 15#[macro_export]
19macro_rules! primitive { 16macro_rules! primitive {
@@ -142,12 +139,26 @@ pub fn new_env() -> Result<Environment, LispError> {
142 Ok(LispExpr::Unit) 139 Ok(LispExpr::Unit)
143 }); 140 });
144 141
145 primitive!(env, Arity::Exact(2), "eq?", |args, app| { 142 primitive!(env, Arity::Exact(2), "eq?", |args, _| {
146 let s = &args[0]; 143 let s = &args[0];
147 let o = &args[1]; 144 let o = &args[1];
148 info!("comparing s: {} and o: {}", s, o); 145 match (s, o) {
149 let result = s.compare(o, &app.lisp_env); 146 (LispExpr::Unit, LispExpr::Unit) => Ok(true),
150 result.map(LispExpr::BoolLit) 147 (LispExpr::Number(s), LispExpr::Number(o)) => Ok(s == o),
148 (LispExpr::List(s), LispExpr::List(o)) => Ok(s.iter().zip(o).all(|(a, b)| a == b)),
149 (LispExpr::List(s), LispExpr::Unit) => Ok(s.len() == 0),
150 (LispExpr::Unit, LispExpr::List(s)) => Ok(s.len() == 0),
151 (LispExpr::StringLit(s), LispExpr::StringLit(o)) => Ok(s == o),
152 (LispExpr::Char(s), LispExpr::Char(o)) => Ok(s == o),
153 (LispExpr::BoolLit(s), LispExpr::BoolLit(o)) => Ok(s == o),
154 (LispExpr::Ident(s), LispExpr::Ident(o)) => Ok(s == o),
155 (s @ LispExpr::Quote(_, _), o @ LispExpr::Quote(_, _)) => {
156 // text of quotation should be equal
157 Ok(format!("{}", s) == format!("{}", o))
158 }
159 _ => Err(EvalError::TypeMismatch.into()),
160 }
161 .map(LispExpr::BoolLit)
151 }); 162 });
152 163
153 primitive!(env, Arity::Atleast(2), ">", |args, _| { 164 primitive!(env, Arity::Atleast(2), ">", |args, _| {
@@ -204,42 +215,26 @@ pub fn new_env() -> Result<Environment, LispError> {
204 } 215 }
205 }); 216 });
206 217
207 primitive!(env, Arity::Atmost(1), "save", |args, app| { 218 primitive!(env, Arity::Exact(0), "save", |_, app| {
208 let image = app.export().encode().unwrap(); 219 if let Some(file_name) = &app.file_name {
209 if type_match!(args, 0 => LispExpr::StringLit(_)) { 220 return app
210 let mut buffer = File::create(&args[0].as_ref()).unwrap(); 221 .save_as(&file_name)
211 buffer.write_all(&image[..]).unwrap(); 222 .map_err(|e| LispError::Stringified(e.to_string()))
212 } else if let Some(p) = app.file_name { 223 .map(|_| LispExpr::Unit);
213 let file_name = p;
214 let mut buffer = File::create(&file_name).unwrap();
215 buffer.write_all(&image[..]).unwrap();
216 } else {
217 return Err(EvalError::NoFileName.into());
218 } 224 }
219 225 return Err(EvalError::NoFileName.into());
220 return Ok(LispExpr::Unit);
221 }); 226 });
222 227
223 primitive!(env, Arity::Atmost(1), "brush", |args, app| { 228 primitive!(env, Arity::Exact(1), "save-as", |args, app| {
224 let old_size = if matches!(app.brush, Brush::Line { .. } | Brush::Circle { .. }) { 229 match &args[0] {
225 app.brush.size().unwrap() 230 LispExpr::StringLit(s) => {
226 } else { 231 return app
227 0 232 .save_as(&s)
228 }; 233 .map_err(|e| LispError::Stringified(e.to_string()))
229 if let [LispExpr::Quote(kind, _)] = args { 234 .map(|_| LispExpr::Unit);
230 if matches!(kind.as_ref(), LispExpr::Ident(_)) {
231 match (&**kind).as_ref() {
232 "fill" => app.brush = Brush::Fill,
233 "circle" => app.brush = Brush::new(old_size),
234 "line" => app.brush = Brush::line(old_size, false),
235 "line-extend" => app.brush = Brush::line(old_size, true),
236 _ => return Err(EvalError::CustomInternal("unknown brush type").into()),
237 }
238 } 235 }
239 } else { 236 _ => return Err(EvalError::TypeMismatch.into()),
240 return Err(EvalError::TypeMismatch.into());
241 } 237 }
242 return Ok(LispExpr::Unit);
243 }); 238 });
244 239
245 primitive!(env, Arity::Exact(2), "cons", |args, _| { 240 primitive!(env, Arity::Exact(2), "cons", |args, _| {
@@ -254,6 +249,26 @@ pub fn new_env() -> Result<Environment, LispError> {
254 } 249 }
255 }); 250 });
256 251
252 primitive!(env, Arity::Exact(0), "brush-fill", |_, app| {
253 app.brush = Brush::Fill;
254 return Ok(LispExpr::Unit);
255 });
256
257 primitive!(env, Arity::Exact(0), "brush-circle", |_, app| {
258 app.brush = Brush::new(0);
259 return Ok(LispExpr::Unit);
260 });
261
262 primitive!(env, Arity::Exact(0), "brush-line", |_, app| {
263 app.brush = Brush::line(0, false);
264 return Ok(LispExpr::Unit);
265 });
266
267 primitive!(env, Arity::Exact(0), "brush-line-extend", |_, app| {
268 app.brush = Brush::line(0, true);
269 return Ok(LispExpr::Unit);
270 });
271
257 primitive!(env, Arity::Exact(1), "car", |args, _| { 272 primitive!(env, Arity::Exact(1), "car", |args, _| {
258 if type_match!(args, 0 => LispExpr::List(_)) { 273 if type_match!(args, 0 => LispExpr::List(_)) {
259 return Ok(args[0].unwrap_list().swap_remove(0)); 274 return Ok(args[0].unwrap_list().swap_remove(0));