165 lines
7.0 KiB
Rust
165 lines
7.0 KiB
Rust
use crate::ast::add_expression::AddExpression;
|
|
use crate::ast::call::Call;
|
|
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),
|
|
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::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::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::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::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::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::String(string_literal) => {
|
|
Some(IrExpression::String(string_literal.content().into()))
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
let expressible_symbol = identifier.expressible_symbol();
|
|
Some(expressible_symbol.ir_expression())
|
|
}
|
|
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(_) => todo!(),
|
|
}
|
|
}
|
|
}
|