deimos-lang/dmc-lib/src/ast/expression.rs

177 lines
7.6 KiB
Rust

use crate::ast::add_expression::AddExpression;
use crate::ast::call::Call;
use crate::ast::double_literal::DoubleLiteral;
use crate::ast::identifier::Identifier;
use crate::ast::integer_literal::IntegerLiteral;
use crate::ast::ir_builder::IrBuilder;
use crate::ast::negative_expression::NegativeExpression;
use crate::ast::string_literal::StringLiteral;
use crate::ast::subtract_expression::SubtractExpression;
use crate::diagnostic::Diagnostic;
use crate::ir::ir_assign::IrAssign;
use crate::ir::ir_expression::IrExpression;
use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_variable::IrVariable;
use crate::source_range::SourceRange;
use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo;
use std::cell::RefCell;
use std::rc::Rc;
pub enum Expression {
Add(AddExpression),
Subtract(SubtractExpression),
Negative(NegativeExpression),
Call(Call),
Identifier(Identifier),
Integer(IntegerLiteral),
Double(DoubleLiteral),
String(StringLiteral),
}
impl Expression {
pub fn gather_declared_names(
&mut self,
symbol_table: &mut SymbolTable,
) -> Result<(), Vec<Diagnostic>> {
match self {
Expression::Add(add_expression) => add_expression.gather_declared_names(symbol_table),
Expression::Subtract(subtract_expression) => {
subtract_expression.gather_declared_names(symbol_table)
}
Expression::Negative(negative_expression) => {
negative_expression.gather_declared_names(symbol_table)
}
Expression::Call(call) => call.gather_declared_names(symbol_table),
Expression::Identifier(identifier) => identifier.gather_declared_names(symbol_table),
Expression::Integer(_) => Ok(()),
Expression::Double(_) => Ok(()),
Expression::String(_) => Ok(()),
}
}
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
match self {
Expression::Add(add_expression) => add_expression.check_name_usages(symbol_table),
Expression::Subtract(subtract_expression) => {
subtract_expression.check_name_usages(symbol_table)
}
Expression::Negative(negative_expression) => {
negative_expression.check_name_usages(symbol_table)
}
Expression::Call(call) => call.check_name_usages(symbol_table),
Expression::Identifier(identifier) => identifier.check_name_usages(symbol_table),
Expression::Integer(_) => Ok(()),
Expression::Double(_) => Ok(()),
Expression::String(_) => Ok(()),
}
}
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
match self {
Expression::Add(add_expression) => add_expression.type_check(symbol_table),
Expression::Subtract(subtract_expression) => {
subtract_expression.type_check(symbol_table)
}
Expression::Negative(negative_expression) => {
negative_expression.type_check(symbol_table)
}
Expression::Call(call) => call.type_check(symbol_table),
Expression::Identifier(identifier) => identifier.type_check(symbol_table),
Expression::Integer(_) => Ok(()),
Expression::Double(_) => Ok(()),
Expression::String(_) => Ok(()),
}
}
pub fn type_info(&self) -> &TypeInfo {
match self {
Expression::Add(add_expression) => add_expression.type_info(),
Expression::Subtract(subtract_expression) => subtract_expression.type_info(),
Expression::Negative(negative_expression) => negative_expression.type_info(),
Expression::Call(call) => call.return_type_info(),
Expression::Identifier(identifier) => identifier.type_info(),
Expression::Integer(integer_literal) => integer_literal.type_info(),
Expression::Double(double_literal) => double_literal.type_info(),
Expression::String(string_literal) => string_literal.type_info(),
}
}
pub fn source_range(&self) -> &SourceRange {
match self {
Expression::Add(additive_expression) => additive_expression.source_range(),
Expression::Subtract(subtract_expression) => subtract_expression.source_range(),
Expression::Negative(negative_expression) => negative_expression.source_range(),
Expression::Call(call) => call.source_range(),
Expression::Identifier(identifier) => identifier.source_range(),
Expression::Integer(integer_literal) => integer_literal.source_range(),
Expression::Double(double_literal) => double_literal.source_range(),
Expression::String(string_literal) => string_literal.source_range(),
}
}
pub fn to_ir(
&self,
builder: &mut IrBuilder,
symbol_table: &SymbolTable,
) -> Option<IrExpression> {
match self {
Expression::Call(call) => {
let ir_call = call.to_ir(builder, symbol_table);
if matches!(call.return_type_info(), TypeInfo::Void) {
builder
.current_block_mut()
.add_statement(IrStatement::Call(ir_call));
None
} else {
let t_var = IrVariable::new_vr(
builder.new_t_var().into(),
builder.current_block().id(),
call.return_type_info(),
);
let as_rc = Rc::new(RefCell::new(t_var));
let assign = IrAssign::new(as_rc.clone(), IrOperation::Call(ir_call));
builder
.current_block_mut()
.add_statement(IrStatement::Assign(assign));
Some(IrExpression::Variable(as_rc))
}
}
Expression::Integer(integer_literal) => {
Some(IrExpression::Int(integer_literal.value()))
}
Expression::Double(double_literal) => {
Some(IrExpression::Double(double_literal.value()))
}
Expression::String(string_literal) => {
Some(IrExpression::String(string_literal.content().into()))
}
Expression::Identifier(identifier) => {
let expressible_symbol = identifier.expressible_symbol();
Some(expressible_symbol.ir_expression(builder))
}
Expression::Add(additive_expression) => {
let ir_add = additive_expression.to_ir(builder, symbol_table);
let t_var = IrVariable::new_vr(
builder.new_t_var().into(),
builder.current_block().id(),
additive_expression.type_info(),
);
let as_rc = Rc::new(RefCell::new(t_var));
let assign = IrAssign::new(as_rc.clone(), IrOperation::Add(ir_add));
builder
.current_block_mut()
.add_statement(IrStatement::Assign(assign));
Some(IrExpression::Variable(as_rc))
}
Expression::Subtract(subtract_expression) => {
Some(subtract_expression.to_ir_expression(builder, symbol_table))
}
Expression::Negative(negative_expression) => {
Some(negative_expression.to_ir(builder, symbol_table))
}
}
}
}