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, } 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> { self.expression.gather_declared_names(symbol_table) } pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { self.expression.check_name_usages(symbol_table) } pub fn type_check( &mut self, symbol_table: &SymbolTable, must_return_type_info: Option<&TypeInfo>, ) -> Result<(), Vec> { 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))); } } }