deimos-lang/dmc-lib/src/ast/expression_statement.rs
2026-03-12 15:39:13 -05:00

73 lines
2.2 KiB
Rust

use crate::ast::expression::Expression;
use crate::ast::ir_builder::IrBuilder;
use crate::diagnostic::Diagnostic;
use crate::ir::ir_return::IrReturn;
use crate::ir::ir_statement::IrStatement;
use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo;
pub struct ExpressionStatement {
expression: Box<Expression>,
}
impl ExpressionStatement {
pub fn new(expression: Expression) -> Self {
Self {
expression: expression.into(),
}
}
pub fn expression(&self) -> &Expression {
&self.expression
}
pub fn gather_declared_names(
&mut self,
symbol_table: &mut SymbolTable,
) -> Result<(), Vec<Diagnostic>> {
self.expression.gather_declared_names(symbol_table)
}
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
self.expression.check_name_usages(symbol_table)
}
pub fn type_check(
&mut self,
symbol_table: &SymbolTable,
must_return_type_info: Option<&TypeInfo>,
) -> Result<(), Vec<Diagnostic>> {
self.expression.type_check(symbol_table)?;
if must_return_type_info.is_some() {
let expression_type = self.expression.type_info();
let return_type = must_return_type_info.unwrap();
if !return_type.is_assignable_from(expression_type) {
return Err(vec![Diagnostic::new(
&format!(
"Incompatible type on return expression: expected {} but found {}",
return_type, expression_type
),
self.expression.source_range().start(),
self.expression.source_range().end(),
)]);
}
}
Ok(())
}
pub fn to_ir(
&self,
builder: &mut IrBuilder,
symbol_table: &SymbolTable,
should_return_value: bool,
) {
let ir_expression = self.expression.to_ir(builder, symbol_table);
if ir_expression.is_some() && should_return_value {
builder
.current_block_mut()
.add_statement(IrStatement::Return(IrReturn::new(ir_expression)));
}
}
}