Added some error checking to the inverter.

This commit is contained in:
PaddiM8 2020-06-13 22:18:37 +02:00
parent 7a4fefe1d0
commit 6e81ea5ae1
2 changed files with 29 additions and 16 deletions

View File

@ -1,9 +1,10 @@
use crate::ast::{Expr, Stmt}; use crate::ast::{Expr, Stmt};
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::parser::CalcError;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
impl Expr { impl Expr {
pub fn invert(&self, symbol_table: &mut SymbolTable) -> Self { pub fn invert(&self, symbol_table: &mut SymbolTable) -> Result<Self, CalcError> {
match self { match self {
Expr::Binary(left, op, right) => invert_binary(symbol_table, &left, op, &right), Expr::Binary(left, op, right) => invert_binary(symbol_table, &left, op, &right),
Expr::Unary(op, expr) => invert_unary(op, &expr), Expr::Unary(op, expr) => invert_unary(op, &expr),
@ -23,7 +24,7 @@ fn invert_binary(
left: &Expr, left: &Expr,
op: &TokenKind, op: &TokenKind,
right: &Expr, right: &Expr,
) -> Expr { ) -> Result<Expr, CalcError> {
let op_inv = match op { let op_inv = match op {
TokenKind::Plus => TokenKind::Minus, TokenKind::Plus => TokenKind::Minus,
TokenKind::Minus => TokenKind::Plus, TokenKind::Minus => TokenKind::Plus,
@ -32,38 +33,50 @@ fn invert_binary(
_ => unreachable!(), _ => unreachable!(),
}; };
Expr::Binary( Ok(Expr::Binary(
Box::new(right.invert(symbol_table)), Box::new(right.invert(symbol_table)?),
op_inv, op_inv,
Box::new(left.invert(symbol_table)), Box::new(left.invert(symbol_table)?),
) ))
} }
fn invert_unary(op: &TokenKind, expr: &Expr) -> Expr { fn invert_unary(op: &TokenKind, expr: &Expr) -> Result<Expr, CalcError> {
match op { Ok(match op {
TokenKind::Minus => expr.clone(), TokenKind::Minus => expr.clone(),
TokenKind::Exclamation => unimplemented!(), TokenKind::Exclamation => unimplemented!(),
_ => unreachable!(), _ => unreachable!(),
} })
} }
// Not necessary yet // Not necessary yet
fn invert_unit(_identifier: &str, _expr: &Expr) -> Expr { fn invert_unit(_identifier: &str, _expr: &Expr) -> Result<Expr, CalcError> {
unimplemented!() unimplemented!()
} }
fn invert_group(expr: &Expr) -> Expr { fn invert_group(expr: &Expr) -> Result<Expr, CalcError> {
invert_value(expr) invert_value(expr)
} }
fn invert_fn_call(symbol_table: &mut SymbolTable, identifier: &str, arguments: &Vec<Expr>) -> Expr { fn invert_fn_call(
symbol_table: &mut SymbolTable,
identifier: &str,
arguments: &Vec<Expr>,
) -> Result<Expr, CalcError> {
let (parameters, body) = let (parameters, body) =
if let Some(Stmt::FnDecl(_, parameters, body)) = symbol_table.get_fn(identifier).cloned() { if let Some(Stmt::FnDecl(_, parameters, body)) = symbol_table.get_fn(identifier).cloned() {
(parameters, body) (parameters, body)
} else { } else {
panic!(); // TODO: Error checking return Err(CalcError::UndefinedFn(identifier.into()));
}; };
if parameters.len() != arguments.len() {
return Err(CalcError::IncorrectAmountOfArguments(
parameters.len(),
identifier.into(),
arguments.len(),
));
}
let mut parameters_iter = parameters.iter(); let mut parameters_iter = parameters.iter();
for argument in arguments { for argument in arguments {
symbol_table.insert(Stmt::VarDecl( symbol_table.insert(Stmt::VarDecl(
@ -75,6 +88,6 @@ fn invert_fn_call(symbol_table: &mut SymbolTable, identifier: &str, arguments: &
body.invert(symbol_table) body.invert(symbol_table)
} }
fn invert_value(expr: &Expr) -> Expr { fn invert_value(expr: &Expr) -> Result<Expr, CalcError> {
Expr::Unary(TokenKind::Minus, Box::new(expr.clone())) Ok(Expr::Unary(TokenKind::Minus, Box::new(expr.clone())))
} }

View File

@ -187,7 +187,7 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
let stmt_inv = Stmt::UnitDecl( let stmt_inv = Stmt::UnitDecl(
base_unit.clone(), base_unit.clone(),
identifier.value.clone(), identifier.value.clone(),
Box::new(def.invert(&mut context.symbol_table)), Box::new(def.invert(&mut context.symbol_table)?),
); );
let stmt = Stmt::UnitDecl(identifier.value, base_unit, Box::new(def)); let stmt = Stmt::UnitDecl(identifier.value, base_unit, Box::new(def));