diff --git a/dmc-lib/src/ast/call.rs b/dmc-lib/src/ast/call.rs index b9ff254..5d3a5dd 100644 --- a/dmc-lib/src/ast/call.rs +++ b/dmc-lib/src/ast/call.rs @@ -17,6 +17,7 @@ use crate::symbol::expressible_symbol::ExpressibleSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; use crate::types_table::TypesTable; +use std::thread::Builder; pub struct Call { node_id: NodeId, @@ -304,6 +305,7 @@ impl Call { (nodes_to_types, diagnostics) } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -390,6 +392,7 @@ impl Call { } } + #[deprecated] fn get_callee_symbol(&self, symbol_table: &SymbolTable) -> CallableSymbol { match self.callee() { Expression::Identifier(identifier) => { @@ -417,6 +420,7 @@ impl Call { } } + #[deprecated] pub fn return_type_info<'a>( &self, symbol_table: &SymbolTable, @@ -435,6 +439,51 @@ impl Call { } } + pub fn lower_to_ir( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + ) -> IrCall { + let arguments = self + .arguments + .iter() + .map(|expression| { + expression.lower_to_ir_expression( + builder, + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + ) + }) + .collect::>(); + + let callee_symbol = nodes_to_symbols.get(&self.callee().node_id()).unwrap(); + let callable_symbol = match callee_symbol { + Symbol::Class(class_symbol) => match class_symbol.constructor_symbol_owned() { + None => panic!(), + Some(constructor_symbol) => CallableSymbol::Constructor(constructor_symbol), + }, + Symbol::Function(function_symbol) => CallableSymbol::Function(function_symbol.clone()), + _ => panic!(), + }; + + match callable_symbol { + CallableSymbol::Function(function_symbol) => IrCall::new( + fqn_parts_to_string(function_symbol.fqn_parts()), + arguments, + function_symbol.is_extern(), + ), + CallableSymbol::Constructor(constructor_symbol) => IrCall::new( + fqn_parts_to_string(constructor_symbol.fqn_parts()), + arguments, + constructor_symbol.is_extern(), + ), + CallableSymbol::ErrorPlaceholder => unreachable!(), + } + } + pub fn to_ir( &self, builder: &mut IrBuilder, diff --git a/dmc-lib/src/ast/compilation_unit.rs b/dmc-lib/src/ast/compilation_unit.rs index ba8c375..a5488cf 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -5,7 +5,7 @@ use crate::ast::function::Function; use crate::ast::helpers::{ collect_diagnostics_into_mut, insert_declared_types_into, insert_resolved_types_into, }; -use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes}; +use crate::ast::{FunctionReturnTypes, NodesToSymbols, NodesToTypes, SymbolsToTypes}; use crate::compile_pipeline::FileId; use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::ir::ir_class::IrClass; @@ -245,8 +245,26 @@ impl CompilationUnit { diagnostics_result!(diagnostics) } - pub fn lower(&self, resolved_types: &NodesToTypes) -> (Vec, Vec) { - todo!() + pub fn lower( + &self, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + function_return_types: &FunctionReturnTypes, + ) -> (Vec, Vec) { + let mut ir_classes = Vec::new(); + let mut ir_functions = Vec::new(); + + for function in &self.functions { + ir_functions.push(function.lower_static( + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + function_return_types, + )); + } + + (ir_classes, ir_functions) } pub fn to_ir( diff --git a/dmc-lib/src/ast/expression.rs b/dmc-lib/src/ast/expression.rs index e3fc047..ad439c2 100644 --- a/dmc-lib/src/ast/expression.rs +++ b/dmc-lib/src/ast/expression.rs @@ -321,6 +321,7 @@ impl Expression { } } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -341,6 +342,7 @@ impl Expression { } } + #[deprecated] pub fn type_info<'a>( &'a self, symbol_table: &SymbolTable, @@ -369,6 +371,54 @@ impl Expression { } } + pub fn lower_to_ir_operation( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + ) -> IrOperation { + match self { + Expression::Binary(binary_expression) => {} + Expression::Negative(negative_expression) => { + IrOperation::Load(negative_expression.lower_to_ir_expression( + builder, + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + )) + } + Expression::Call(call) => IrOperation::Call(call.lower_to_ir( + builder, + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + )), + Expression::Identifier(identifier) => IrOperation::Load( + identifier.lower_to_ir_expression(builder, nodes_to_symbols, symbols_to_types), + ), + Expression::Integer(integer_literal) => { + IrOperation::Load(IrExpression::Int(integer_literal.value())) + } + Expression::Double(double_literal) => { + IrOperation::Load(IrExpression::Double(double_literal.value())) + } + Expression::String(string_literal) => { + IrOperation::Load(IrExpression::String(string_literal.content().into())) + } + } + } + + pub fn lower_to_ir_expression( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + ) -> IrExpression { + todo!() + } + pub fn to_ir_operation( &self, builder: &mut IrBuilder, diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 7e37fe4..ee06366 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -9,7 +9,7 @@ use crate::ast::ir_builder::IrBuilder; use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::ast::type_use::TypeUse; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; +use crate::ast::{FunctionReturnTypes, NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::ir::ir_function::IrFunction; use crate::ir::ir_parameter::IrParameter; @@ -236,6 +236,7 @@ impl Function { (symbols_to_types, nodes_to_types, diagnostics) } + #[deprecated] pub fn gather_types(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) { let function_symbol = symbol_table .get_function_symbol_owned(self.scope_id.unwrap(), self.declared_name()) @@ -327,6 +328,7 @@ impl Function { ); } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -438,4 +440,59 @@ impl Function { entry_block, ) } + + pub fn lower_static( + &self, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + function_return_types: &FunctionReturnTypes, + ) -> IrFunction { + let mut builder = IrBuilder::new(); + + let function_symbol = nodes_to_symbols + .get(&self.node_id) + .unwrap() + .unwrap_function_symbol(); + + // put parameters in builder + for (i, parameter_symbol) in function_symbol.parameters().iter().enumerate() { + let parameter_type_info = symbols_to_types + .get(&Symbol::Parameter(parameter_symbol.clone())) + .unwrap(); + let stack_offset = (function_symbol.parameters().len() as isize).neg() + (i as isize); + let ir_parameter = Rc::new(IrParameter::new( + parameter_symbol.declared_name(), + parameter_type_info.clone(), + stack_offset, + )); + builder.push_parameter(parameter_symbol, ir_parameter); + } + + let entry_block_id = builder.new_block(); + + // lower statements + let return_type_info = function_return_types.get(function_symbol).unwrap(); + let should_return_value = !matches!(return_type_info, TypeInfo::Void); + for (i, statement) in self.statements.iter().enumerate() { + let is_last = i == self.statements.len() - 1; + statement.lower( + &mut builder, + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + should_return_value && is_last, + ); + } + + builder.finish_block(); + + let entry_block = builder.get_block(entry_block_id).clone(); + IrFunction::new( + fqn_parts_to_string(function_symbol.fqn_parts()), + builder.parameters().iter().map(|p| (*p).clone()).collect(), + return_type_info, + entry_block, + ) + } } diff --git a/dmc-lib/src/ast/identifier.rs b/dmc-lib/src/ast/identifier.rs index 610adea..dd661aa 100644 --- a/dmc-lib/src/ast/identifier.rs +++ b/dmc-lib/src/ast/identifier.rs @@ -521,6 +521,7 @@ impl Identifier { (resolved_types, Diagnostics::new()) } + #[deprecated] pub fn type_info<'a>( &self, symbol_table: &SymbolTable, @@ -553,6 +554,55 @@ impl Identifier { } } + pub fn lower_to_ir_expression( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + ) -> IrExpression { + let symbol = nodes_to_symbols.get(&self.node_id).unwrap(); + match &symbol.unwrap_expressible_symbol() { + ExpressibleSymbol::Class(_class_symbol) => { + todo!() + } + ExpressibleSymbol::Field(field_symbol) => { + let field_type = symbols_to_types.get(symbol).unwrap(); + let read_destination = Rc::new(RefCell::new(IrVariable::new_vr( + builder.new_t_var().into(), + builder.current_block().id(), + field_type, + ))); + let ir_read_field = IrReadField::new( + get_or_init_field_pointer_variable(builder, field_symbol, field_type).clone(), + ); + builder + .current_block_mut() + .add_statement(IrStatement::Assign(IrAssign::new( + read_destination.clone(), + IrOperation::ReadField(ir_read_field), + ))); + IrExpression::Variable(read_destination) + } + ExpressibleSymbol::Function(_function_symbol) => { + todo!() + } + ExpressibleSymbol::Parameter(parameter_symbol) => IrExpression::Parameter( + builder + .parameters_map() + .get(parameter_symbol) + .unwrap() + .clone(), + ), + ExpressibleSymbol::Variable(variable_symbol) => IrExpression::Variable( + builder + .local_variables() + .get(variable_symbol) + .unwrap() + .clone(), + ), + } + } + pub fn ir_expression( &self, builder: &mut IrBuilder, diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index 41fc426..ad267bd 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -132,7 +132,7 @@ impl LetStatement { { let (ns, mut ds) = self .initializer - .resolve_names_method(symbol_table, self_class_symbol); + .resolve_names_method(symbol_table, self_class_symbol); // todo insert_resolved_names_into(ns, &mut nodes_to_symbols); diagnostics.append(&mut ds); } @@ -216,6 +216,7 @@ impl LetStatement { (resolved_symbol_type_infos, resolved_types, diagnostics) } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -320,4 +321,35 @@ impl LetStatement { .add_statement(IrStatement::Assign(ir_assign)); as_rc } + + pub fn lower( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + ) { + let init_operation = self + .initializer + .lower_to_ir_operation(builder, nodes_to_types); + + let destination_symbol = nodes_to_symbols.get(&self.node_id).unwrap(); + let destination_type_info = symbols_to_types.get(destination_symbol).unwrap(); + let vr_variable = Rc::new(RefCell::new(IrVariable::new_vr( + self.declared_name().into(), + builder.current_block().id(), + destination_type_info, + ))); + + // save local variable to builder + builder.local_variables_mut().insert( + destination_symbol.unwrap_variable_symbol().clone(), + vr_variable.clone(), + ); + + let ir_assign = IrAssign::new(vr_variable, init_operation); + builder + .current_block_mut() + .add_statement(IrStatement::Assign(ir_assign)); + } } diff --git a/dmc-lib/src/ast/mod.rs b/dmc-lib/src/ast/mod.rs index 1642753..e02dbb7 100644 --- a/dmc-lib/src/ast/mod.rs +++ b/dmc-lib/src/ast/mod.rs @@ -1,6 +1,8 @@ use crate::symbol::Symbol; +use crate::symbol::function_symbol::FunctionSymbol; use crate::type_info::TypeInfo; use std::collections::HashMap; +use std::rc::Rc; pub mod assign_statement; pub mod binary_expression; @@ -34,3 +36,4 @@ pub type NodeId = usize; pub type NodesToSymbols = HashMap; pub type SymbolsToTypes = HashMap; pub type NodesToTypes = HashMap; +pub type FunctionReturnTypes = HashMap, TypeInfo>; diff --git a/dmc-lib/src/ast/negative_expression.rs b/dmc-lib/src/ast/negative_expression.rs index 8251bb9..35e05aa 100644 --- a/dmc-lib/src/ast/negative_expression.rs +++ b/dmc-lib/src/ast/negative_expression.rs @@ -147,6 +147,7 @@ impl NegativeExpression { (nodes_to_types, diagnostics) } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -167,6 +168,56 @@ impl NegativeExpression { } } + pub fn lower_to_ir_expression( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + ) -> IrExpression { + let base_ir_expression = self.operand.lower_to_ir_expression( + builder, + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + ); + + match base_ir_expression { + IrExpression::Parameter(ir_parameter) => { + let destination = Rc::new(RefCell::new(IrVariable::new_vr( + builder.new_t_var().into(), + builder.current_block().id(), + ir_parameter.type_info(), + ))); + + let rhs = match ir_parameter.type_info() { + TypeInfo::Integer => IrExpression::Int(-1), + TypeInfo::Double => IrExpression::Double(-1.0), + _ => panic!(), + }; + + let operation = IrOperation::Binary(IrBinaryOperation::new( + IrExpression::Parameter(ir_parameter), + rhs, + IrBinaryOperator::Multiply, + )); + + let ir_assign = IrAssign::new(destination.clone(), operation); + builder + .current_block_mut() + .add_statement(IrStatement::Assign(ir_assign)); + + IrExpression::Variable(destination) + } + IrExpression::Variable(ir_variable) => {} + IrExpression::Int(i) => {} + IrExpression::Double(d) => {} + IrExpression::String(_) => { + panic!(); + } + } + } + pub fn to_ir( &self, builder: &mut IrBuilder, diff --git a/dmc-lib/src/ast/statement.rs b/dmc-lib/src/ast/statement.rs index 51c23b2..1c3ae97 100644 --- a/dmc-lib/src/ast/statement.rs +++ b/dmc-lib/src/ast/statement.rs @@ -160,6 +160,7 @@ impl Statement { } } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -177,6 +178,7 @@ impl Statement { } } + #[deprecated] pub fn to_ir( &self, builder: &mut IrBuilder, @@ -196,4 +198,21 @@ impl Statement { } } } + + pub fn lower( + &self, + builder: &mut IrBuilder, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + is_return_statement: bool, + ) { + match self { + Statement::Let(let_statement) => { + let_statement.lower(builder, nodes_to_symbols, symbols_to_types, nodes_to_types); + } + Statement::Expression(expression_statement) => {} + Statement::Assign(assign_statement) => {} + } + } } diff --git a/dmc-lib/src/symbol/mod.rs b/dmc-lib/src/symbol/mod.rs index 6c428fe..1a63546 100644 --- a/dmc-lib/src/symbol/mod.rs +++ b/dmc-lib/src/symbol/mod.rs @@ -112,4 +112,11 @@ impl Symbol { _ => panic!(), } } + + pub fn unwrap_variable_symbol(&self) -> &Rc { + match self { + Symbol::Variable(variable_symbol) => variable_symbol, + _ => panic!(), + } + } }