From 733a7df549aa7bb7a7bb727a25235f25db875ecd Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 31 Mar 2021 20:22:04 +0530 Subject: introduce basic canvas primitive functions --- src/app.rs | 10 +++++----- src/lisp/error.rs | 3 +++ src/lisp/number.rs | 6 ++++++ src/lisp/prelude.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- src/lisp/std.lisp | 6 ++++++ 5 files changed, 63 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/app.rs b/src/app.rs index 1263324..377c613 100644 --- a/src/app.rs +++ b/src/app.rs @@ -662,6 +662,11 @@ impl<'ctx> AppState<'ctx> { self.apply_operation(op, OpKind::Undo); } } + Keycode::R => { + if let Some(op) = self.undo_stack.redo() { + self.apply_operation(op, OpKind::Redo); + } + } // export to file Keycode::N => { let image = self.export(); @@ -670,11 +675,6 @@ impl<'ctx> AppState<'ctx> { eprintln!("writing to file"); buffer.write_all(&encoded[..]).unwrap(); } - Keycode::R => { - if let Some(op) = self.undo_stack.redo() { - self.apply_operation(op, OpKind::Redo); - } - } _ => (), } } diff --git a/src/lisp/error.rs b/src/lisp/error.rs index f905e6d..f323bb8 100644 --- a/src/lisp/error.rs +++ b/src/lisp/error.rs @@ -1,6 +1,7 @@ use crate::lisp::{ expr::{Arity, LispExpr}, lex::{Span, SpanDisplay}, + number::LispNumber, }; use std::{fmt, io}; @@ -98,6 +99,7 @@ pub enum EvalError { TypeMismatch, NoFileName, AccessEmptyList, + InvalidCoordinates((LispNumber, LispNumber)), AssertionError { expected: LispExpr, got: LispExpr }, ScriptLoadError(io::Error), CustomInternal(&'static str), @@ -125,6 +127,7 @@ impl fmt::Display for EvalError { Self::DivByZero => write!(f, "attempt to divide by zero"), Self::NoFileName => write!(f, "no file name specified"), Self::AccessEmptyList => write!(f, "attempted to access empty list"), + Self::InvalidCoordinates((x, y)) => write!(f, "invalid coordinates: {} {}", x, y), Self::AssertionError { expected, got } => { write!(f, "assertion error: expected `{}` got `{}`", expected, got) } diff --git a/src/lisp/number.rs b/src/lisp/number.rs index 0ce5ac0..4ca890a 100644 --- a/src/lisp/number.rs +++ b/src/lisp/number.rs @@ -26,6 +26,12 @@ impl LispNumber { }); } } + pub fn unwrap_integer(self) -> i64 { + match self { + Self::Integer(x) => x, + Self::Float(x) => x.floor() as i64, // lossy + } + } } impl Add for LispNumber { diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index 54c831f..4a6a4ed 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs @@ -1,4 +1,5 @@ use crate::{ + bitmap::MapPoint, brush::Brush, lisp::{ error::{EvalError, LispError}, @@ -7,6 +8,7 @@ use crate::{ Environment, }, primitive, + undo::PaintRecord, utils::load_script, }; @@ -39,7 +41,8 @@ macro_rules! type_match { { let mut temp_vec = vec![]; $( - for arg in &$args[$range] { + let arg_range: &[LispExpr] = &$args[$range]; + for arg in arg_range { temp_vec.push(matches!(arg, $kind)); } )+ @@ -334,5 +337,44 @@ pub fn new_env() -> Result { } }); + primitive!(env, Arity::Exact(0), "canvas-width", |_, app| { + return Ok(LispExpr::Number(LispNumber::Integer(app.width() as i64))); + }); + + primitive!(env, Arity::Exact(0), "canvas-height", |_, app| { + return Ok(LispExpr::Number(LispNumber::Integer(app.height() as i64))); + }); + + primitive!(env, Arity::Exact(3), "set-pixel!", |args, app| { + if type_match!( + args, 0 => LispExpr::Number(LispNumber::Integer(_)), + 1 => LispExpr::Number(LispNumber::Integer(_)), + 2 => LispExpr::BoolLit(_) + ) { + let x = args[0].unwrap_number(); + let y = args[1].unwrap_number(); + let val = args[2].cast_bool(); + + let set_loc: MapPoint = (x.unwrap_integer(), y.unwrap_integer()) + .try_into() + .map_err(|_| -> LispError { EvalError::InvalidCoordinates((x, y)).into() })?; + if !app.pixmap.contains(set_loc) { + return Err(EvalError::InvalidCoordinates((x, y)).into()); + } else { + let old_val = app.pixmap.set(set_loc, val); + app.current_operation + .push(PaintRecord::new(set_loc, old_val, val)); + return Ok(LispExpr::Unit); + } + } else { + return Err(EvalError::TypeMismatch.into()); + } + }); + + primitive!(env, Arity::Exact(0), "commit", |_, app| { + app.commit_operation(); + return Ok(LispExpr::Unit); + }); + Ok(env) } diff --git a/src/lisp/std.lisp b/src/lisp/std.lisp index d54b32c..97c3984 100644 --- a/src/lisp/std.lisp +++ b/src/lisp/std.lisp @@ -45,3 +45,9 @@ (define (sum ls) (fold 0 + ls)) (define (product ls) (fold 1 * ls)) + +(define (enumerate start stop step) + (if (> start stop) + '() + (cons start + (enumerate (+ start step) stop step)))) -- cgit v1.2.3