diff options
-rw-r--r-- | src/app.rs | 25 | ||||
-rw-r--r-- | src/error.rs | 42 | ||||
-rw-r--r-- | src/lisp/parse.rs | 46 |
3 files changed, 81 insertions, 32 deletions
@@ -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 | ||
15 | use std::{convert::From, fs::File, io::prelude::*, path::Path}; | 16 | use 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 @@ | |||
1 | use crate::lisp::error::LispError; | ||
2 | |||
3 | use std::{error, fmt, io}; | ||
4 | |||
5 | use sdl2::ttf; | ||
6 | |||
7 | #[derive(Debug)] | ||
8 | pub enum AppError { | ||
9 | Lisp(LispError), | ||
10 | File(io::Error), | ||
11 | Sdl(String), | ||
12 | SdlTTF(SdlTTFError), | ||
13 | } | ||
14 | |||
15 | impl 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)] | ||
27 | pub enum SdlTTFError { | ||
28 | Font(ttf::FontError), | ||
29 | Init(ttf::InitError), | ||
30 | } | ||
31 | |||
32 | impl 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 | |||
41 | impl error::Error for AppError {} | ||
42 | impl 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)] |
204 | mod tests { | 210 | mod 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() |