2020-06-13 20:06:21 +02:00
|
|
|
use crate::ast::{Expr, Stmt};
|
2020-06-13 19:01:33 +02:00
|
|
|
use crate::lexer::TokenKind;
|
2020-06-13 20:06:21 +02:00
|
|
|
use crate::symbol_table::SymbolTable;
|
2020-06-13 19:01:33 +02:00
|
|
|
|
|
|
|
impl Expr {
|
2020-06-13 20:06:21 +02:00
|
|
|
pub fn invert(&self, symbol_table: &mut SymbolTable) -> Self {
|
2020-06-13 19:01:33 +02:00
|
|
|
match self {
|
2020-06-13 20:06:21 +02:00
|
|
|
Expr::Binary(left, op, right) => invert_binary(symbol_table, &left, op, &right),
|
2020-06-13 19:01:33 +02:00
|
|
|
Expr::Unary(op, expr) => invert_unary(op, &expr),
|
|
|
|
Expr::Unit(identifier, expr) => invert_unit(&identifier, &expr),
|
2020-06-13 20:06:21 +02:00
|
|
|
Expr::Var(_) => invert_value(self),
|
2020-06-13 19:01:33 +02:00
|
|
|
Expr::Group(expr) => invert_group(&expr),
|
2020-06-13 20:06:21 +02:00
|
|
|
Expr::FnCall(identifier, arguments) => {
|
|
|
|
invert_fn_call(symbol_table, &identifier, arguments)
|
|
|
|
}
|
|
|
|
Expr::Literal(_) => invert_value(self),
|
2020-06-13 19:01:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-13 20:06:21 +02:00
|
|
|
fn invert_binary(
|
|
|
|
symbol_table: &mut SymbolTable,
|
|
|
|
left: &Expr,
|
|
|
|
op: &TokenKind,
|
|
|
|
right: &Expr,
|
|
|
|
) -> Expr {
|
2020-06-13 19:01:33 +02:00
|
|
|
let op_inv = match op {
|
|
|
|
TokenKind::Plus => TokenKind::Minus,
|
|
|
|
TokenKind::Minus => TokenKind::Plus,
|
|
|
|
TokenKind::Star => TokenKind::Slash,
|
|
|
|
TokenKind::Slash => TokenKind::Star,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
|
2020-06-13 20:06:21 +02:00
|
|
|
Expr::Binary(
|
|
|
|
Box::new(right.invert(symbol_table)),
|
|
|
|
op_inv,
|
|
|
|
Box::new(left.invert(symbol_table)),
|
|
|
|
)
|
2020-06-13 19:01:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn invert_unary(op: &TokenKind, expr: &Expr) -> Expr {
|
|
|
|
match op {
|
|
|
|
TokenKind::Minus => expr.clone(),
|
|
|
|
TokenKind::Exclamation => unimplemented!(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-13 20:06:21 +02:00
|
|
|
// Not necessary yet
|
|
|
|
fn invert_unit(_identifier: &str, _expr: &Expr) -> Expr {
|
2020-06-13 19:01:33 +02:00
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn invert_group(expr: &Expr) -> Expr {
|
|
|
|
invert_value(expr)
|
|
|
|
}
|
|
|
|
|
2020-06-13 20:06:21 +02:00
|
|
|
fn invert_fn_call(symbol_table: &mut SymbolTable, identifier: &str, arguments: &Vec<Expr>) -> Expr {
|
|
|
|
let (parameters, body) =
|
|
|
|
if let Some(Stmt::FnDecl(_, parameters, body)) = symbol_table.get_fn(identifier).cloned() {
|
|
|
|
(parameters, body)
|
|
|
|
} else {
|
|
|
|
panic!(); // TODO: Error checking
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut parameters_iter = parameters.iter();
|
|
|
|
for argument in arguments {
|
|
|
|
symbol_table.insert(Stmt::VarDecl(
|
|
|
|
parameters_iter.next().unwrap().to_string(),
|
|
|
|
Box::new(argument.clone()),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
body.invert(symbol_table)
|
2020-06-13 19:01:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn invert_value(expr: &Expr) -> Expr {
|
|
|
|
Expr::Unary(TokenKind::Minus, Box::new(expr.clone()))
|
|
|
|
}
|