From 92b532e70f7650d7a5fc942cc3a56bc838e57f8c Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 31 Mar 2021 16:53:09 +0530 Subject: add save and save-as procedures --- src/lisp/prelude.rs | 93 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 39 deletions(-) (limited to 'src/lisp') 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::{ brush::Brush, lisp::{ error::{EvalError, LispError}, - eval::Evaluator, expr::{Arity, LispExpr}, number::LispNumber, Environment, @@ -11,9 +10,7 @@ use crate::{ utils::load_script, }; -use std::{convert::TryInto, fs::File, io::Write}; - -use log::info; +use std::convert::TryInto; #[macro_export] macro_rules! primitive { @@ -142,12 +139,26 @@ pub fn new_env() -> Result { Ok(LispExpr::Unit) }); - primitive!(env, Arity::Exact(2), "eq?", |args, app| { + primitive!(env, Arity::Exact(2), "eq?", |args, _| { let s = &args[0]; let o = &args[1]; - info!("comparing s: {} and o: {}", s, o); - let result = s.compare(o, &app.lisp_env); - result.map(LispExpr::BoolLit) + match (s, o) { + (LispExpr::Unit, LispExpr::Unit) => Ok(true), + (LispExpr::Number(s), LispExpr::Number(o)) => Ok(s == o), + (LispExpr::List(s), LispExpr::List(o)) => Ok(s.iter().zip(o).all(|(a, b)| a == b)), + (LispExpr::List(s), LispExpr::Unit) => Ok(s.len() == 0), + (LispExpr::Unit, LispExpr::List(s)) => Ok(s.len() == 0), + (LispExpr::StringLit(s), LispExpr::StringLit(o)) => Ok(s == o), + (LispExpr::Char(s), LispExpr::Char(o)) => Ok(s == o), + (LispExpr::BoolLit(s), LispExpr::BoolLit(o)) => Ok(s == o), + (LispExpr::Ident(s), LispExpr::Ident(o)) => Ok(s == o), + (s @ LispExpr::Quote(_, _), o @ LispExpr::Quote(_, _)) => { + // text of quotation should be equal + Ok(format!("{}", s) == format!("{}", o)) + } + _ => Err(EvalError::TypeMismatch.into()), + } + .map(LispExpr::BoolLit) }); primitive!(env, Arity::Atleast(2), ">", |args, _| { @@ -204,42 +215,26 @@ pub fn new_env() -> Result { } }); - primitive!(env, Arity::Atmost(1), "save", |args, app| { - let image = app.export().encode().unwrap(); - if type_match!(args, 0 => LispExpr::StringLit(_)) { - let mut buffer = File::create(&args[0].as_ref()).unwrap(); - buffer.write_all(&image[..]).unwrap(); - } else if let Some(p) = app.file_name { - let file_name = p; - let mut buffer = File::create(&file_name).unwrap(); - buffer.write_all(&image[..]).unwrap(); - } else { - return Err(EvalError::NoFileName.into()); + primitive!(env, Arity::Exact(0), "save", |_, app| { + if let Some(file_name) = &app.file_name { + return app + .save_as(&file_name) + .map_err(|e| LispError::Stringified(e.to_string())) + .map(|_| LispExpr::Unit); } - - return Ok(LispExpr::Unit); + return Err(EvalError::NoFileName.into()); }); - primitive!(env, Arity::Atmost(1), "brush", |args, app| { - let old_size = if matches!(app.brush, Brush::Line { .. } | Brush::Circle { .. }) { - app.brush.size().unwrap() - } else { - 0 - }; - if let [LispExpr::Quote(kind, _)] = args { - if matches!(kind.as_ref(), LispExpr::Ident(_)) { - match (&**kind).as_ref() { - "fill" => app.brush = Brush::Fill, - "circle" => app.brush = Brush::new(old_size), - "line" => app.brush = Brush::line(old_size, false), - "line-extend" => app.brush = Brush::line(old_size, true), - _ => return Err(EvalError::CustomInternal("unknown brush type").into()), - } + primitive!(env, Arity::Exact(1), "save-as", |args, app| { + match &args[0] { + LispExpr::StringLit(s) => { + return app + .save_as(&s) + .map_err(|e| LispError::Stringified(e.to_string())) + .map(|_| LispExpr::Unit); } - } else { - return Err(EvalError::TypeMismatch.into()); + _ => return Err(EvalError::TypeMismatch.into()), } - return Ok(LispExpr::Unit); }); primitive!(env, Arity::Exact(2), "cons", |args, _| { @@ -254,6 +249,26 @@ pub fn new_env() -> Result { } }); + primitive!(env, Arity::Exact(0), "brush-fill", |_, app| { + app.brush = Brush::Fill; + return Ok(LispExpr::Unit); + }); + + primitive!(env, Arity::Exact(0), "brush-circle", |_, app| { + app.brush = Brush::new(0); + return Ok(LispExpr::Unit); + }); + + primitive!(env, Arity::Exact(0), "brush-line", |_, app| { + app.brush = Brush::line(0, false); + return Ok(LispExpr::Unit); + }); + + primitive!(env, Arity::Exact(0), "brush-line-extend", |_, app| { + app.brush = Brush::line(0, true); + return Ok(LispExpr::Unit); + }); + primitive!(env, Arity::Exact(1), "car", |args, _| { if type_match!(args, 0 => LispExpr::List(_)) { return Ok(args[0].unwrap_list().swap_remove(0)); -- cgit v1.2.3