Add more error handling

This commit is contained in:
Sofia 2023-08-02 20:17:06 +03:00
parent 9b7a31c988
commit 91a6485d5a
4 changed files with 45 additions and 44 deletions

View File

@ -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")?)?,
})
}
}

View File

@ -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<IRValue, Error> {
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),
}

View File

@ -54,27 +54,9 @@ impl Token {
}
}
impl Into<String> for Token {
fn into(self) -> String {
format!("{:?}", self)
}
}
pub struct TokenList(pub Vec<Token>);
impl Into<String> for TokenList {
fn into(self) -> String {
self.0
.iter()
.map(|tok| tok.clone().into())
.collect::<Vec<String>>()
.join(" or ")
}
}
impl Into<TokenList> for &[Token] {
fn into(self) -> TokenList {
TokenList(self.to_owned())
impl From<Token> for String {
fn from(value: Token) -> Self {
format!("{:?}", value)
}
}

View File

@ -142,7 +142,7 @@ impl<'a> IRBlock<'a> {
}
}
pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result<IRValue, ()> {
pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result<IRValue, Error> {
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),
}