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::{ use crate::{
lexer::{Token, TokenList}, lexer::Token,
token_stream::{Error, TokenStream}, token_stream::{Error, TokenStream},
}; };
@ -92,7 +92,7 @@ fn parse_binop_rhs(
lhs = match &token { lhs = match &token {
Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)), Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)),
Token::Times => Expression::Binop(Mult, 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() { Ok(match stream.peek() {
Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?), Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?),
Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?), Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?),
_ => { _ => Err(stream.expected_err("import or fn")?)?,
Err(stream.expected_err(TokenList(vec![Token::ImportKeyword, Token::FnKeyword]))?)?
}
}) })
} }
} }

View File

@ -2,7 +2,7 @@ use std::collections::{hash_map, HashMap};
use crate::{ use crate::{
ast::{BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, TopLevelStatement}, ast::{BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, TopLevelStatement},
llvm_ir::{IRBlock, IRModule, IRValue, IRValueType}, llvm_ir::{self, IRBlock, IRModule, IRValue, IRValueType},
}; };
pub struct Scope<'a> { pub struct Scope<'a> {
@ -22,18 +22,18 @@ impl<'a> Scope<'a> {
self.named_vars.get(name) 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()) { if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) {
e.insert(val); e.insert(val);
Ok(()) Ok(())
} else { } else {
Err(()) // TODO! Error Handling! Err(Error::VariableAlreadyDefined(name.to_owned()))
} }
} }
} }
impl TopLevelStatement { impl TopLevelStatement {
pub fn codegen(&self, module: &mut IRModule) { pub fn codegen(&self, module: &mut IRModule) -> Result<(), Error> {
match self { match self {
TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => {
let func = module.create_func(&sig.name, IRValueType::I32); let func = module.create_func(&sig.name, IRValueType::I32);
@ -44,7 +44,7 @@ impl TopLevelStatement {
} }
let value = if let Some(exp) = &block.1 { let value = if let Some(exp) = &block.1 {
exp.codegen(&mut scope) exp.codegen(&mut scope)?
} else { } else {
panic!("Void-return type function not yet implemented!"); panic!("Void-return type function not yet implemented!");
}; };
@ -52,39 +52,54 @@ impl TopLevelStatement {
} }
TopLevelStatement::Import(_) => {} TopLevelStatement::Import(_) => {}
} }
Ok(())
} }
} }
impl BlockLevelStatement { impl BlockLevelStatement {
pub fn codegen(&self, scope: &mut Scope) { pub fn codegen(&self, scope: &mut Scope) -> Result<(), Error> {
match self { match self {
BlockLevelStatement::Let(let_statement) => { BlockLevelStatement::Let(let_statement) => {
let val = let_statement.1.codegen(scope); let val = let_statement.1.codegen(scope)?;
scope.set(&let_statement.0, val).unwrap(); scope.set(&let_statement.0, val)?;
Ok(())
} }
BlockLevelStatement::Return(_) => panic!("Should never exist!"), BlockLevelStatement::Return(_) => panic!("Should never exist!"),
BlockLevelStatement::Import(_) => {} BlockLevelStatement::Import(_) => Ok(()),
BlockLevelStatement::Expression(_) => {} BlockLevelStatement::Expression(_) => Ok(()),
} }
} }
} }
impl Expression { impl Expression {
pub fn codegen(&self, scope: &mut Scope) -> IRValue { pub fn codegen(&self, scope: &mut Scope) -> Result<IRValue, Error> {
use Expression::*; use Expression::*;
match self { match self {
Binop(op, lhs, rhs) => match op { Binop(op, lhs, rhs) => match op {
BinaryOperator::Add => { BinaryOperator::Add => {
let lhs = lhs.codegen(scope); let lhs = lhs.codegen(scope)?;
let rhs = rhs.codegen(scope); let rhs = rhs.codegen(scope)?;
scope.block.add(lhs, rhs).unwrap() Ok(scope.block.add(lhs, rhs)?)
} }
BinaryOperator::Mult => panic!("Not implemented!"), BinaryOperator::Mult => panic!("Not implemented!"),
}, },
BlockExpr(_) => panic!("Not implemented!"), BlockExpr(_) => panic!("Not implemented!"),
FunctionCall(_) => panic!("Not implemented!"), FunctionCall(_) => panic!("Not implemented!"),
VariableName(name) => scope.get(name).cloned().unwrap(), VariableName(name) => Ok(scope
Literal(lit) => scope.block.get_const(lit), .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 { impl From<Token> for String {
fn into(self) -> String { fn from(value: Token) -> Self {
format!("{:?}", self) format!("{:?}", value)
}
}
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())
} }
} }

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 { unsafe {
if lhs.0 == rhs.0 { if lhs.0 == rhs.0 {
Ok(IRValue( Ok(IRValue(
@ -150,8 +150,14 @@ impl<'a> IRBlock<'a> {
LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")),
)) ))
} else { } else {
Err(()) Err(Error::TypeMismatch(lhs.0, rhs.0))
} }
} }
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Type Mismatch: {0:?} {1:?}")]
TypeMismatch(IRValueType, IRValueType),
}