diff --git a/dmc-lib/src/ast/ast_to_ir_util.rs b/dmc-lib/src/ast/ast_to_ir_util.rs index 855969f..8e47d05 100644 --- a/dmc-lib/src/ast/ast_to_ir_util.rs +++ b/dmc-lib/src/ast/ast_to_ir_util.rs @@ -5,6 +5,7 @@ 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::symbol::ExpressibleSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; @@ -22,12 +23,13 @@ pub fn expression_to_ir_expression( .add_statement(IrStatement::Call(ir_call)); None } else { - let t_var = IrVariable::new(&builder.new_t_var()); - let assign = IrAssign::new(t_var.clone(), IrOperation::Call(ir_call)); + let t_var = IrVariable::new(&builder.new_t_var(), call.type_info()); + let assign = IrAssign::new(t_var, IrOperation::Call(ir_call)); + let destination = assign.destination().clone(); builder .current_block_mut() .add_statement(IrStatement::Assign(assign)); - Some(IrExpression::Variable(t_var)) + Some(IrExpression::Variable(destination)) } } Expression::IntegerLiteral(integer_literal) => { @@ -36,17 +38,19 @@ pub fn expression_to_ir_expression( Expression::String(string_literal) => { Some(IrExpression::String(string_literal.content().into())) } - Expression::Identifier(identifier) => Some(IrExpression::Variable(IrVariable::new( - identifier.name().into(), - ))), + Expression::Identifier(identifier) => { + let expressible_symbol = identifier.expressible_symbol(); + Some(IrExpression::Variable(expressible_symbol.ir_variable())) + } Expression::Additive(additive_expression) => { let ir_add = additive_expression.to_ir(builder, symbol_table); - let t_var = IrVariable::new(&builder.new_t_var()); - let assign = IrAssign::new(t_var.clone(), IrOperation::Add(ir_add)); + let t_var = IrVariable::new(&builder.new_t_var(), additive_expression.type_info()); + let assign = IrAssign::new(t_var, IrOperation::Add(ir_add)); + let destination = assign.destination().clone(); builder .current_block_mut() .add_statement(IrStatement::Assign(assign)); - Some(IrExpression::Variable(t_var)) + Some(IrExpression::Variable(destination)) } } } diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index eed1004..4163a84 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -7,6 +7,7 @@ use crate::ast::type_use::TypeUse; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; use crate::ir::ir_function::IrFunction; +use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; use crate::symbol::FunctionSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; @@ -162,6 +163,19 @@ impl Function { pub fn to_ir(&self, symbol_table: &SymbolTable) -> IrFunction { let mut builder = IrBuilder::new(); + + // parameters + for parameter in &self.parameters { + let parameter_symbol = parameter.parameter_symbol(); + let ir_variable = IrVariable::new( + parameter_symbol.borrow().name(), + parameter_symbol.borrow().type_info().clone(), + ); + let as_rc = Rc::new(RefCell::new(ir_variable)); + builder.parameters_mut().push(as_rc.clone()); + parameter_symbol.borrow_mut().set_ir_variable(as_rc); + } + let entry_block_id = builder.new_block(); for (i, statement) in self.statements.iter().enumerate() { let is_last = i == self.statements.len() - 1; @@ -169,8 +183,18 @@ impl Function { } builder.finish_block(); - let entry_block = builder.get_block(entry_block_id); - IrFunction::new(Rc::from(self.declared_name()), entry_block.clone()) + let return_type_info = self + .return_type + .as_ref() + .map(|return_type| return_type.to_type_info()) + .unwrap_or(TypeInfo::Void); + let entry_block = builder.get_block(entry_block_id).clone(); + IrFunction::new( + Rc::from(self.declared_name()), + builder.parameters(), + return_type_info, + entry_block, + ) } pub fn assemble( diff --git a/dmc-lib/src/ast/ir_builder.rs b/dmc-lib/src/ast/ir_builder.rs index 101dd0a..c1f0d82 100644 --- a/dmc-lib/src/ast/ir_builder.rs +++ b/dmc-lib/src/ast/ir_builder.rs @@ -1,10 +1,12 @@ use crate::ir::ir_block::IrBlock; use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; pub struct IrBuilder { + parameters: Vec>>, block_counter: usize, t_var_counter: usize, blocks: HashMap>>, @@ -14,6 +16,7 @@ pub struct IrBuilder { impl IrBuilder { pub fn new() -> Self { Self { + parameters: vec![], block_counter: 0, t_var_counter: 0, blocks: HashMap::new(), @@ -21,6 +24,14 @@ impl IrBuilder { } } + pub fn parameters(&self) -> &[Rc>] { + &self.parameters + } + + pub fn parameters_mut(&mut self) -> &mut Vec>> { + &mut self.parameters + } + pub fn new_block(&mut self) -> usize { let block_id = self.block_counter; self.block_counter += 1; diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index 8a5fb2f..8e39974 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -4,9 +4,7 @@ use crate::ast::expression::Expression; use crate::ast::ir_builder::IrBuilder; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; -use crate::ir::ir_add::IrAdd; use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_call::IrCall; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_operation::IrOperation; use crate::ir::ir_statement::IrStatement; @@ -14,7 +12,6 @@ use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; use crate::symbol::{ExpressibleSymbol, VariableSymbol}; use crate::symbol_table::{SymbolInsertError, SymbolTable}; -use std::process::id; pub struct LetStatement { declared_name: String, @@ -99,22 +96,28 @@ impl LetStatement { Expression::String(string_literal) => { IrOperation::Load(IrExpression::String(string_literal.content().into())) } - Expression::Identifier(identifier) => { - IrOperation::Load(IrExpression::Variable(IrVariable::new(identifier.name()))) - } + Expression::Identifier(identifier) => IrOperation::Load(IrExpression::Variable( + identifier.expressible_symbol().ir_variable(), + )), Expression::Additive(additive_expression) => { IrOperation::Add(additive_expression.to_ir(builder, symbol_table)) } }; - let destination_variable = IrVariable::new(self.declared_name()); + let destination_symbol = + symbol_table.get_variable_symbol(self.scope_id.unwrap(), &self.declared_name); + let ir_assign = IrAssign::new( + IrVariable::new(self.declared_name(), self.initializer().type_info()), + init_operation, + ); + let destination_ir_variable = ir_assign.destination(); + destination_symbol + .borrow_mut() + .set_ir_variable(destination_ir_variable.clone()); builder .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - destination_variable, - init_operation, - ))) + .add_statement(IrStatement::Assign(ir_assign)); } pub fn assemble( diff --git a/dmc-lib/src/ast/parameter.rs b/dmc-lib/src/ast/parameter.rs index aec3230..144d845 100644 --- a/dmc-lib/src/ast/parameter.rs +++ b/dmc-lib/src/ast/parameter.rs @@ -11,6 +11,7 @@ pub struct Parameter { declared_name: String, declared_name_source_range: SourceRange, type_use: TypeUse, + parameter_symbol: Option>>, } impl Parameter { @@ -23,6 +24,7 @@ impl Parameter { declared_name: declared_name.into(), declared_name_source_range, type_use, + parameter_symbol: None, } } @@ -35,7 +37,10 @@ impl Parameter { TypeInfo::from_declared_name(self.type_use.declared_name()), )); match insert_result { - Ok(parameter_symbol) => Ok(parameter_symbol), + Ok(parameter_symbol) => { + self.parameter_symbol = Some(parameter_symbol.clone()); + Ok(parameter_symbol) + } Err(symbol_insert_error) => match symbol_insert_error { SymbolInsertError::AlreadyDeclared(already_declared) => Err(vec![Diagnostic::new( &format!("Parameter {} already declared.", already_declared.name()), @@ -46,11 +51,20 @@ impl Parameter { } } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn check_name_usages( + &mut self, + _symbol_table: &SymbolTable, + ) -> Result<(), Vec> { Ok(()) // no-op for now } - pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn type_check(&mut self, _symbol_table: &SymbolTable) -> Result<(), Vec> { Ok(()) // no-op for now } + + pub fn parameter_symbol(&self) -> &Rc> { + self.parameter_symbol + .as_ref() + .expect("parameter symbol not initialized") + } } diff --git a/dmc-lib/src/ir/ir_assign.rs b/dmc-lib/src/ir/ir_assign.rs index d8f6bd4..47124ab 100644 --- a/dmc-lib/src/ir/ir_assign.rs +++ b/dmc-lib/src/ir/ir_assign.rs @@ -1,23 +1,35 @@ use crate::ir::ir_operation::IrOperation; use crate::ir::ir_variable::IrVariable; +use std::cell::RefCell; use std::fmt::{Display, Formatter}; +use std::rc::Rc; pub struct IrAssign { - destination: Box, + destination: Rc>, initializer: Box, } impl IrAssign { pub fn new(destination: IrVariable, initializer: IrOperation) -> Self { Self { - destination: destination.into(), + destination: Rc::new(RefCell::new(destination)), initializer: initializer.into(), } } + + pub fn destination(&self) -> &Rc> { + &self.destination + } } impl Display for IrAssign { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{} = {}", self.destination, self.initializer) + write!( + f, + "{}: {} = {}", + self.destination.borrow(), + self.destination.borrow().type_info(), + self.initializer + ) } } diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs index 9e0b0ad..819a121 100644 --- a/dmc-lib/src/ir/ir_expression.rs +++ b/dmc-lib/src/ir/ir_expression.rs @@ -1,9 +1,10 @@ use crate::ir::ir_variable::IrVariable; +use std::cell::RefCell; use std::fmt::{Display, Formatter}; use std::rc::Rc; pub enum IrExpression { - Variable(IrVariable), + Variable(Rc>), Int(i32), String(Rc), } @@ -12,7 +13,7 @@ impl Display for IrExpression { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { IrExpression::Variable(ir_variable) => { - write!(f, "{}", ir_variable) + write!(f, "{}", ir_variable.borrow()) } IrExpression::Int(i) => { write!(f, "{}", i) diff --git a/dmc-lib/src/ir/ir_function.rs b/dmc-lib/src/ir/ir_function.rs index 919a21a..3e1e70a 100644 --- a/dmc-lib/src/ir/ir_function.rs +++ b/dmc-lib/src/ir/ir_function.rs @@ -1,22 +1,48 @@ use crate::ir::ir_block::IrBlock; +use crate::ir::ir_variable::IrVariable; +use crate::type_info::TypeInfo; use std::cell::RefCell; use std::fmt::Display; use std::rc::Rc; pub struct IrFunction { name: Rc, + parameters: Vec>>, + return_type_info: TypeInfo, entry: Rc>, } impl IrFunction { - pub fn new(name: Rc, entry: Rc>) -> Self { - Self { name, entry } + pub fn new( + name: Rc, + parameters: &[Rc>], + return_type_info: TypeInfo, + entry: Rc>, + ) -> Self { + Self { + name, + parameters: parameters.to_vec(), + return_type_info, + entry, + } } } impl Display for IrFunction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "fn {}\n{}", self.name, self.entry.borrow())?; + write!(f, "fn {}(", self.name)?; + for (i, parameter) in self.parameters.iter().enumerate() { + write!( + f, + "{}: {}", + parameter.borrow(), + parameter.borrow().type_info() + )?; + if i < self.parameters.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ") -> {}\n{}", self.return_type_info, self.entry.borrow())?; Ok(()) } } diff --git a/dmc-lib/src/ir/ir_variable.rs b/dmc-lib/src/ir/ir_variable.rs index 5180c21..7350d3f 100644 --- a/dmc-lib/src/ir/ir_variable.rs +++ b/dmc-lib/src/ir/ir_variable.rs @@ -1,14 +1,22 @@ +use crate::type_info::TypeInfo; use std::fmt::{Display, Formatter}; use std::rc::Rc; -#[derive(Clone)] pub struct IrVariable { name: Rc, + type_info: TypeInfo, } impl IrVariable { - pub fn new(name: &str) -> Self { - Self { name: name.into() } + pub fn new(name: &str, type_info: TypeInfo) -> Self { + Self { + name: name.into(), + type_info, + } + } + + pub fn type_info(&self) -> &TypeInfo { + &self.type_info } } diff --git a/dmc-lib/src/symbol.rs b/dmc-lib/src/symbol.rs index 5f87e31..aa1b9b7 100644 --- a/dmc-lib/src/symbol.rs +++ b/dmc-lib/src/symbol.rs @@ -1,3 +1,4 @@ +use crate::ir::ir_variable::IrVariable; use crate::type_info::TypeInfo; use std::cell::RefCell; use std::rc::Rc; @@ -47,6 +48,9 @@ impl FunctionSymbol { pub struct ParameterSymbol { name: Rc, type_info: TypeInfo, + ir_variable: Option>>, + + #[deprecated] stack_frame_offset: Option, } @@ -55,6 +59,7 @@ impl ParameterSymbol { Self { name: name.into(), type_info, + ir_variable: None, stack_frame_offset: None, } } @@ -71,10 +76,22 @@ impl ParameterSymbol { &self.type_info } + pub fn set_ir_variable(&mut self, ir_variable: Rc>) { + self.ir_variable = Some(ir_variable); + } + + pub fn ir_variable(&self) -> &Rc> { + self.ir_variable + .as_ref() + .expect("ir_variable not yet initialized") + } + + #[deprecated] pub fn set_stack_frame_offset(&mut self, offset: isize) { self.stack_frame_offset = Some(offset); } + #[deprecated] pub fn stack_frame_offset(&self) -> isize { self.stack_frame_offset.unwrap() } @@ -83,6 +100,9 @@ impl ParameterSymbol { pub struct VariableSymbol { name: Rc, type_info: Option, + ir_variable: Option>>, + + #[deprecated] register: Option, } @@ -91,6 +111,7 @@ impl VariableSymbol { Self { name: name.into(), type_info: None, + ir_variable: None, register: None, } } @@ -113,6 +134,16 @@ impl VariableSymbol { .expect("TypeInfo not initialized. Did you type check?") } + pub fn set_ir_variable(&mut self, ir_variable: Rc>) { + self.ir_variable = Some(ir_variable); + } + + pub fn ir_variable(&self) -> &Rc> { + self.ir_variable + .as_ref() + .expect("ir_variable not yet initialized") + } + pub fn set_register(&mut self, register: usize) { self.register = Some(register); } @@ -127,3 +158,19 @@ pub enum ExpressibleSymbol { Parameter(Rc>), Variable(Rc>), } + +impl ExpressibleSymbol { + pub fn ir_variable(&self) -> Rc> { + match self { + ExpressibleSymbol::Function(_) => { + panic!("Cannot get ir_variable for FunctionSymbol"); + } + ExpressibleSymbol::Parameter(parameter_symbol) => { + parameter_symbol.borrow().ir_variable().clone() + } + ExpressibleSymbol::Variable(variable_symbol) => { + variable_symbol.borrow().ir_variable().clone() + } + } + } +}