From a76cd56b9f8cce132555f6c3b59d76da5ae86f6b Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 30 Mar 2021 16:51:51 +0530 Subject: add new catch-all error types --- src/app.rs | 25 +++++++++++++------------ src/error.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/lisp/parse.rs | 46 ++++++++++++++++++++++++++-------------------- 3 files changed, 81 insertions(+), 32 deletions(-) create mode 100644 src/error.rs 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::{ bitmap::{positive_angle_with_x, MapPoint, Pixmap}, brush::{Brush, CircleBrush, LineBrush}, command::CommandBox, - consts::{colors::*, FONT_PATH}, + consts::{colors::*, FONT_PATH, STDLIB_PATH}, dither, + error::AppError, lisp::{eval, lex::Lexer, parse::Parser, prelude, EnvList}, message::Message, rect, symmetry::Symmetry, undo::{ModifyRecord, OpKind, PaintRecord, UndoStack}, - utils::{draw_text, handle_error, is_copy_event, is_paste_event}, + utils::{draw_text, handle_error, is_copy_event, is_paste_event, load_script}, }; use std::{convert::From, fs::File, io::prelude::*, path::Path}; @@ -284,7 +285,7 @@ impl<'ctx, 'file> AppState<'ctx, 'file> { Ok(val) => self.message.set_info(format!("{}", val)), Err(eval_err) => self.message.set_error(format!("{}", eval_err)), }, - Err(err) => self.message = handle_error(err, &lisp_expr), + Err(err) => self.message = handle_error(err, &lisp_expr, "repl"), } self.command_box.hist_append(); @@ -510,8 +511,8 @@ impl<'ctx, 'file> AppState<'ctx, 'file> { ttf_context: &'ctx Sdl2TtfContext, start_data: Option>, file_name: Option<&'file Path>, - ) -> Self { - let video_subsystem = context.video().unwrap(); + ) -> Result { + let video_subsystem = context.video().map_err(AppError::Sdl)?; let window = video_subsystem .window("Pixel editor", 500, 500) @@ -519,18 +520,16 @@ impl<'ctx, 'file> AppState<'ctx, 'file> { .resizable() .opengl() .build() - .map_err(|e| e.to_string()) - .unwrap(); + .map_err(|e| AppError::Sdl(e.to_string()))?; let canvas = window .into_canvas() .build() - .map_err(|e| e.to_string()) - .unwrap(); + .map_err(|e| AppError::Sdl(e.to_string()))?; let data = start_data.unwrap_or(vec![false; (width * height) as usize]); let pixmap = Pixmap::new_with(width, height, data); - Self { + let mut app = Self { active_color: true, brush: Brush::new(0), canvas, @@ -540,7 +539,7 @@ impl<'ctx, 'file> AppState<'ctx, 'file> { dither_level: 16, file_name, grid: Grid::new(), - lisp_env: vec![prelude::new_env()], + lisp_env: vec![prelude::new_env().map_err(AppError::Lisp)?], message: Message::new().text(" "), mode: Mode::Draw, mouse: (0, 0), @@ -550,7 +549,9 @@ impl<'ctx, 'file> AppState<'ctx, 'file> { ttf_context, undo_stack: UndoStack::new(), zoom: 5, - } + }; + load_script(STDLIB_PATH, &mut app).map_err(AppError::Lisp)?; + Ok(app) } 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 @@ +use crate::lisp::error::LispError; + +use std::{error, fmt, io}; + +use sdl2::ttf; + +#[derive(Debug)] +pub enum AppError { + Lisp(LispError), + File(io::Error), + Sdl(String), + SdlTTF(SdlTTFError), +} + +impl fmt::Display for AppError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Lisp(e) => write!(f, "lisp error: {}", e), + Self::File(e) => write!(f, "file error: {}", e), + Self::Sdl(e) => write!(f, "sdl2 error: {}", e), + Self::SdlTTF(e) => write!(f, "ttf error: {}", e), + } + } +} + +#[derive(Debug)] +pub enum SdlTTFError { + Font(ttf::FontError), + Init(ttf::InitError), +} + +impl fmt::Display for SdlTTFError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Font(e) => write!(f, "font error: {}", e), + Self::Init(e) => write!(f, "init error: {}", e), + } + } +} + +impl error::Error for AppError {} +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> { } } - pub fn parse_expr(&mut self) -> Result { + pub fn parse_expr(&mut self) -> Result { let mut stack = Vec::new(); let mut total_backticks = 0; loop { let (span, token) = self.next()?; - let r: Result = match token { + let r: Result = match token { Token::LeftParen => { stack.push(Group::Parens(Vec::new())); continue; } Token::RightParen => { - let group = stack.pop().ok_or_else( - || (ParseError::new(span, ParseErrorKind::UnmatchedParen)), // unmatched paren here - )?; + let group = stack + .pop() + .ok_or_else(|| (ParseError::new(span, ParseErrorKind::UnmatchedParen)))?; match group { - Group::Parens(v) => Ok(LispExpr::List(v)), + Group::Parens(v) => { + if v.len() == 0 { + Ok(LispExpr::Unit) + } else { + Ok(LispExpr::List(v)) + } + } _ => Err(From::from(ParseError::new( span, ParseErrorKind::UnexpectedToken { @@ -59,11 +65,11 @@ impl<'lex> Parser<'lex> { .map(|n| LispExpr::Number(LispNumber::Integer(n))) .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), Token::String(s) => Ok(LispExpr::StringLit(s[1..s.len() - 1].into())), - Token::Char(s) => Ok(LispExpr::Char(s.chars().nth(2).ok_or_else( - || -> LispError { - ParseError::new(span, ParseErrorKind::LiteralParseError).into() - }, - )?)), + Token::Char(s) => { + Ok(LispExpr::Char(s.chars().nth(2).ok_or_else(|| { + ParseError::new(span, ParseErrorKind::LiteralParseError) + })?)) + } Token::Name(n) => Ok(name_expr(n)), Token::BackQuote => { total_backticks += 1; @@ -76,7 +82,7 @@ impl<'lex> Parser<'lex> { } Token::Comma => { if total_backticks <= 0 { - return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); + return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); } total_backticks -= 1; if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { @@ -88,7 +94,7 @@ impl<'lex> Parser<'lex> { } Token::CommaAt => { if total_backticks <= 0 { - return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); + return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); } total_backticks -= 1; stack.push(Group::CommaAt); @@ -109,9 +115,9 @@ impl<'lex> Parser<'lex> { }); if any_paren { - Err(ParseError::new(span, ParseErrorKind::MissingCloseParen).into()) + Err(ParseError::new(span, ParseErrorKind::MissingCloseParen)) } else { - Err(ParseError::new(span, ParseErrorKind::UnexpectedEof).into()) + Err(ParseError::new(span, ParseErrorKind::UnexpectedEof)) } } }; @@ -148,13 +154,13 @@ impl<'lex> Parser<'lex> { } } - fn next(&mut self) -> Result<(Span, Token<'lex>), LispError> { + fn next(&mut self) -> Result<(Span, Token<'lex>), ParseError> { let r = self.peek()?; self.cur_token = None; Ok(r) } - fn peek(&mut self) -> Result<(Span, Token<'lex>), LispError> { + fn peek(&mut self) -> Result<(Span, Token<'lex>), ParseError> { if let Some(tok) = self.cur_token { Ok(tok) } else { @@ -164,7 +170,7 @@ impl<'lex> Parser<'lex> { } } - pub fn parse_single_expr(&mut self) -> Result { + pub fn parse_single_expr(&mut self) -> Result { let expr = self.parse_expr()?; match self.next()? { @@ -180,7 +186,7 @@ impl<'lex> Parser<'lex> { } } - pub fn parse_exprs(&mut self) -> Result, LispError> { + pub fn parse_exprs(&mut self) -> Result, ParseError> { let mut res = Vec::new(); loop { match self.peek()? { @@ -203,7 +209,7 @@ fn name_expr(input: &str) -> LispExpr { #[cfg(test)] mod tests { use super::*; - fn parse(input: &str) -> Result { + fn parse(input: &str) -> Result { let mut parser = Parser::new(Lexer::new(input, 0)); parser.parse_single_expr() -- cgit v1.2.3