aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.rs25
-rw-r--r--src/error.rs42
-rw-r--r--src/lisp/parse.rs46
3 files changed, 81 insertions, 32 deletions
diff --git a/src/app.rs b/src/app.rs
index ffa73dd..fb6e9df 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -2,14 +2,15 @@ use crate::{
2 bitmap::{positive_angle_with_x, MapPoint, Pixmap}, 2 bitmap::{positive_angle_with_x, MapPoint, Pixmap},
3 brush::{Brush, CircleBrush, LineBrush}, 3 brush::{Brush, CircleBrush, LineBrush},
4 command::CommandBox, 4 command::CommandBox,
5 consts::{colors::*, FONT_PATH}, 5 consts::{colors::*, FONT_PATH, STDLIB_PATH},
6 dither, 6 dither,
7 error::AppError,
7 lisp::{eval, lex::Lexer, parse::Parser, prelude, EnvList}, 8 lisp::{eval, lex::Lexer, parse::Parser, prelude, EnvList},
8 message::Message, 9 message::Message,
9 rect, 10 rect,
10 symmetry::Symmetry, 11 symmetry::Symmetry,
11 undo::{ModifyRecord, OpKind, PaintRecord, UndoStack}, 12 undo::{ModifyRecord, OpKind, PaintRecord, UndoStack},
12 utils::{draw_text, handle_error, is_copy_event, is_paste_event}, 13 utils::{draw_text, handle_error, is_copy_event, is_paste_event, load_script},
13}; 14};
14 15
15use std::{convert::From, fs::File, io::prelude::*, path::Path}; 16use std::{convert::From, fs::File, io::prelude::*, path::Path};
@@ -284,7 +285,7 @@ impl<'ctx, 'file> AppState<'ctx, 'file> {
284 Ok(val) => self.message.set_info(format!("{}", val)), 285 Ok(val) => self.message.set_info(format!("{}", val)),
285 Err(eval_err) => self.message.set_error(format!("{}", eval_err)), 286 Err(eval_err) => self.message.set_error(format!("{}", eval_err)),
286 }, 287 },
287 Err(err) => self.message = handle_error(err, &lisp_expr), 288 Err(err) => self.message = handle_error(err, &lisp_expr, "repl"),
288 } 289 }
289 self.command_box.hist_append(); 290 self.command_box.hist_append();
290 291
@@ -510,8 +511,8 @@ impl<'ctx, 'file> AppState<'ctx, 'file> {
510 ttf_context: &'ctx Sdl2TtfContext, 511 ttf_context: &'ctx Sdl2TtfContext,
511 start_data: Option<Vec<bool>>, 512 start_data: Option<Vec<bool>>,
512 file_name: Option<&'file Path>, 513 file_name: Option<&'file Path>,
513 ) -> Self { 514 ) -> Result<Self, AppError> {
514 let video_subsystem = context.video().unwrap(); 515 let video_subsystem = context.video().map_err(AppError::Sdl)?;
515 516
516 let window = video_subsystem 517 let window = video_subsystem
517 .window("Pixel editor", 500, 500) 518 .window("Pixel editor", 500, 500)
@@ -519,18 +520,16 @@ impl<'ctx, 'file> AppState<'ctx, 'file> {
519 .resizable() 520 .resizable()
520 .opengl() 521 .opengl()
521 .build() 522 .build()
522 .map_err(|e| e.to_string()) 523 .map_err(|e| AppError::Sdl(e.to_string()))?;
523 .unwrap();
524 524
525 let canvas = window 525 let canvas = window
526 .into_canvas() 526 .into_canvas()
527 .build() 527 .build()
528 .map_err(|e| e.to_string()) 528 .map_err(|e| AppError::Sdl(e.to_string()))?;
529 .unwrap();
530 529
531 let data = start_data.unwrap_or(vec![false; (width * height) as usize]); 530 let data = start_data.unwrap_or(vec![false; (width * height) as usize]);
532 let pixmap = Pixmap::new_with(width, height, data); 531 let pixmap = Pixmap::new_with(width, height, data);
533 Self { 532 let mut app = Self {
534 active_color: true, 533 active_color: true,
535 brush: Brush::new(0), 534 brush: Brush::new(0),
536 canvas, 535 canvas,
@@ -540,7 +539,7 @@ impl<'ctx, 'file> AppState<'ctx, 'file> {
540 dither_level: 16, 539 dither_level: 16,
541 file_name, 540 file_name,
542 grid: Grid::new(), 541 grid: Grid::new(),
543 lisp_env: vec![prelude::new_env()], 542 lisp_env: vec![prelude::new_env().map_err(AppError::Lisp)?],
544 message: Message::new().text(" "), 543 message: Message::new().text(" "),
545 mode: Mode::Draw, 544 mode: Mode::Draw,
546 mouse: (0, 0), 545 mouse: (0, 0),
@@ -550,7 +549,9 @@ impl<'ctx, 'file> AppState<'ctx, 'file> {
550 ttf_context, 549 ttf_context,
551 undo_stack: UndoStack::new(), 550 undo_stack: UndoStack::new(),
552 zoom: 5, 551 zoom: 5,
553 } 552 };
553 load_script(STDLIB_PATH, &mut app).map_err(AppError::Lisp)?;
554 Ok(app)
554 } 555 }
555 556
556 pub fn export(&self) -> Image { 557 pub fn export(&self) -> Image {
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..ff25db7
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,42 @@
1use crate::lisp::error::LispError;
2
3use std::{error, fmt, io};
4
5use sdl2::ttf;
6
7#[derive(Debug)]
8pub enum AppError {
9 Lisp(LispError),
10 File(io::Error),
11 Sdl(String),
12 SdlTTF(SdlTTFError),
13}
14
15impl fmt::Display for AppError {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 Self::Lisp(e) => write!(f, "lisp error: {}", e),
19 Self::File(e) => write!(f, "file error: {}", e),
20 Self::Sdl(e) => write!(f, "sdl2 error: {}", e),
21 Self::SdlTTF(e) => write!(f, "ttf error: {}", e),
22 }
23 }
24}
25
26#[derive(Debug)]
27pub enum SdlTTFError {
28 Font(ttf::FontError),
29 Init(ttf::InitError),
30}
31
32impl fmt::Display for SdlTTFError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Self::Font(e) => write!(f, "font error: {}", e),
36 Self::Init(e) => write!(f, "init error: {}", e),
37 }
38 }
39}
40
41impl error::Error for AppError {}
42impl error::Error for SdlTTFError {}
diff --git a/src/lisp/parse.rs b/src/lisp/parse.rs
index 6a8de9f..737e7ad 100644
--- a/src/lisp/parse.rs
+++ b/src/lisp/parse.rs
@@ -25,22 +25,28 @@ impl<'lex> Parser<'lex> {
25 } 25 }
26 } 26 }
27 27
28 pub fn parse_expr(&mut self) -> Result<LispExpr, LispError> { 28 pub fn parse_expr(&mut self) -> Result<LispExpr, ParseError> {
29 let mut stack = Vec::new(); 29 let mut stack = Vec::new();
30 let mut total_backticks = 0; 30 let mut total_backticks = 0;
31 loop { 31 loop {
32 let (span, token) = self.next()?; 32 let (span, token) = self.next()?;
33 let r: Result<LispExpr, LispError> = match token { 33 let r: Result<LispExpr, ParseError> = match token {
34 Token::LeftParen => { 34 Token::LeftParen => {
35 stack.push(Group::Parens(Vec::new())); 35 stack.push(Group::Parens(Vec::new()));
36 continue; 36 continue;
37 } 37 }
38 Token::RightParen => { 38 Token::RightParen => {
39 let group = stack.pop().ok_or_else( 39 let group = stack
40 || (ParseError::new(span, ParseErrorKind::UnmatchedParen)), // unmatched paren here 40 .pop()
41 )?; 41 .ok_or_else(|| (ParseError::new(span, ParseErrorKind::UnmatchedParen)))?;
42 match group { 42 match group {
43 Group::Parens(v) => Ok(LispExpr::List(v)), 43 Group::Parens(v) => {
44 if v.len() == 0 {
45 Ok(LispExpr::Unit)
46 } else {
47 Ok(LispExpr::List(v))
48 }
49 }
44 _ => Err(From::from(ParseError::new( 50 _ => Err(From::from(ParseError::new(
45 span, 51 span,
46 ParseErrorKind::UnexpectedToken { 52 ParseErrorKind::UnexpectedToken {
@@ -59,11 +65,11 @@ impl<'lex> Parser<'lex> {
59 .map(|n| LispExpr::Number(LispNumber::Integer(n))) 65 .map(|n| LispExpr::Number(LispNumber::Integer(n)))
60 .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), 66 .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()),
61 Token::String(s) => Ok(LispExpr::StringLit(s[1..s.len() - 1].into())), 67 Token::String(s) => Ok(LispExpr::StringLit(s[1..s.len() - 1].into())),
62 Token::Char(s) => Ok(LispExpr::Char(s.chars().nth(2).ok_or_else( 68 Token::Char(s) => {
63 || -> LispError { 69 Ok(LispExpr::Char(s.chars().nth(2).ok_or_else(|| {
64 ParseError::new(span, ParseErrorKind::LiteralParseError).into() 70 ParseError::new(span, ParseErrorKind::LiteralParseError)
65 }, 71 })?))
66 )?)), 72 }
67 Token::Name(n) => Ok(name_expr(n)), 73 Token::Name(n) => Ok(name_expr(n)),
68 Token::BackQuote => { 74 Token::BackQuote => {
69 total_backticks += 1; 75 total_backticks += 1;
@@ -76,7 +82,7 @@ impl<'lex> Parser<'lex> {
76 } 82 }
77 Token::Comma => { 83 Token::Comma => {
78 if total_backticks <= 0 { 84 if total_backticks <= 0 {
79 return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); 85 return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma));
80 } 86 }
81 total_backticks -= 1; 87 total_backticks -= 1;
82 if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { 88 if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() {
@@ -88,7 +94,7 @@ impl<'lex> Parser<'lex> {
88 } 94 }
89 Token::CommaAt => { 95 Token::CommaAt => {
90 if total_backticks <= 0 { 96 if total_backticks <= 0 {
91 return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); 97 return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma));
92 } 98 }
93 total_backticks -= 1; 99 total_backticks -= 1;
94 stack.push(Group::CommaAt); 100 stack.push(Group::CommaAt);
@@ -109,9 +115,9 @@ impl<'lex> Parser<'lex> {
109 }); 115 });
110 116
111 if any_paren { 117 if any_paren {
112 Err(ParseError::new(span, ParseErrorKind::MissingCloseParen).into()) 118 Err(ParseError::new(span, ParseErrorKind::MissingCloseParen))
113 } else { 119 } else {
114 Err(ParseError::new(span, ParseErrorKind::UnexpectedEof).into()) 120 Err(ParseError::new(span, ParseErrorKind::UnexpectedEof))
115 } 121 }
116 } 122 }
117 }; 123 };
@@ -148,13 +154,13 @@ impl<'lex> Parser<'lex> {
148 } 154 }
149 } 155 }
150 156
151 fn next(&mut self) -> Result<(Span, Token<'lex>), LispError> { 157 fn next(&mut self) -> Result<(Span, Token<'lex>), ParseError> {
152 let r = self.peek()?; 158 let r = self.peek()?;
153 self.cur_token = None; 159 self.cur_token = None;
154 Ok(r) 160 Ok(r)
155 } 161 }
156 162
157 fn peek(&mut self) -> Result<(Span, Token<'lex>), LispError> { 163 fn peek(&mut self) -> Result<(Span, Token<'lex>), ParseError> {
158 if let Some(tok) = self.cur_token { 164 if let Some(tok) = self.cur_token {
159 Ok(tok) 165 Ok(tok)
160 } else { 166 } else {
@@ -164,7 +170,7 @@ impl<'lex> Parser<'lex> {
164 } 170 }
165 } 171 }
166 172
167 pub fn parse_single_expr(&mut self) -> Result<LispExpr, LispError> { 173 pub fn parse_single_expr(&mut self) -> Result<LispExpr, ParseError> {
168 let expr = self.parse_expr()?; 174 let expr = self.parse_expr()?;
169 175
170 match self.next()? { 176 match self.next()? {
@@ -180,7 +186,7 @@ impl<'lex> Parser<'lex> {
180 } 186 }
181 } 187 }
182 188
183 pub fn parse_exprs(&mut self) -> Result<Vec<LispExpr>, LispError> { 189 pub fn parse_exprs(&mut self) -> Result<Vec<LispExpr>, ParseError> {
184 let mut res = Vec::new(); 190 let mut res = Vec::new();
185 loop { 191 loop {
186 match self.peek()? { 192 match self.peek()? {
@@ -203,7 +209,7 @@ fn name_expr(input: &str) -> LispExpr {
203#[cfg(test)] 209#[cfg(test)]
204mod tests { 210mod tests {
205 use super::*; 211 use super::*;
206 fn parse(input: &str) -> Result<LispExpr, LispError> { 212 fn parse(input: &str) -> Result<LispExpr, ParseError> {
207 let mut parser = Parser::new(Lexer::new(input, 0)); 213 let mut parser = Parser::new(Lexer::new(input, 0));
208 214
209 parser.parse_single_expr() 215 parser.parse_single_expr()