From 91a6485d5a03159bab968a421b3027bea6fa9582 Mon Sep 17 00:00:00 2001 From: sofia Date: Wed, 2 Aug 2023 20:17:06 +0300 Subject: [PATCH] Add more error handling --- src/ast.rs | 8 +++----- src/codegen.rs | 47 +++++++++++++++++++++++++++++++---------------- src/lexer.rs | 24 +++--------------------- src/llvm_ir.rs | 10 ++++++++-- 4 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 64e6afb..3f52952 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,5 +1,5 @@ use crate::{ - lexer::{Token, TokenList}, + lexer::Token, token_stream::{Error, TokenStream}, }; @@ -92,7 +92,7 @@ fn parse_binop_rhs( lhs = match &token { Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)), Token::Times => Expression::Binop(Mult, Box::new(lhs), Box::new(rhs)), - _ => Err(stream.expected_err(TokenList(vec![Token::Plus, Token::Times]))?)?, // TODO: Add error raporting! + _ => Err(stream.expected_err("+ or *")?)?, }; } } @@ -266,9 +266,7 @@ impl Parse for TopLevelStatement { Ok(match stream.peek() { Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?), Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?), - _ => { - Err(stream.expected_err(TokenList(vec![Token::ImportKeyword, Token::FnKeyword]))?)? - } + _ => Err(stream.expected_err("import or fn")?)?, }) } } diff --git a/src/codegen.rs b/src/codegen.rs index a6412c7..3b20b5d 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -2,7 +2,7 @@ use std::collections::{hash_map, HashMap}; use crate::{ ast::{BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, TopLevelStatement}, - llvm_ir::{IRBlock, IRModule, IRValue, IRValueType}, + llvm_ir::{self, IRBlock, IRModule, IRValue, IRValueType}, }; pub struct Scope<'a> { @@ -22,18 +22,18 @@ impl<'a> Scope<'a> { self.named_vars.get(name) } - pub fn set(&mut self, name: &str, val: IRValue) -> Result<(), ()> { + pub fn set(&mut self, name: &str, val: IRValue) -> Result<(), Error> { if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) { e.insert(val); Ok(()) } else { - Err(()) // TODO! Error Handling! + Err(Error::VariableAlreadyDefined(name.to_owned())) } } } impl TopLevelStatement { - pub fn codegen(&self, module: &mut IRModule) { + pub fn codegen(&self, module: &mut IRModule) -> Result<(), Error> { match self { TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { let func = module.create_func(&sig.name, IRValueType::I32); @@ -44,7 +44,7 @@ impl TopLevelStatement { } let value = if let Some(exp) = &block.1 { - exp.codegen(&mut scope) + exp.codegen(&mut scope)? } else { panic!("Void-return type function not yet implemented!"); }; @@ -52,39 +52,54 @@ impl TopLevelStatement { } TopLevelStatement::Import(_) => {} } + Ok(()) } } impl BlockLevelStatement { - pub fn codegen(&self, scope: &mut Scope) { + pub fn codegen(&self, scope: &mut Scope) -> Result<(), Error> { match self { BlockLevelStatement::Let(let_statement) => { - let val = let_statement.1.codegen(scope); - scope.set(&let_statement.0, val).unwrap(); + let val = let_statement.1.codegen(scope)?; + scope.set(&let_statement.0, val)?; + Ok(()) } BlockLevelStatement::Return(_) => panic!("Should never exist!"), - BlockLevelStatement::Import(_) => {} - BlockLevelStatement::Expression(_) => {} + BlockLevelStatement::Import(_) => Ok(()), + BlockLevelStatement::Expression(_) => Ok(()), } } } impl Expression { - pub fn codegen(&self, scope: &mut Scope) -> IRValue { + pub fn codegen(&self, scope: &mut Scope) -> Result { use Expression::*; match self { Binop(op, lhs, rhs) => match op { BinaryOperator::Add => { - let lhs = lhs.codegen(scope); - let rhs = rhs.codegen(scope); - scope.block.add(lhs, rhs).unwrap() + let lhs = lhs.codegen(scope)?; + let rhs = rhs.codegen(scope)?; + Ok(scope.block.add(lhs, rhs)?) } BinaryOperator::Mult => panic!("Not implemented!"), }, BlockExpr(_) => panic!("Not implemented!"), FunctionCall(_) => panic!("Not implemented!"), - VariableName(name) => scope.get(name).cloned().unwrap(), - Literal(lit) => scope.block.get_const(lit), + VariableName(name) => Ok(scope + .get(name) + .cloned() + .unwrap_or(Err(Error::UndefinedVariable(name.clone()))?)), + Literal(lit) => Ok(scope.block.get_const(lit)), } } } + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Variable already defined {0}")] + VariableAlreadyDefined(String), + #[error("Variable not yet defined {0}")] + UndefinedVariable(String), + #[error(transparent)] + Deeper(#[from] llvm_ir::Error), +} diff --git a/src/lexer.rs b/src/lexer.rs index c180c8c..cd53fef 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -54,27 +54,9 @@ impl Token { } } -impl Into for Token { - fn into(self) -> String { - format!("{:?}", self) - } -} - -pub struct TokenList(pub Vec); - -impl Into for TokenList { - fn into(self) -> String { - self.0 - .iter() - .map(|tok| tok.clone().into()) - .collect::>() - .join(" or ") - } -} - -impl Into for &[Token] { - fn into(self) -> TokenList { - TokenList(self.to_owned()) +impl From for String { + fn from(value: Token) -> Self { + format!("{:?}", value) } } diff --git a/src/llvm_ir.rs b/src/llvm_ir.rs index 218be82..47151b3 100644 --- a/src/llvm_ir.rs +++ b/src/llvm_ir.rs @@ -142,7 +142,7 @@ impl<'a> IRBlock<'a> { } } - pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result { + pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result { unsafe { if lhs.0 == rhs.0 { Ok(IRValue( @@ -150,8 +150,14 @@ impl<'a> IRBlock<'a> { LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), )) } else { - Err(()) + Err(Error::TypeMismatch(lhs.0, rhs.0)) } } } } + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Type Mismatch: {0:?} {1:?}")] + TypeMismatch(IRValueType, IRValueType), +}