diff --git a/dmc-lib/src/ast/assign_statement.rs b/dmc-lib/src/ast/assign_statement.rs index f5d0582..176f3eb 100644 --- a/dmc-lib/src/ast/assign_statement.rs +++ b/dmc-lib/src/ast/assign_statement.rs @@ -1,24 +1,4 @@ use crate::ast::expression::Expression; -use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into}; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::ir_util::get_or_init_mut_field_pointer_variable; -use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics, SecondaryLabel}; -use crate::diagnostic_factories::{ - destination_must_be_mutable, mismatched_assign_types, must_be_l_value, -}; -use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE}; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_set_field::IrSetField; -use crate::ir::ir_statement::IrStatement; -use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::expressible_symbol::ExpressibleSymbol; -use crate::symbol_table::SymbolTable; -use crate::types_table::TypesTable; -use std::collections::HashSet; -use std::rc::Rc; pub struct AssignStatement { destination: Box, @@ -40,513 +20,4 @@ impl AssignStatement { pub fn value(&self) -> &Expression { &self.value } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.destination.init_scopes(symbol_table, container_scope); - self.value.init_scopes(symbol_table, container_scope); - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.destination.as_ref(), self.value.as_ref()] { - let (ns, mut ds) = expression.resolve_names_static(symbol_table); - for (node_id, symbol) in ns { - names_table.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - initialized_fields: &mut HashSet>, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - { - let (ns, mut ds) = self - .value - .resolve_names_ctor(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - match self.destination.as_ref() { - Expression::Identifier(identifier) => { - let (ns, mut ds) = - identifier.resolve_name_ctor_destination(symbol_table, initialized_fields); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - _ => { - // no-op, because this is a non-L-Value and will be caught during type checking. - } - } - - (names_table, diagnostics) - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.destination.as_ref(), self.value.as_ref()] { - let (ns, mut ds) = expression.resolve_names_method(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - [ - self.destination - .check_constructor_destination_names(symbol_table, class_symbol), - self.value - .check_constructor_local_names(symbol_table, class_symbol), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - [ - self.destination - .check_method_local_names(symbol_table, class_symbol), - self.value - .check_method_local_names(symbol_table, class_symbol), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - [ - self.destination.check_static_fn_local_names(symbol_table), - self.value.check_static_fn_local_names(symbol_table), - ] - .into_iter() - .flatten() - .collect() - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_types = NodesToTypes::new(); - - { - let (nts, mut ds) = self.value.resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - { - let (nts, mut ds) = self - .destination - .resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - // check that destination is L value, mutable, and assignable - match &*self.destination { - // must be identifier (for now) - Expression::Identifier(identifier) => { - let expressible_symbol = nodes_to_symbols - .get(&identifier.node_id()) - .unwrap() - .unwrap_expressible_symbol(); - let is_mut = match &expressible_symbol { - ExpressibleSymbol::Field(field_symbol) => field_symbol.is_mut(), - ExpressibleSymbol::Variable(variable_symbol) => variable_symbol.is_mut(), - _ => false, - }; - - // check mut - if !is_mut { - diagnostics.push(destination_must_be_mutable( - self.destination.source_range(), - expressible_symbol.source_range(), - )); - } - - let maybe_expressible_symbol_source_range = - expressible_symbol.source_range().cloned(); - - let lhs_type = symbols_to_types - .get(&expressible_symbol.into_symbol()) - .unwrap(); - let rhs_type = nodes_to_types.get(&self.value.node_id()).unwrap(); - - // check assignable - if !lhs_type.is_assignable_from(rhs_type) { - diagnostics.push(mismatched_assign_types( - rhs_type, - lhs_type, - &SourceRange::new( - self.destination.source_range().start(), - self.value.source_range().end(), - ), - maybe_expressible_symbol_source_range.as_ref(), - )); - } - } - _ => { - diagnostics.push(must_be_l_value(self.destination.source_range())); - } - } - - (nodes_to_types, diagnostics) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - match self.value.type_check(symbol_table, types_table) { - Ok(_) => {} - Err(mut value_diagnostics) => { - diagnostics.append(&mut value_diagnostics); - } - } - - match self.destination.type_check(symbol_table, types_table) { - Ok(_) => {} - Err(mut destination_diagnostics) => { - diagnostics.append(&mut destination_diagnostics); - } - } - - // check destination is l value - match &*self.destination { - Expression::Identifier(identifier) => { - let expressible_symbol = symbol_table - .find_expressible_symbol(identifier.scope_id(), identifier.name()) - .unwrap(); - - let is_mut = match &expressible_symbol { - ExpressibleSymbol::Field(field_symbol) => field_symbol.is_mut(), - ExpressibleSymbol::Variable(variable_symbol) => variable_symbol.is_mut(), - _ => false, - }; - - // check mutable - if !is_mut { - let secondary_label = - if let Some(source_range) = expressible_symbol.source_range() { - Some(SecondaryLabel::new( - source_range.start(), - source_range.end(), - Some("Destination (declared here) is immutable.".to_string()), - )) - } else { - None - }; - - let mut diagnostic = Diagnostic::new( - "Destination is immutable and not re-assignable.", - self.destination.source_range().start(), - self.destination.source_range().end(), - ) - .with_primary_label_message("Attempt to mutate immutable destination.") - .with_reporter(file!(), line!()) - .with_error_code(ASSIGN_LHS_IMMUTABLE); - - if let Some(secondary_label) = secondary_label { - diagnostic = diagnostic.with_secondary_labels(&[secondary_label]); - } - - diagnostics.push(diagnostic); - } - - // check assignable - let lhs_type = match &expressible_symbol { - ExpressibleSymbol::Field(field_symbol) => { - types_table.field_types().get(field_symbol).unwrap() - } - ExpressibleSymbol::Variable(variable_symbol) => { - types_table.variable_types().get(variable_symbol).unwrap() - } - _ => panic!(), - }; - - let rhs_type = self.value.type_info(symbol_table, types_table); - if !lhs_type.is_assignable_from(rhs_type) { - let secondary_label = - if let Some(source_range) = expressible_symbol.source_range() { - Some(SecondaryLabel::new( - source_range.start(), - source_range.end(), - Some(format!( - "Destination declared here is of type {}.", - lhs_type - )), - )) - } else { - None - }; - - let mut diagnostic = Diagnostic::new( - &format!( - "Mismatched types: right-hand side {} is not assignable to left {}.", - rhs_type, lhs_type - ), - self.destination.source_range().start(), - self.value.source_range().end(), - ) - .with_primary_label_message(&format!( - "Attempt to assign {} to {}.", - rhs_type, lhs_type - )) - .with_error_code(ASSIGN_MISMATCHED_TYPES) - .with_reporter(file!(), line!()); - - if let Some(secondary_label) = secondary_label { - diagnostic = diagnostic.with_secondary_labels(&[secondary_label]); - } - - diagnostics.push(diagnostic); - } - } - _ => { - let diagnostic = Diagnostic::new( - "Left-hand side of assign must be an L value.", - self.destination.source_range().start(), - self.destination.source_range().end(), - ) - .with_primary_label_message("Must be L value.") - .with_reporter(file!(), line!()) - .with_error_code(ASSIGN_NO_L_VALUE); - diagnostics.push(diagnostic); - } - } - - if diagnostics.is_empty() { - Ok(()) - } else { - Err(diagnostics) - } - } - - #[deprecated] - pub fn to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) { - let destination_symbol = match &*self.destination { - Expression::Identifier(identifier) => symbol_table - .find_expressible_symbol(identifier.scope_id(), identifier.name()) - .unwrap(), - _ => unreachable!("Destination must be a mutable L value"), - }; - - let ir_statement = match destination_symbol { - ExpressibleSymbol::Field(field_symbol) => { - let field_type = types_table.field_types().get(&field_symbol).unwrap(); - let mut_field_pointer_variable = - get_or_init_mut_field_pointer_variable(builder, &field_symbol, field_type) - .clone(); - let ir_set_field = IrSetField::new( - todo!(), - self.value - .to_ir_expression(builder, symbol_table, types_table) - .expect("Attempt to convert non-value to value"), - ); - IrStatement::SetField(ir_set_field) - } - ExpressibleSymbol::Variable(variable_symbol) => { - let vr_variable = builder.local_variables().get(&variable_symbol).unwrap(); - let ir_assign = IrAssign::new( - todo!(), - self.value - .to_ir_operation(builder, symbol_table, types_table), - ); - IrStatement::Assign(ir_assign) - } - _ => unreachable!("Destination must be a mutable L value"), - }; - - builder.current_block_mut().add_statement(ir_statement); - } - - pub fn lower_to_ir( - &self, - builder: &mut IrBuilder, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) { - let destination_expressible_symbol = match self.destination.as_ref() { - Expression::Identifier(identifier) => nodes_to_symbols - .get(&identifier.scope_id()) - .unwrap() - .unwrap_expressible_symbol(), - _ => unreachable!("Destination must be a mutable L value"), - }; - - let ir_statement = match destination_expressible_symbol { - ExpressibleSymbol::Field(field_symbol) => { - let field_type = symbols_to_types - .get(&Symbol::Field(field_symbol.clone())) - .unwrap(); - let mut_field_pointer_variable = - get_or_init_mut_field_pointer_variable(builder, &field_symbol, field_type) - .clone(); - - let ir_set_field = IrSetField::new( - todo!(), - self.value.lower_to_ir_expression( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ), - ); - IrStatement::SetField(ir_set_field) - } - ExpressibleSymbol::Variable(variable_symbol) => { - let ir_variable = builder.local_variables().get(&variable_symbol).unwrap(); - let ir_assign = IrAssign::new( - todo!(), - self.value.lower_to_ir_operation( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ), - ); - IrStatement::Assign(ir_assign) - } - _ => unreachable!("Destination must be a mutable L value"), - }; - - builder.current_block_mut().add_statement(ir_statement); - } -} - -#[cfg(test)] -mod tests { - use crate::ast::compilation_unit::CompilationUnit; - use crate::diagnostic::Diagnostic; - use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE}; - use crate::parser::get_compilation_unit; - use crate::symbol_table::SymbolTable; - use crate::types_table::TypesTable; - - fn compile_up_to_type_check( - compilation_unit: &mut CompilationUnit, - symbol_table: &mut SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - compilation_unit.init_scopes(symbol_table); - compilation_unit.gather_symbols_into(symbol_table)?; - compilation_unit.check_names(symbol_table)?; - compilation_unit.gather_types_into(symbol_table, types_table) - } - - #[test] - fn finds_mismatched_types() -> Result<(), Vec> { - let mut compilation_unit = get_compilation_unit( - " - fn main() - let mut x = 4 - x = \"Hello\" - end - ", - None, - )?; - let mut symbol_table = SymbolTable::new(); - let mut types_table = TypesTable::new(); - compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?; - let diagnostics = compilation_unit - .type_check(&symbol_table, &mut types_table) - .unwrap_err(); - assert_eq!(diagnostics.len(), 1); - assert_eq!( - diagnostics[0].error_code().unwrap(), - ASSIGN_MISMATCHED_TYPES - ); - Ok(()) - } - - #[test] - fn finds_no_l_value() -> Result<(), Vec> { - let mut compilation_unit = get_compilation_unit( - " - fn main() - 42 = 42 - end - ", - None, - )?; - let mut symbol_table = SymbolTable::new(); - let mut types_table = TypesTable::new(); - compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?; - let diagnostics = compilation_unit - .type_check(&symbol_table, &mut types_table) - .unwrap_err(); - assert_eq!(diagnostics.len(), 1); - assert_eq!(diagnostics[0].error_code().unwrap(), ASSIGN_NO_L_VALUE); - Ok(()) - } - - #[test] - fn finds_immutable_destination() -> Result<(), Vec> { - let mut compilation_unit = get_compilation_unit( - " - fn main() - let x = 42 - x = 43 - end - ", - None, - )?; - let mut symbol_table = SymbolTable::new(); - let mut types_table = TypesTable::new(); - compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?; - let diagnostics = compilation_unit - .type_check(&symbol_table, &mut types_table) - .unwrap_err(); - assert_eq!(diagnostics.len(), 1); - assert_eq!(diagnostics[0].error_code().unwrap(), ASSIGN_LHS_IMMUTABLE); - Ok(()) - } } diff --git a/dmc-lib/src/ast/binary_expression.rs b/dmc-lib/src/ast/binary_expression.rs index df2226b..0a4e4cb 100644 --- a/dmc-lib/src/ast/binary_expression.rs +++ b/dmc-lib/src/ast/binary_expression.rs @@ -1,23 +1,6 @@ +use crate::ast::NodeId; use crate::ast::expression::Expression; -use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into}; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::error_codes::BINARY_INCOMPATIBLE_TYPES; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator}; -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::class_symbol::ClassSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostic, handle_diagnostics, maybe_return_diagnostics}; -use std::cell::RefCell; -use std::rc::Rc; pub enum BinaryOperation { Multiply, @@ -38,7 +21,6 @@ pub struct BinaryExpression { rhs: Box, op: BinaryOperation, source_range: SourceRange, - type_info: Option, } impl BinaryExpression { @@ -55,7 +37,6 @@ impl BinaryExpression { rhs: rhs.into(), op, source_range, - type_info: None, } } @@ -78,558 +59,4 @@ impl BinaryExpression { pub fn source_range(&self) -> &SourceRange { &self.source_range } - - pub fn type_info(&self) -> &TypeInfo { - self.type_info.as_ref().unwrap() - } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.lhs.init_scopes(symbol_table, container_scope); - self.rhs.init_scopes(symbol_table, container_scope); - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.lhs.as_ref(), self.rhs.as_ref()] { - let (ns, mut ds) = expression.resolve_names_static(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_field_init( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.lhs.as_ref(), self.rhs.as_ref()] { - let (ns, mut ds) = expression.resolve_names_field_init(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.lhs.as_ref(), self.rhs.as_ref()] { - let (ns, mut ds) = expression.resolve_names_ctor(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for expression in [self.lhs.as_ref(), self.rhs.as_ref()] { - let (ns, mut ds) = expression.resolve_names_method(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_field_initializer_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - [ - self.lhs - .check_field_initializer_names(symbol_table, class_symbol), - self.rhs - .check_field_initializer_names(symbol_table, class_symbol), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - [ - self.lhs - .check_constructor_local_names(symbol_table, class_symbol), - self.rhs - .check_constructor_local_names(symbol_table, class_symbol), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - [ - self.lhs - .check_method_local_names(symbol_table, class_symbol), - self.rhs - .check_method_local_names(symbol_table, class_symbol), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - [ - self.lhs.check_static_fn_local_names(symbol_table), - self.rhs.check_static_fn_local_names(symbol_table), - ] - .into_iter() - .flatten() - .collect() - } - - fn resolve_op_result( - &self, - nodes_to_types: &NodesToTypes, - op_compatibility_check: impl Fn(&TypeInfo, &TypeInfo) -> bool, - get_op_result: impl Fn(&TypeInfo, &TypeInfo) -> TypeInfo, - lazy_diagnostic_message: impl Fn(&TypeInfo, &TypeInfo) -> String, - ) -> (TypeInfo, Diagnostics) { - let lhs_type_info = nodes_to_types.get(&self.lhs.node_id()).unwrap(); - let rhs_type_info = nodes_to_types.get(&self.rhs.node_id()).unwrap(); - - if op_compatibility_check(lhs_type_info, rhs_type_info) { - let op_result = get_op_result(lhs_type_info, rhs_type_info); - (op_result, Diagnostics::new()) - } else { - let mut diagnostics = Diagnostics::new(); - diagnostics.push( - Diagnostic::new( - &lazy_diagnostic_message(lhs_type_info, rhs_type_info), - self.source_range.start(), - self.source_range.end(), - ) - .with_error_code(BINARY_INCOMPATIBLE_TYPES), - ); - (TypeInfo::PlaceholderError, diagnostics) - } - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_types = NodesToTypes::new(); - - { - let (nts, mut ds) = self.lhs.resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - { - let (nts, mut ds) = self.rhs.resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - { - let (result_type_info, mut ds) = match &self.op { - BinaryOperation::Multiply => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_multiply(rhs), - |lhs, rhs| lhs.multiply_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot multiply {} by {}", lhs, rhs), - ), - BinaryOperation::Divide => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_divide(rhs), - |lhs, rhs| lhs.divide_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot divide {} by {}", lhs, rhs), - ), - BinaryOperation::Modulo => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_modulo(rhs), - |lhs, rhs| lhs.modulo_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot modulo {} by {}", lhs, rhs), - ), - BinaryOperation::Add => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_add(rhs), - |lhs, rhs| lhs.add_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot add {} and {}", lhs, rhs), - ), - BinaryOperation::Subtract => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_subtract(rhs), - |lhs, rhs| lhs.subtract_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot subtract {} from {}", rhs, lhs), // n.b. order - ), - BinaryOperation::LeftShift => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_left_shift(rhs), - |lhs, rhs| lhs.left_shift_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot left shift {} by {}", lhs, rhs), - ), - BinaryOperation::RightShift => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_right_shift(rhs), - |lhs, rhs| lhs.right_shift_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot right shift {} by {}", lhs, rhs), - ), - BinaryOperation::BitwiseAnd => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_bitwise_and(rhs), - |lhs, rhs| lhs.bitwise_and_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot bitwise-and {} by {}", lhs, rhs), - ), - BinaryOperation::BitwiseXor => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_bitwise_xor(rhs), - |lhs, rhs| lhs.bitwise_xor_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot bitwise-xor {} by {}", lhs, rhs), - ), - BinaryOperation::BitwiseOr => self.resolve_op_result( - &nodes_to_types, - |lhs, rhs| lhs.can_bitwise_or(rhs), - |lhs, rhs| lhs.bitwise_or_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot bitwise-or {} by {}", lhs, rhs), - ), - }; - - nodes_to_types.insert(self.node_id, result_type_info); - diagnostics.append(&mut ds); - } - - (nodes_to_types, diagnostics) - } - - fn check_op( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - check: impl Fn(&TypeInfo, &TypeInfo) -> bool, - op_result: impl Fn(&TypeInfo, &TypeInfo) -> TypeInfo, - lazy_diagnostic_message: impl Fn(&TypeInfo, &TypeInfo) -> String, - ) -> Result<(), Diagnostic> { - let lhs_type_info = self.lhs.type_info(symbol_table, types_table); - let rhs_type_info = self.rhs.type_info(symbol_table, types_table); - - if check(lhs_type_info, rhs_type_info) { - self.type_info = Some(op_result(lhs_type_info, rhs_type_info)); - Ok(()) - } else { - let diagnostic = Diagnostic::new( - &lazy_diagnostic_message(lhs_type_info, rhs_type_info), - self.source_range.start(), - self.source_range.end(), - ) - .with_primary_label_message("Incompatible types for addition.") - .with_reporter(file!(), line!()) - .with_error_code(BINARY_INCOMPATIBLE_TYPES); - Err(diagnostic) - } - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - handle_diagnostics!(self.lhs.type_check(symbol_table, types_table), diagnostics); - handle_diagnostics!(self.rhs.type_check(symbol_table, types_table), diagnostics); - - maybe_return_diagnostics!(diagnostics); - - match &self.op { - BinaryOperation::Multiply => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_multiply(rhs), - |lhs, rhs| lhs.multiply_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot multiply {} by {}", - lhs, rhs - ) - ), - diagnostics - ); - } - BinaryOperation::Divide => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_divide(rhs), - |lhs, rhs| lhs.divide_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot divide {} by {}", lhs, rhs) - ), - diagnostics - ); - } - BinaryOperation::Modulo => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_modulo(rhs), - |lhs, rhs| lhs.modulo_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot modulo {} by {}", lhs, rhs) - ), - diagnostics - ); - } - BinaryOperation::Add => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_add(rhs), - |lhs, rhs| lhs.add_result(&rhs), - |lhs, rhs| format!("Incompatible types: cannot add {} to {}.", rhs, lhs) - ), - diagnostics - ); - } - BinaryOperation::Subtract => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_subtract(rhs), - |lhs, rhs| lhs.subtract_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot subtract {} from {}.", - rhs, lhs - ) - ), - diagnostics - ) - } - BinaryOperation::LeftShift => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_left_shift(rhs), - |lhs, rhs| lhs.left_shift_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot left shift {} by {}", - lhs, rhs - ) - ), - diagnostics - ); - } - BinaryOperation::RightShift => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_right_shift(rhs), - |lhs, rhs| lhs.right_shift_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot right shift {} by {}", - lhs, rhs - ) - ), - diagnostics - ); - } - BinaryOperation::BitwiseAnd => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_bitwise_and(rhs), - |lhs, rhs| lhs.bitwise_and_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot bitwise and {} by {}", - lhs, rhs - ) - ), - diagnostics - ); - } - BinaryOperation::BitwiseXor => handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_bitwise_xor(rhs), - |lhs, rhs| lhs.bitwise_xor_result(rhs), - |lhs, rhs| format!("Incompatible types: cannot bitwise xor {} by {}", lhs, rhs) - ), - diagnostics - ), - BinaryOperation::BitwiseOr => { - handle_diagnostic!( - self.check_op( - symbol_table, - types_table, - |lhs, rhs| lhs.can_bitwise_or(rhs), - |lhs, rhs| lhs.bitwise_or_result(rhs), - |lhs, rhs| format!( - "Incompatible types: cannot bitwise or {} by {}", - lhs, rhs - ) - ), - diagnostics - ); - } - } - - diagnostics_result!(diagnostics) - } - - pub fn lower_to_ir_operation( - &self, - builder: &mut IrBuilder, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> IrOperation { - let lhs = self.lhs.lower_to_ir_expression( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ); - let rhs = self.rhs.lower_to_ir_expression( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ); - - let ir_binary_operator = match &self.op { - BinaryOperation::Multiply => IrBinaryOperator::Multiply, - BinaryOperation::Divide => IrBinaryOperator::Divide, - BinaryOperation::Modulo => IrBinaryOperator::Modulo, - BinaryOperation::Add => IrBinaryOperator::Add, - BinaryOperation::Subtract => IrBinaryOperator::Subtract, - BinaryOperation::LeftShift => IrBinaryOperator::LeftShift, - BinaryOperation::RightShift => IrBinaryOperator::RightShift, - BinaryOperation::BitwiseAnd => IrBinaryOperator::BitwiseAnd, - BinaryOperation::BitwiseXor => IrBinaryOperator::BitwiseXor, - BinaryOperation::BitwiseOr => IrBinaryOperator::BitwiseOr, - }; - IrOperation::Binary(IrBinaryOperation::new(lhs, rhs, ir_binary_operator)) - } - - #[deprecated] - pub fn to_ir_operation( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrOperation { - let lhs = self - .lhs - .to_ir_expression(builder, symbol_table, types_table) - .expect("Attempt to use a non-value expression in binary expression."); - let rhs = self - .rhs - .to_ir_expression(builder, symbol_table, types_table) - .expect("Attempt to use a non-value expression in binary expression."); - let ir_binary_operation = match self.op { - BinaryOperation::Multiply => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply) - } - BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide), - BinaryOperation::Modulo => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Modulo), - BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add), - BinaryOperation::Subtract => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract) - } - BinaryOperation::LeftShift => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::LeftShift) - } - BinaryOperation::RightShift => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::RightShift) - } - BinaryOperation::BitwiseAnd => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::BitwiseAnd) - } - BinaryOperation::BitwiseXor => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::BitwiseXor) - } - BinaryOperation::BitwiseOr => { - IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::BitwiseOr) - } - }; - IrOperation::Binary(ir_binary_operation) - } - - #[deprecated] - pub fn to_ir_expression( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrExpression { - let ir_operation = self.to_ir_operation(builder, symbol_table, types_table); - let t_var = todo!(); - let as_rc = Rc::new(RefCell::new(t_var)); - let ir_assign = IrAssign::new(todo!(), ir_operation); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(ir_assign)); - IrExpression::Variable(todo!()) - } - - pub fn lower_to_ir_expression( - &self, - builder: &mut IrBuilder, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> IrExpression { - let ir_operation = - self.lower_to_ir_operation(builder, nodes_to_symbols, symbols_to_types, nodes_to_types); - - let type_info = nodes_to_types.get(&self.node_id).unwrap(); - - let t_var = Rc::new(RefCell::new(todo!())); - - let ir_assign = IrAssign::new(todo!(), ir_operation); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(ir_assign)); - IrExpression::Variable(todo!()) - } } diff --git a/dmc-lib/src/ast/call.rs b/dmc-lib/src/ast/call.rs index 557ce1a..5dbe5f6 100644 --- a/dmc-lib/src/ast/call.rs +++ b/dmc-lib/src/ast/call.rs @@ -1,22 +1,6 @@ +use crate::ast::NodeId; use crate::ast::expression::Expression; -use crate::ast::fqn_util::fqn_parts_to_string; -use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into}; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostic_factories::{ - class_has_no_constructor, mismatched_types, receiver_not_callable, wrong_number_of_arguments, -}; -use crate::ir::ir_call::IrCall; -use crate::ir::ir_expression::IrExpression; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::callable_symbol::CallableSymbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::expressible_symbol::ExpressibleSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; pub struct Call { node_id: NodeId, @@ -52,470 +36,6 @@ impl Call { &self.arguments } - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.callee.init_scopes(symbol_table, container_scope); - for argument in &mut self.arguments { - argument.init_scopes(symbol_table, container_scope); - } - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - { - let (ns, mut ds) = self.callee.resolve_names_static(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - for argument in &self.arguments { - let (ns, mut ds) = argument.resolve_names_static(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_field_init( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - { - let (ns, mut ds) = self - .callee - .resolve_names_field_init(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - for argument in &self.arguments { - let (ns, mut ds) = argument.resolve_names_field_init(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - { - let (ns, mut ds) = self - .callee - .resolve_names_ctor(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - for argument in &self.arguments { - let (ns, mut ds) = argument.resolve_names_ctor(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_symbols = NodesToSymbols::new(); - - { - let (ns, mut ds) = self - .callee - .resolve_names_method(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - for argument in &self.arguments { - let (ns, mut ds) = argument.resolve_names_method(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - (nodes_to_symbols, diagnostics) - } - - #[deprecated] - pub fn check_field_initializer_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - let mut diagnostics: Vec = Vec::new(); - diagnostics.append( - &mut self - .callee - .check_field_initializer_names(symbol_table, class_symbol), - ); - for argument in &self.arguments { - diagnostics - .append(&mut argument.check_field_initializer_names(symbol_table, class_symbol)) - } - diagnostics - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - let mut diagnostics = Vec::new(); - for argument in &self.arguments { - diagnostics - .append(&mut argument.check_constructor_local_names(symbol_table, class_symbol)) - } - diagnostics.append( - &mut self - .callee - .check_constructor_local_names(symbol_table, class_symbol), - ); - diagnostics - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - let mut diagnostics = Vec::new(); - for argument in &self.arguments { - diagnostics.append(&mut argument.check_method_local_names(symbol_table, class_symbol)); - } - diagnostics.append( - &mut self - .callee - .check_method_local_names(symbol_table, class_symbol), - ); - diagnostics - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - for argument in &self.arguments { - diagnostics.append(&mut argument.check_static_fn_local_names(symbol_table)); - } - diagnostics.append(&mut self.callee.check_static_fn_local_names(symbol_table)); - diagnostics - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_types = NodesToTypes::new(); - - { - let (nts, mut ds) = self - .callee - .resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - for argument in &self.arguments { - let (nts, mut ds) = argument.resolve_types(nodes_to_symbols, symbols_to_types); - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - // get callee symbol and check that its callable - 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 => { - diagnostics.push(class_has_no_constructor( - class_symbol.declared_name(), - self.callee.source_range(), - )); - CallableSymbol::ErrorPlaceholder - } - Some(constructor_symbol) => CallableSymbol::Constructor(constructor_symbol), - }, - Symbol::Function(function_symbol) => CallableSymbol::Function(function_symbol.clone()), - _ => { - diagnostics.push(receiver_not_callable( - symbols_to_types.get(&callee_symbol).unwrap(), - self.callee.source_range(), - )); - CallableSymbol::ErrorPlaceholder - } - }; - - let parameter_symbols = callable_symbol.parameters(); - - // check args length - if parameter_symbols.len() != self.arguments().len() { - diagnostics.push(wrong_number_of_arguments( - self.source_range(), - parameter_symbols.len(), - self.arguments().len(), - )); - } - - // check arg types - for i in 0..parameter_symbols.len() { - let parameter_symbol = parameter_symbols[i].clone(); - let argument = if i < self.arguments.len() { - &self.arguments[i] - } else { - continue; - }; - let parameter_type_info = symbols_to_types - .get(&Symbol::Parameter(parameter_symbol)) - .unwrap(); - let argument_type_info = nodes_to_types.get(&argument.node_id()).unwrap(); - if !parameter_type_info.is_assignable_from(argument_type_info) { - diagnostics.push(mismatched_types( - parameter_type_info, - argument_type_info, - argument.source_range(), - )); - } - } - - // TODO: insert self type (i.e., the return type of the call) - - (nodes_to_types, diagnostics) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - self.callee.as_mut().type_check(symbol_table, types_table)?; - - let mut diagnostics: Vec = self - .arguments - .iter_mut() - .map(|argument| argument.type_check(symbol_table, types_table)) - .filter_map(Result::err) - .flatten() - .collect(); - - // check that callee is callable - let callable_symbol = match self.callee.type_info(symbol_table, types_table) { - TypeInfo::Function(function_symbol) => { - CallableSymbol::Function(function_symbol.clone()) - } - TypeInfo::Class(class_symbol) => match class_symbol.constructor_symbol_owned() { - None => { - diagnostics.push(class_has_no_constructor( - class_symbol.declared_name(), - self.callee.source_range(), - )); - return Err(diagnostics); - } - Some(constructor_symbol) => CallableSymbol::Constructor(constructor_symbol), - }, - _ => { - diagnostics.push(Diagnostic::new( - &format!( - "Receiver of type {} is not callable.", - self.callee.type_info(symbol_table, types_table) - ), - self.callee.source_range().start(), - self.callee.source_range().end(), - )); - return Err(diagnostics); - } - }; - - // check arguments length - let parameters = callable_symbol.parameters(); - if parameters.len() != self.arguments.len() { - diagnostics.push(Diagnostic::new( - &format!( - "Wrong number of arguments; expected {} but found {}", - parameters.len(), - self.arguments.len() - ), - self.source_range.start(), - self.source_range.end(), - )); - } - - if !diagnostics.is_empty() { - return Err(diagnostics); - } - - // check argument types - for i in 0..parameters.len() { - let parameter = ¶meters[i]; - let argument = &self.arguments[i]; - let parameter_type_info = types_table.parameter_types().get(parameter).unwrap(); - let argument_type_info = argument.type_info(symbol_table, types_table); - if !parameter_type_info.is_assignable_from(argument_type_info) { - diagnostics.push(Diagnostic::new( - &format!( - "Mismatched types: expected {} but found {}", - parameter_type_info, argument_type_info - ), - argument.source_range().start(), - argument.source_range().end(), - )) - } - } - - if diagnostics.is_empty() { - Ok(()) - } else { - Err(diagnostics) - } - } - - #[deprecated] - fn get_callee_symbol(&self, symbol_table: &SymbolTable) -> CallableSymbol { - match self.callee() { - Expression::Identifier(identifier) => { - let expressible_symbol = symbol_table - .find_expressible_symbol(identifier.scope_id(), identifier.name()) - .unwrap(); - match expressible_symbol { - ExpressibleSymbol::Function(function_symbol) => { - CallableSymbol::Function(function_symbol.clone()) - } - ExpressibleSymbol::Class(class_symbol) => { - match class_symbol.constructor_symbol_owned() { - None => { - panic!("Attempt to get non-existent constructor symbol") - } - Some(constructor_symbol) => { - CallableSymbol::Constructor(constructor_symbol) - } - } - } - _ => panic!("Calling things other than functions not yet supported."), - } - } - _ => panic!("Calling things other than identifiers not yet supported."), - } - } - - #[deprecated] - pub fn return_type_info<'a>( - &self, - symbol_table: &SymbolTable, - types_table: &'a TypesTable, - ) -> &'a TypeInfo { - match self.get_callee_symbol(symbol_table) { - CallableSymbol::Function(function_symbol) => types_table - .function_return_types() - .get(&function_symbol) - .unwrap(), - CallableSymbol::Constructor(constructor_symbol) => types_table - .constructor_return_types() - .get(&constructor_symbol) - .unwrap(), - CallableSymbol::ErrorPlaceholder => unreachable!(), - } - } - - 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, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrCall { - let arguments: Vec = self - .arguments - .iter() - .map(|argument| argument.to_ir_expression(builder, symbol_table, types_table)) - .inspect(|expression| { - if expression.is_none() { - panic!("Attempt to pass non-expression") - } - }) - .map(Option::unwrap) - .collect(); - let callable_symbol = self.get_callee_symbol(symbol_table); - 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, - false, - ), - CallableSymbol::ErrorPlaceholder => unreachable!(), - } - } - pub fn source_range(&self) -> &SourceRange { &self.source_range } diff --git a/dmc-lib/src/ast/class.rs b/dmc-lib/src/ast/class.rs index 75bbd10..f364c51 100644 --- a/dmc-lib/src/ast/class.rs +++ b/dmc-lib/src/ast/class.rs @@ -1,30 +1,9 @@ -use crate::ast::assign_statement::AssignStatement; +use crate::ast::NodeId; use crate::ast::constructor::Constructor; -use crate::ast::expression::Expression; use crate::ast::field::Field; -use crate::ast::fqn_context::FqnContext; -use crate::ast::fqn_util::fqn_parts_to_string; use crate::ast::function::Function; use crate::ast::generic_parameter::GenericParameter; -use crate::ast::helpers::{ - collect_diagnostics_mut, collect_diagnostics_single, insert_resolved_names_into, - resolve_ctor_name, -}; -use crate::ast::statement::Statement; -use crate::ast::{FunctionReturnTypes, NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::error_codes::{FIELD_MULTIPLE_INIT, FIELD_UNINIT}; -use crate::ir::ir_class::{IrClass, IrField}; -use crate::ir::ir_function::IrFunction; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::constructor_symbol::ConstructorSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics, ok_or_err_diagnostics}; -use std::collections::HashSet; use std::rc::Rc; pub struct Class { @@ -35,9 +14,6 @@ pub struct Class { constructor: Option, fields: Vec, functions: Vec, - scope_id: Option, - self_class_scope_id: Option, - self_class_body_scope_id: Option, } impl Class { @@ -58,523 +34,6 @@ impl Class { constructor, fields, functions, - scope_id: None, - self_class_scope_id: None, - self_class_body_scope_id: None, } } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - - let class_scope_id = - symbol_table.push_class_scope(&format!("class_scope({})", self.declared_name)); - self.self_class_scope_id = Some(class_scope_id); - - for generic_parameter in &mut self.generic_parameters { - generic_parameter.init_scopes(symbol_table, class_scope_id); - } - - let class_body_scope_id = symbol_table - .push_class_body_scope(&format!("class_body_scope({})", self.declared_name)); - self.self_class_body_scope_id = Some(class_body_scope_id); - - for field in &mut self.fields { - field.init_scopes(symbol_table, class_body_scope_id); - } - - if let Some(constructor) = &mut self.constructor { - constructor.init_scopes(symbol_table, class_body_scope_id); - } - for function in &mut self.functions { - function.init_scopes(symbol_table, class_body_scope_id); - } - - symbol_table.pop_scope(); - symbol_table.pop_scope(); - } - - pub fn declared_symbols(&self, fqn_context: &FqnContext) -> Vec { - let mut all_symbols: Vec = Vec::new(); - - let mut generic_parameter_symbols = Vec::new(); - for generic_parameter in &self.generic_parameters { - let symbol = Rc::new(generic_parameter.make_symbol()); - all_symbols.push(Symbol::GenericParameter(symbol.clone())); - generic_parameter_symbols.push(symbol); - } - - let mut field_symbols = Vec::new(); - for (field_index, field) in self.fields.iter().enumerate() { - let symbol = Rc::new(field.make_symbol(field_index)); - all_symbols.push(Symbol::Field(symbol.clone())); - field_symbols.push(symbol); - } - - let class_body_fqn_context = fqn_context.with_part(&self.declared_name); - - let constructor_symbol = if let Some(constructor) = &self.constructor { - let (constructor_symbol, mut symbols) = - constructor.make_symbols(&class_body_fqn_context); - all_symbols.append(&mut symbols); - constructor_symbol - } else { - Rc::new(ConstructorSymbol::new( - &self.declared_name_source_range, - resolve_ctor_name(&class_body_fqn_context), - false, - true, - self.self_class_body_scope_id.unwrap(), - vec![], - )) - }; - all_symbols.push(Symbol::Constructor(constructor_symbol.clone())); - - let mut function_symbols = Vec::new(); - for function in &self.functions { - let (function_symbol, mut symbols) = - function.declared_symbols(&class_body_fqn_context, true); - all_symbols.append(&mut symbols); - function_symbols.push(function_symbol); - } - - let class_symbol = Rc::new(ClassSymbol::new( - &self.declared_name, - Some(self.declared_name_source_range.clone()), - fqn_context.resolve(&self.declared_name), // not class body! - false, - self.scope_id.unwrap(), - generic_parameter_symbols, - Some(constructor_symbol), - field_symbols, - function_symbols, - )); - all_symbols.push(Symbol::Class(class_symbol.clone())); - - all_symbols - } - - pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for generic_parameter in &self.generic_parameters { - let (ns, mut ds) = generic_parameter.resolve_names(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - let self_class_symbol = self.get_class_symbol_owned(symbol_table); - let mut initialized_fields = HashSet::new(); - - for field in &self.fields { - let (ns, mut ds) = field.resolve_names(symbol_table, &self_class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - initialized_fields.insert(field.declared_name_owned()); - } - - if let Some(constructor) = &self.constructor { - let (ns, mut ds) = constructor.resolve_names( - symbol_table, - self_class_symbol.as_ref(), - &mut initialized_fields, - ); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - - for generic_parameter in &self.generic_parameters { - diagnostics.append(&mut generic_parameter.check_names(symbol_table)); - } - - for field in &self.fields { - diagnostics.append(&mut field.check_names(symbol_table)); - } - - if let Some(constructor) = &self.constructor { - diagnostics.append(&mut constructor.check_names(symbol_table)); - } - - for function in &self.functions { - diagnostics.append(&mut function.check_names(symbol_table)); - } - - diagnostics - } - - fn get_self_class_symbol<'a>(&self, symbol_table: &'a SymbolTable) -> &'a ClassSymbol { - symbol_table - .get_class_symbol(self.scope_id.unwrap(), &self.declared_name) - .unwrap() - .as_ref() - } - - fn get_class_symbol_owned(&self, symbol_table: &SymbolTable) -> Rc { - symbol_table - .get_class_symbol(self.scope_id.unwrap(), &self.declared_name) - .cloned() - .unwrap() - } - - pub fn check_field_initializer_names(&self, symbol_table: &SymbolTable) -> Vec { - let class_symbol = self.get_class_symbol_owned(symbol_table); - self.fields - .iter() - .flat_map(|field| field.check_field_initializer_names(symbol_table, &class_symbol)) - .collect() - } - - #[deprecated] - pub fn analyze_local_names(&self, symbol_table: &mut SymbolTable) -> Vec { - let class_symbol = self.get_class_symbol_owned(symbol_table); - let mut diagnostics: Vec = Vec::new(); - if let Some(constructor) = &self.constructor { - diagnostics.append(&mut constructor.analyze_local_names(symbol_table, &class_symbol)); - } - for function in &self.functions { - diagnostics - .append(&mut function.analyze_method_local_names(symbol_table, &class_symbol)); - } - diagnostics - } - - #[deprecated] - pub fn gather_types( - &self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - // class type - let class_symbol = self.get_class_symbol_owned(symbol_table); - types_table - .class_types_mut() - .insert(class_symbol.clone(), TypeInfo::Class(class_symbol.clone())); - - // constructor return type - // this works for both declared and default constructors - let constructor_symbol = symbol_table - .get_constructor_symbol_owned(self.self_class_body_scope_id.unwrap()) - .unwrap(); - types_table - .constructor_return_types_mut() - .insert(constructor_symbol, TypeInfo::Class(class_symbol)); - - let mut diagnostics = Vec::new(); - - // generic params - for generic_parameter in &self.generic_parameters { - handle_diagnostics!( - generic_parameter.gather_types(symbol_table, types_table), - diagnostics - ); - } - - // field types - for field in &self.fields { - handle_diagnostics!(field.gather_types(symbol_table, types_table), diagnostics); - } - - // now the constructor (parameters, etc.) - if let Some(constructor) = &self.constructor { - constructor.gather_types_into(symbol_table, types_table); - } - - // function return types - for function in &self.functions { - function.gather_types(symbol_table, types_table); - } - - diagnostics_result!(diagnostics) - } - - fn type_check_generics( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - collect_diagnostics_mut(&mut self.generic_parameters, |gp| { - gp.type_check(symbol_table, types_table) - }) - } - - fn type_check_fields( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - collect_diagnostics_mut(&mut self.fields, |f| { - f.type_check(symbol_table, types_table) - }) - } - - fn type_check_constructor( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - if let Some(constructor) = &mut self.constructor { - constructor.type_check(symbol_table, types_table)?; - } - Ok(()) - } - - fn type_check_functions( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - collect_diagnostics_mut(&mut self.functions, |f| { - f.type_check(symbol_table, types_table) - }) - } - - /// Returns all field names with declared initializers. - fn field_names_with_initializers(&self) -> HashSet<&str> { - let mut set: HashSet<&str> = HashSet::new(); - for field in &self.fields { - if field.initializer().is_some() { - set.insert(field.declared_name()); - } - } - set - } - - /// If the destination of the given [AssignStatement] matches a field, returns an - /// `Ok(Some(field_name))` only if the field is not already in the `fields_already_init` set, - /// AND, if the field is immutable, the field is not initialized more than once in the - /// constructor. Otherwise, returns an `Err(Diagnostic)`. - fn check_ctor_assign_statement<'a>( - &self, - assign_statement: &'a AssignStatement, - fields_already_init: &HashSet<&&str>, - class_symbol: &ClassSymbol, - ) -> Result, Diagnostic> { - match assign_statement.destination() { - Expression::Identifier(identifier) => { - // find matching field symbol, if there is one - if let Some(field_symbol) = class_symbol.fields().get(identifier.name()) { - // check that we don't init more than once IF field is immutable - if fields_already_init.contains(&identifier.name()) && !field_symbol.is_mut() { - let diagnostic = Diagnostic::new( - &format!("Immutable field {} cannot be initialized more than once in constructor.", identifier.name()), - identifier.source_range().start(), - identifier.source_range().end(), - ).with_reporter(file!(), line!()) - .with_error_code(FIELD_MULTIPLE_INIT); - Err(diagnostic) - } else { - Ok(Some(identifier.name())) - } - } else { - Ok(None) - } - } - _ => panic!("Found a non-L Value destination"), - } - } - - /// Returns an `Ok(HashSet<&str>)` containing the names of all fields initialized in the - /// constructor, provided that the following are true: - /// - /// - The field is not initialized more than once in the constructor - /// - The field is not also initialized with a declared initializer. - /// - /// If the above are not met, returns `Err(diagnostics)`. - fn get_fields_init_in_ctor<'a>( - &self, - fields_with_declared_initializers: &HashSet<&str>, - symbol_table: &SymbolTable, - ) -> Result, Vec> { - let mut constructor_inits: HashSet<&str> = HashSet::new(); - let mut diagnostics: Vec = vec![]; - if let Some(constructor) = &self.constructor { - let class_symbol = symbol_table - .get_class_symbol(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - for statement in constructor.statements() { - match statement { - Statement::Assign(assign_statement) => { - let fields_init_so_far = constructor_inits - .union(fields_with_declared_initializers) - .collect::>(); - match self.check_ctor_assign_statement( - assign_statement, - &fields_init_so_far, - &class_symbol, - ) { - Ok(maybe_init_field) => match maybe_init_field { - None => {} - Some(init_field) => { - constructor_inits.insert(init_field); - } - }, - Err(diagnostic) => { - diagnostics.push(diagnostic); - } - } - } - _ => {} - } - } - } - ok_or_err_diagnostics!(constructor_inits, diagnostics) - } - - /// Checks that all declared fields in this `Class` are present in the `all_inits` set. If so, - /// returns `Ok`, else `Err`. - fn check_all_fields_in_init_set( - &self, - all_inits: &HashSet<&&str>, - ) -> Result<(), Vec> { - collect_diagnostics_single(&self.fields, |field| { - if all_inits.contains(&field.declared_name()) { - Ok(()) - } else { - Err(Diagnostic::new( - &format!("Field {} is not initialized.", field.declared_name()), - field.declared_name_source_range().start(), - field.declared_name_source_range().end(), - ) - .with_primary_label_message("Must be initialized in declaration or constructor.") - .with_reporter(file!(), line!()) - .with_error_code(FIELD_UNINIT)) - } - }) - } - - /// Checks that all fields are initialized, either at their declaration or in the constructor. - /// Immutable fields may be only initialized once, either at their declaration or once in the - /// constructor. Mutable fields may be initialized either at their declaration, or at least once - /// in the constructor. - fn check_field_initialization( - &self, - symbol_table: &SymbolTable, - ) -> Result<(), Vec> { - // We need to determine if fields are initialized or not (the latter is an error). - // First phase: check all fields, then check constructor, leaving pending those things that - // are fields <- initialized by constructor. Then circle back to fields and check all are - // initialized - let field_names_with_initializers = self.field_names_with_initializers(); - let field_names_init_in_constructor = - self.get_fields_init_in_ctor(&field_names_with_initializers, symbol_table)?; - let combined = field_names_with_initializers - .union(&field_names_init_in_constructor) - .collect::>(); - - // check that all fields are present in the hash set - self.check_all_fields_in_init_set(&combined)?; - - Ok(()) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - self.type_check_generics(symbol_table, types_table)?; - self.type_check_fields(symbol_table, types_table)?; - self.type_check_constructor(symbol_table, types_table)?; - self.type_check_functions(symbol_table, types_table)?; - self.check_field_initialization(symbol_table)?; - Ok(()) - } - - #[deprecated] - pub fn to_ir( - &self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> (IrClass, Vec) { - let self_class_symbol = symbol_table - .get_class_symbol(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - - let mut ir_functions: Vec = vec![]; - if let Some(constructor) = &self.constructor { - ir_functions.push(constructor.to_ir( - self_class_symbol, - &self.fields, - symbol_table, - types_table, - )) - } - - for function in &self.functions { - ir_functions.push(function.to_ir(symbol_table, types_table, Some(self_class_symbol))); - } - - let ir_class = IrClass::new( - self_class_symbol.declared_name_owned(), - fqn_parts_to_string(self_class_symbol.fqn_parts()).into(), - self.fields - .iter() - .map(|field| { - let field_symbol = symbol_table - .get_field_symbol_owned(field.scope_id(), field.declared_name()) - .unwrap(); - let field_type = types_table.field_types().get(&field_symbol).unwrap(); - IrField::new( - field.declared_name().into(), - field_symbol.field_index(), - field_type.clone(), - ) - }) - .collect(), - ); - - (ir_class, ir_functions) - } - - pub fn lower_to_ir( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> (IrClass, Vec) { - let mut ir_functions = Vec::new(); - - let self_class_symbol = nodes_to_symbols - .get(&self.node_id) - .unwrap() - .unwrap_class_symbol(); - - if let Some(constructor) = &self.constructor { - ir_functions.push(constructor.lower_to_ir( - self_class_symbol, - &self.fields, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - )); - } - - for function in &self.functions { - ir_functions.push(function.lower_to_ir_static( - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - )); - } - - let ir_class = IrClass::new( - self_class_symbol.declared_name_owned(), - fqn_parts_to_string(self_class_symbol.fqn_parts()).into(), - self.fields - .iter() - .map(|field| field.lower_to_ir_field(nodes_to_symbols, symbols_to_types)) - .collect(), - ); - - (ir_class, ir_functions) - } } diff --git a/dmc-lib/src/ast/compilation_unit.rs b/dmc-lib/src/ast/compilation_unit.rs index ebd20de..e944545 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -1,20 +1,7 @@ +use crate::FileId; use crate::ast::class::Class; use crate::ast::extern_function::ExternFunction; -use crate::ast::fqn_context::FqnContext; 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::compile_pipeline::FileId; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::ir::ir_class::IrClass; -use crate::ir::ir_function::IrFunction; -use crate::symbol::Symbol; -use crate::symbol_table::SymbolTable; -use crate::symbol_table::util::try_insert_symbols_into; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics}; pub struct CompilationUnit { file_id: Option, @@ -49,258 +36,4 @@ impl CompilationUnit { pub fn classes(&self) -> &[Class] { &self.classes } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable) { - let compilation_unit_scope = symbol_table.push_module_scope("compilation_unit_scope"); - for class in &mut self.classes { - class.init_scopes(symbol_table, compilation_unit_scope); - } - for function in &mut self.functions { - function.init_scopes(symbol_table, compilation_unit_scope); - } - for extern_function in &mut self.extern_functions { - extern_function.init_scopes(symbol_table, compilation_unit_scope); - } - symbol_table.pop_scope(); - } - - pub fn declared_symbols(&self) -> Vec { - let fqn_context = FqnContext::new(); - [ - self.classes - .iter() - .flat_map(|class| class.declared_symbols(&fqn_context)) - .collect::>(), - self.extern_functions - .iter() - .flat_map(|function| function.declared_symbols(&fqn_context).1) - .collect(), - self.functions - .iter() - .flat_map(|function| function.declared_symbols(&fqn_context, false).1) - .collect(), - ] - .into_iter() - .flatten() - .collect() - } - - #[deprecated] - pub fn gather_symbols_into( - &self, - symbol_table: &mut SymbolTable, - ) -> Result<(), Vec> { - let mut diagnostics = vec![]; - let fqn_context = FqnContext::new(); - for class in &self.classes { - handle_diagnostics!( - try_insert_symbols_into(class.declared_symbols(&fqn_context), symbol_table), - diagnostics - ); - } - for function in &self.functions { - let (_, symbols) = function.declared_symbols(&fqn_context, false); - handle_diagnostics!(try_insert_symbols_into(symbols, symbol_table), diagnostics); - } - for extern_function in &self.extern_functions { - let (_, symbols) = extern_function.declared_symbols(&fqn_context); - handle_diagnostics!(try_insert_symbols_into(symbols, symbol_table), diagnostics); - } - diagnostics_result!(diagnostics) - } - - pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for function in &self.functions { - let (ns, mut ds) = function.resolve_names_static(symbol_table); - for (node_id, symbol) in ns.into_iter() { - names_table.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - for extern_function in &self.extern_functions { - let (ns, mut ds) = extern_function.resolve_names_static(symbol_table); - for (node_id, symbol) in ns { - names_table.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - for class in &self.classes { - let (ns, mut ds) = class.resolve_names(symbol_table); - for (node_id, symbol) in ns { - names_table.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &mut SymbolTable) -> Result<(), Vec> { - let mut diagnostics = vec![]; - for class in &self.classes { - diagnostics.append(&mut class.check_names(symbol_table)); - diagnostics.append(&mut class.check_field_initializer_names(symbol_table)); - diagnostics.append(&mut class.analyze_local_names(symbol_table)); - } - for function in &self.functions { - diagnostics.append(&mut function.check_names(symbol_table)); - diagnostics.append(&mut function.analyze_static_fn_local_names(symbol_table)); - } - for extern_function in &self.extern_functions { - diagnostics.append(&mut extern_function.check_names(symbol_table)); - } - diagnostics_result!(diagnostics) - } - - /// Associate each declared symbol with a TypeInfo. - pub fn declared_types( - &self, - nodes_to_symbols: &NodesToSymbols, - ) -> (SymbolsToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut symbols_to_types = SymbolsToTypes::new(); - - for function in &self.functions { - let (sts, mut ds) = function.declared_types(nodes_to_symbols); - insert_declared_types_into(sts, &mut symbols_to_types); - diagnostics.append(&mut ds); - } - - for extern_function in &self.extern_functions { - let (sts, mut ds) = extern_function.declared_types(nodes_to_symbols); - insert_declared_types_into(sts, &mut symbols_to_types); - diagnostics.append(&mut ds); - } - - (symbols_to_types, diagnostics) - } - - /// Resolve types of all nodes that have an implicit (perhaps not declared) type, checking that - /// things are assignable, etc., along the way. - pub fn resolve_types( - &self, - names_table: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (SymbolsToTypes, NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut resolved_types = NodesToTypes::new(); - let mut symbols_to_types = symbols_to_types.clone(); - - for function in &self.functions { - let (sts, nts, mut ds) = function.resolve_types(names_table, &symbols_to_types); - insert_declared_types_into(sts, &mut symbols_to_types); - insert_resolved_types_into(nts, &mut resolved_types); - diagnostics.append(&mut ds); - } - - (symbols_to_types, resolved_types, diagnostics) - } - - #[deprecated] - pub fn gather_types_into( - &self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics = Vec::new(); - - for class in &self.classes { - handle_diagnostics!(class.gather_types(symbol_table, types_table), diagnostics); - } - - for function in &self.functions { - function.gather_types(symbol_table, types_table); - } - - for extern_function in &self.extern_functions { - extern_function.gather_types(symbol_table, types_table); - } - - diagnostics_result!(diagnostics) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - collect_diagnostics_into_mut( - &mut self.functions, - |f| f.type_check(symbol_table, types_table), - &mut diagnostics, - ); - - collect_diagnostics_into_mut( - &mut self.extern_functions, - |ef| ef.type_check(symbol_table, types_table), - &mut diagnostics, - ); - - collect_diagnostics_into_mut( - &mut self.classes, - |c| c.type_check(symbol_table, types_table), - &mut diagnostics, - ); - - diagnostics_result!(diagnostics) - } - - pub fn lower_to_ir( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> (Vec, Vec) { - let mut ir_classes = Vec::new(); - let mut ir_functions = Vec::new(); - - for function in &self.functions { - ir_functions.push(function.lower_to_ir_static( - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - )); - } - - for class in &self.classes { - let (ir_class, mut class_ir_functions) = - class.lower_to_ir(nodes_to_symbols, symbols_to_types, nodes_to_types); - ir_classes.push(ir_class); - ir_functions.append(&mut class_ir_functions); - } - - (ir_classes, ir_functions) - } - - #[deprecated] - pub fn to_ir( - &self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> (Vec, Vec) { - let mut functions: Vec = vec![]; - let mut classes: Vec = vec![]; - - self.functions - .iter() - .map(|f| f.to_ir(symbol_table, types_table, None)) - .for_each(|f| functions.push(f)); - - for class in &self.classes { - let (class, mut class_functions) = class.to_ir(symbol_table, types_table); - functions.append(&mut class_functions); - classes.push(class); - } - - (classes, functions) - } } diff --git a/dmc-lib/src/ast/constructor.rs b/dmc-lib/src/ast/constructor.rs index faaab87..2938f10 100644 --- a/dmc-lib/src/ast/constructor.rs +++ b/dmc-lib/src/ast/constructor.rs @@ -1,37 +1,7 @@ -use crate::ast::field::Field; -use crate::ast::fqn_context::FqnContext; -use crate::ast::fqn_util::fqn_parts_to_string; -use crate::ast::helpers::{ - collect_parameter_symbols_into, insert_resolved_names_into, resolve_ctor_name, -}; -use crate::ast::ir_builder::IrBuilder; +use crate::ast::NodeId; use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::ir::ir_allocate::IrAllocate; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_expression::IrExpression; -use crate::ir::ir_function::IrFunction; -use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut; -use crate::ir::ir_operation::IrOperation; -use crate::ir::ir_parameter::IrParameter; -use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; -use crate::ir::ir_return::IrReturn; -use crate::ir::ir_set_field::IrSetField; -use crate::ir::ir_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::constructor_symbol::ConstructorSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::cell::RefCell; -use std::collections::HashSet; -use std::ops::Neg; -use std::rc::Rc; pub struct Constructor { node_id: NodeId, @@ -63,375 +33,4 @@ impl Constructor { pub fn statements(&self) -> &[Statement] { &self.statements } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - - let function_scope = symbol_table.push_function_scope("constructor_scope"); - - for parameter in &mut self.parameters { - parameter.init_scopes(symbol_table, function_scope); - } - - let body_scope = symbol_table.push_block_scope("body_scope"); - for statement in &mut self.statements { - statement.init_scopes(symbol_table, body_scope); - } - - symbol_table.pop_scope(); - symbol_table.pop_scope(); - } - - pub fn make_symbols(&self, fqn_context: &FqnContext) -> (Rc, Vec) { - let mut all_symbols: Vec = Vec::new(); - - let mut parameter_symbols = Vec::new(); - collect_parameter_symbols_into(&self.parameters, &mut all_symbols, &mut parameter_symbols); - - let constructor_symbol = Rc::new(ConstructorSymbol::new( - &self.ctor_keyword_source_range, - resolve_ctor_name(fqn_context), - false, - false, - self.scope_id.unwrap(), - parameter_symbols, - )); - all_symbols.push(Symbol::Constructor(constructor_symbol.clone())); - - (constructor_symbol, all_symbols) - } - - pub fn resolve_names( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - initialized_fields: &mut HashSet>, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for parameter in &self.parameters { - let (ns, mut ds) = parameter.resolve_names(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - for statement in &self.statements { - let (ns, mut ds) = - statement.resolve_names_ctor(symbol_table, self_class_symbol, initialized_fields); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - for parameter in &self.parameters { - diagnostics.append(&mut parameter.check_names(symbol_table)); - } - diagnostics - } - - #[deprecated] - pub fn analyze_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.statements - .iter() - .flat_map(|s| s.analyze_constructor_local_names(symbol_table, class_symbol)) - .collect() - } - - #[deprecated] - pub fn gather_types_into(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) { - for parameter in &self.parameters { - parameter.gather_types_into(symbol_table, types_table); - } - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - let parameters_diagnostics: Vec = self - .parameters - .iter_mut() - .map(|param| param.type_check(symbol_table, types_table)) - .filter_map(Result::err) - .flatten() - .collect(); - - if !parameters_diagnostics.is_empty() { - return Err(parameters_diagnostics); - } - - let statements_diagnostics: Vec = self - .statements - .iter_mut() - .map(|statement| statement.type_check(symbol_table, types_table, None)) - .filter_map(Result::err) - .flatten() - .collect(); - - if statements_diagnostics.is_empty() { - Ok(()) - } else { - Err(statements_diagnostics) - } - } - - #[deprecated] - pub fn to_ir( - &self, - class_symbol: &Rc, - fields: &[Field], - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrFunction { - let mut ir_builder = IrBuilder::new(); - - let parameters_count = self.parameters.len(); - let ir_parameters = self - .parameters - .iter() - .enumerate() - .map(|(i, parameter)| { - let parameter_symbol = symbol_table - .get_parameter_symbol_owned(parameter.scope_id(), parameter.declared_name()) - .unwrap(); - let parameter_type = types_table - .parameter_types() - .get(¶meter_symbol) - .unwrap(); - let offset = (parameters_count as isize).neg() + i as isize; - let ir_parameter = Rc::new(IrParameter::new( - parameter_symbol.declared_name(), - todo!(), - offset, - )); - - // make sure to save ir_parameter to symbol so others can access it - ir_builder.push_parameter(¶meter_symbol, ir_parameter.clone()); - - ir_parameter - }) - .collect::>(); - - let entry_block_id = ir_builder.new_block(); - - // first, allocate the object into a t var - let alloc_assign_destination = todo!(); - let self_variable = Rc::new(RefCell::new(alloc_assign_destination)); - - // save self variable so statements can assign stuff to self's fields - ir_builder.set_self_parameter_or_variable(IrParameterOrVariable::Variable(todo!())); - - let alloc_assign = IrAssign::new( - todo!(), - IrOperation::Allocate(IrAllocate::new(class_symbol.declared_name_owned())), - ); - ir_builder - .current_block_mut() - .add_statement(IrStatement::Assign(alloc_assign)); - - // next, initialize fields that have an initializer in their declaration - for field in fields { - if let Some(initializer) = field.initializer() { - let field_symbol = symbol_table - .get_field_symbol_owned(field.scope_id(), field.declared_name()) - .unwrap(); - let field_type = types_table.field_types().get(&field_symbol).unwrap(); - // get a mut ref to the field - let ir_get_field_ref_mut = IrGetFieldRefMut::new( - IrParameterOrVariable::Variable(todo!()), - field_symbol.field_index(), - ); - let field_mut_ref_variable_name: Rc = ir_builder.new_t_var().into(); - let field_mut_ref_variable = Rc::new(RefCell::new(todo!())); - let field_mut_ref_assign = - IrAssign::new(todo!(), IrOperation::GetFieldRefMut(ir_get_field_ref_mut)); - ir_builder - .current_block_mut() - .add_statement(IrStatement::Assign(field_mut_ref_assign)); - - // save the mut ref to the builder for other uses if needed - ir_builder - .field_mut_pointer_variables_mut() - .insert(field.declared_name_owned(), field_mut_ref_variable); // n.b. field name, not t var name - - // now write the initializer result to the field - let field_mut_ref_variable = ir_builder - .field_mut_pointer_variables() - .get(field.declared_name()) - .unwrap() - .clone(); - - let ir_expression = initializer - .to_ir_expression(&mut ir_builder, symbol_table, types_table) - .unwrap(); - let ir_set_field = IrSetField::new( - todo!(), // dumb that we clone it and then ref it - ir_expression, - ); - ir_builder - .current_block_mut() - .add_statement(IrStatement::SetField(ir_set_field)); - } - } - - // do "declared" statements of constructor - for statement in &self.statements { - statement.to_ir(&mut ir_builder, symbol_table, types_table, false); - } - - // return complete self object - let ir_return_statement = - IrStatement::Return(IrReturn::new(Some(IrExpression::Variable(todo!())))); - ir_builder - .current_block_mut() - .add_statement(ir_return_statement); - - ir_builder.finish_block(); - let entry_block = ir_builder.get_block(entry_block_id); - - let constructor_symbol = symbol_table - .get_constructor_symbol(self.scope_id.unwrap()) - .unwrap(); - todo!() - } - - pub fn lower_to_ir( - &self, - class_symbol: &Rc, - fields: &[Field], - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> IrFunction { - let mut ir_builder = IrBuilder::new(); - - // gather ir_parameters - let mut ir_parameters = Vec::new(); - let base_offset = (self.parameters.len() as isize).neg(); - for (i, parameter) in self.parameters.iter().enumerate() { - let symbol = nodes_to_symbols.get(¶meter.node_id()).unwrap(); - let parameter_type = symbols_to_types.get(symbol).unwrap(); - let offset = base_offset + i as isize; - let ir_parameter = Rc::new(IrParameter::new(symbol.declared_name(), todo!(), offset)); - - // save in builder - ir_builder.push_parameter(symbol.unwrap_parameter_symbol(), ir_parameter.clone()); - - // push for saving to IrFunction - ir_parameters.push(ir_parameter); - } - - // entry-block - let entry_block_id = ir_builder.new_block(); - - // PART 1: Make self object - let self_variable = Rc::new(RefCell::new(todo!())); - // - // // save self variable in builder - // ir_builder - // .set_self_parameter_or_variable(IrParameterOrVariable::Variable(self_variable.clone())); - // - // // allocate the self object - // let ir_assign = IrAssign::new( - // self_variable.clone(), - // IrOperation::Allocate(IrAllocate::new(class_symbol.declared_name_owned())), - // ); - // ir_builder - // .current_block_mut() - // .add_statement(IrStatement::Assign(ir_assign)); - // - // // PART 2: Initialize fields that are initialized OUTSIDE the constructor - // for field in fields { - // if let Some(initializer) = field.initializer() { - // let symbol = nodes_to_symbols.get(&field.node_id()).unwrap(); - // let field_type = symbols_to_types.get(symbol).unwrap(); - // let field_symbol = symbol.unwrap_field_symbol(); - // - // // 1. Get a mut ref to the field - // // mut t_var: Type = &mut self.x - // let ir_get_field_ref_mut = IrGetFieldRefMut::new( - // IrParameterOrVariable::Variable(self_variable.clone()), - // field_symbol.field_index(), - // ); - // let field_ref_mut_ir_variable = Rc::new(RefCell::new(IrVariable::new_vr( - // ir_builder.new_t_var().into(), - // ir_builder.current_block().id(), - // field_type, - // ))); - // let ir_assign = IrAssign::new( - // field_ref_mut_ir_variable.clone(), - // IrOperation::GetFieldRefMut(ir_get_field_ref_mut), - // ); - // ir_builder - // .current_block_mut() - // .add_statement(IrStatement::Assign(ir_assign)); - // - // // save the mut ref for later uses if needed - // ir_builder.field_mut_pointer_variables_mut().insert( - // field.declared_name_owned(), - // field_ref_mut_ir_variable.clone(), - // ); - // - // // 2. Evaluate initializer and save result to mut field ref - // let ir_expression = initializer.lower_to_ir_expression( - // &mut ir_builder, - // nodes_to_symbols, - // symbols_to_types, - // nodes_to_types, - // ); - // let ir_set_field = IrSetField::new(&field_ref_mut_ir_variable, ir_expression); - // ir_builder - // .current_block_mut() - // .add_statement(IrStatement::SetField(ir_set_field)); - // } - // } - // - // // PART 3. Constructor statements - // for statement in &self.statements { - // statement.lower_to_ir( - // &mut ir_builder, - // nodes_to_symbols, - // symbols_to_types, - // nodes_to_types, - // false, - // ); - // } - // - // // PART 4. Return finished self object - // let ir_return_statement = IrStatement::Return(IrReturn::new(Some(IrExpression::Variable( - // self_variable.clone(), - // )))); - // ir_builder - // .current_block_mut() - // .add_statement(ir_return_statement); - // - // // Finish up the builder and return IrFunction - // ir_builder.finish_block(); - // let entry_block = ir_builder.get_block(entry_block_id); - // - // let constructor_symbol = nodes_to_symbols - // .get(&self.node_id) - // .unwrap() - // .unwrap_constructor_symbol(); - - // IrFunction::new( - // fqn_parts_to_string(constructor_symbol.fqn_parts()), - // ir_parameters, - // &TypeInfo::Class(class_symbol.clone()), // TODO - // entry_block.clone(), - // ) - todo!() - } } diff --git a/dmc-lib/src/ast/expression.rs b/dmc-lib/src/ast/expression.rs index 8da989b..c2dbda2 100644 --- a/dmc-lib/src/ast/expression.rs +++ b/dmc-lib/src/ast/expression.rs @@ -1,25 +1,12 @@ +use crate::ast::NodeId; use crate::ast::binary_expression::BinaryExpression; use crate::ast::call::Call; use crate::ast::double_literal::DoubleLiteral; 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::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -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::class_symbol::ClassSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::cell::RefCell; -use std::rc::Rc; pub enum Expression { Binary(BinaryExpression), @@ -44,321 +31,6 @@ impl Expression { } } - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.init_scopes(symbol_table, container_scope); - } - Expression::Negative(negative_expression) => { - negative_expression.init_scopes(symbol_table, container_scope); - } - Expression::Call(call) => { - call.init_scopes(symbol_table, container_scope); - } - Expression::Identifier(identifier) => { - identifier.init_scope_id(container_scope); - } - _ => {} - } - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.resolve_names_static(symbol_table) - } - Expression::Negative(negative_expression) => { - negative_expression.resolve_names_static(symbol_table) - } - Expression::Call(call) => call.resolve_names_static(symbol_table), - Expression::Identifier(identifier) => identifier.resolve_name_static(symbol_table), - _ => (NodesToSymbols::new(), Diagnostics::new()), - } - } - - pub fn resolve_names_field_init( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.resolve_names_field_init(symbol_table, self_class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.resolve_names_field_init(symbol_table, self_class_symbol) - } - Expression::Call(call) => { - call.resolve_names_field_init(symbol_table, self_class_symbol) - } - Expression::Identifier(identifier) => { - identifier.resolve_name_field_init(symbol_table, self_class_symbol) - } - _ => (NodesToSymbols::new(), Diagnostics::new()), - } - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.resolve_names_ctor(symbol_table, self_class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.resolve_names_ctor(symbol_table, self_class_symbol) - } - Expression::Call(call) => call.resolve_names_ctor(symbol_table, self_class_symbol), - Expression::Identifier(identifier) => { - identifier.resolve_name_ctor(symbol_table, self_class_symbol) - } - _ => (NodesToSymbols::new(), Diagnostics::new()), - } - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.resolve_names_method(symbol_table, self_class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.resolve_names_method(symbol_table, self_class_symbol) - } - Expression::Call(call) => call.resolve_names_method(symbol_table, self_class_symbol), - Expression::Identifier(identifier) => { - identifier.resolve_name_method(symbol_table, self_class_symbol) - } - _ => (NodesToSymbols::new(), Diagnostics::new()), - } - } - - #[deprecated] - pub fn check_field_initializer_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Expression::Binary(binary_expression) => { - binary_expression.check_field_initializer_names(symbol_table, class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.check_field_initializer_names(symbol_table, class_symbol) - } - Expression::Call(call) => { - call.check_field_initializer_names(symbol_table, class_symbol) - } - Expression::Identifier(identifier) => { - if let Some(diagnostic) = - identifier.check_name_as_field_initializer(symbol_table, class_symbol) - { - vec![diagnostic] - } else { - vec![] - } - } - _ => vec![], - } - } - - #[deprecated] - pub fn check_constructor_destination_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Expression::Binary(_) => { - panic!() - } - Expression::Negative(_) => { - panic!() - } - Expression::Call(_) => { - panic!() - } - Expression::Identifier(identifier) => { - if let Some(diagnostic) = - identifier.check_constructor_destination_name(symbol_table, class_symbol) - { - vec![diagnostic] - } else { - vec![] - } - } - _ => vec![], - } - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Expression::Binary(binary_expression) => { - binary_expression.check_constructor_local_names(symbol_table, class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.check_constructor_local_names(symbol_table, class_symbol) - } - Expression::Call(call) => { - call.check_constructor_local_names(symbol_table, class_symbol) - } - Expression::Identifier(identifier) => { - if let Some(diagnostic) = - identifier.check_constructor_local_name(symbol_table, class_symbol) - { - vec![diagnostic] - } else { - vec![] - } - } - _ => vec![], - } - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Expression::Binary(binary_expression) => { - binary_expression.check_method_local_names(symbol_table, class_symbol) - } - Expression::Negative(negative_expression) => { - negative_expression.check_method_local_names(symbol_table, class_symbol) - } - Expression::Call(call) => call.check_method_local_names(symbol_table, class_symbol), - Expression::Identifier(identifier) => { - if let Some(diagnostic) = - identifier.check_method_local_name(symbol_table, class_symbol) - { - vec![diagnostic] - } else { - vec![] - } - } - _ => vec![], - } - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - match self { - Expression::Binary(binary_expression) => { - binary_expression.check_static_fn_local_names(symbol_table) - } - Expression::Negative(negative_expression) => { - negative_expression.check_static_fn_local_names(symbol_table) - } - Expression::Call(call) => call.check_static_fn_local_names(symbol_table), - Expression::Identifier(identifier) => { - if let Some(diagnostic) = identifier.check_static_fn_local_name(symbol_table) { - vec![diagnostic] - } else { - vec![] - } - } - Expression::Integer(_) => { - vec![] - } - Expression::Double(_) => { - vec![] - } - Expression::String(_) => { - vec![] - } - } - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - match self { - Expression::Binary(binary_expression) => { - binary_expression.resolve_types(nodes_to_symbols, symbols_to_types) - } - Expression::Negative(negative_expression) => { - negative_expression.resolve_types(nodes_to_symbols, symbols_to_types) - } - Expression::Call(call) => call.resolve_types(nodes_to_symbols, symbols_to_types), - Expression::Identifier(identifier) => { - identifier.resolve_type(nodes_to_symbols, symbols_to_types) - } - Expression::Integer(integer_literal) => { - let mut resolved_types = NodesToTypes::new(); - resolved_types.insert( - integer_literal.node_id(), - integer_literal.type_info().clone(), - ); - (resolved_types, Diagnostics::new()) - } - Expression::Double(double_literal) => { - let mut resolved_types = NodesToTypes::new(); - resolved_types.insert(double_literal.node_id(), double_literal.type_info().clone()); - (resolved_types, Diagnostics::new()) - } - Expression::String(string_literal) => { - let mut resolved_types = NodesToTypes::new(); - resolved_types.insert(string_literal.node_id(), string_literal.type_info().clone()); - (resolved_types, Diagnostics::new()) - } - } - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - match self { - Expression::Binary(binary_expression) => { - binary_expression.type_check(symbol_table, types_table) - } - Expression::Negative(negative_expression) => { - negative_expression.type_check(symbol_table, types_table) - } - Expression::Call(call) => call.type_check(symbol_table, types_table), - Expression::Identifier(_) => Ok(()), - Expression::Integer(_) => Ok(()), - Expression::Double(_) => Ok(()), - Expression::String(_) => Ok(()), - } - } - - #[deprecated] - pub fn type_info<'a>( - &'a self, - symbol_table: &SymbolTable, - types_table: &'a TypesTable, - ) -> &'a TypeInfo { - match self { - Expression::Binary(binary_expression) => binary_expression.type_info(), - Expression::Negative(negative_expression) => negative_expression.type_info(), - Expression::Call(call) => call.return_type_info(symbol_table, types_table), - Expression::Identifier(identifier) => identifier.type_info(symbol_table, types_table), - Expression::Integer(integer_literal) => integer_literal.type_info(), - Expression::Double(double_literal) => double_literal.type_info(), - Expression::String(string_literal) => string_literal.type_info(), - } - } - pub fn source_range(&self) -> &SourceRange { match self { Expression::Binary(binary_expression) => binary_expression.source_range(), @@ -370,136 +42,4 @@ impl Expression { Expression::String(string_literal) => string_literal.source_range(), } } - - 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) => binary_expression.lower_to_ir_operation( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ), - 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, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrOperation { - match self { - Expression::Binary(binary_expression) => { - binary_expression.to_ir_operation(builder, symbol_table, types_table) - } - Expression::Call(call) => { - IrOperation::Call(call.to_ir(builder, symbol_table, types_table)) - } - 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())) - } - Expression::Identifier(identifier) => { - IrOperation::Load(identifier.ir_expression(builder, symbol_table, types_table)) - } - Expression::Negative(negative_expression) => { - IrOperation::Load(negative_expression.to_ir(builder, symbol_table, types_table)) - } - } - } - - pub fn to_ir_expression( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Option { - match self { - Expression::Binary(binary_expression) => { - Some(binary_expression.to_ir_expression(builder, symbol_table, types_table)) - } - Expression::Negative(negative_expression) => { - Some(negative_expression.to_ir(builder, symbol_table, types_table)) - } - Expression::Call(call) => { - let ir_call = call.to_ir(builder, symbol_table, types_table); - if matches!( - call.return_type_info(symbol_table, types_table), - TypeInfo::Void - ) { - builder - .current_block_mut() - .add_statement(IrStatement::Call(ir_call)); - None - } else { - let t_var = todo!(); - let as_rc = Rc::new(RefCell::new(t_var)); - let assign = IrAssign::new(todo!(), IrOperation::Call(ir_call)); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(assign)); - Some(IrExpression::Variable(todo!())) - } - } - Expression::Identifier(identifier) => { - Some(identifier.ir_expression(builder, symbol_table, types_table)) - } - Expression::Integer(integer_literal) => { - Some(IrExpression::Int(integer_literal.value())) - } - Expression::Double(double_literal) => { - Some(IrExpression::Double(double_literal.value())) - } - Expression::String(string_literal) => { - Some(IrExpression::String(string_literal.content().into())) - } - } - } } diff --git a/dmc-lib/src/ast/expression_statement.rs b/dmc-lib/src/ast/expression_statement.rs index f5e9bff..3e4af73 100644 --- a/dmc-lib/src/ast/expression_statement.rs +++ b/dmc-lib/src/ast/expression_statement.rs @@ -1,23 +1,12 @@ use crate::ast::expression::Expression; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::ir::ir_return::IrReturn; -use crate::ir::ir_statement::IrStatement; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; pub struct ExpressionStatement { - node_id: NodeId, expression: Box, } impl ExpressionStatement { - pub fn new(node_id: NodeId, expression: Expression) -> Self { + pub fn new(expression: Expression) -> Self { Self { - node_id, expression: expression.into(), } } @@ -25,140 +14,4 @@ impl ExpressionStatement { pub fn expression(&self) -> &Expression { &self.expression } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.expression.init_scopes(symbol_table, container_scope); - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - self.expression.resolve_names_static(symbol_table) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - self.expression - .resolve_names_ctor(symbol_table, self_class_symbol) - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - self.expression - .resolve_names_method(symbol_table, self_class_symbol) - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.expression - .check_constructor_local_names(symbol_table, class_symbol) - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.expression - .check_method_local_names(symbol_table, class_symbol) - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - self.expression.check_static_fn_local_names(symbol_table) - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let (mut nodes_to_types, diagnostics) = self - .expression - .resolve_types(nodes_to_symbols, symbols_to_types); - - // add self for last-statement type checking - let expression_type_info = nodes_to_types - .get(&self.expression.node_id()) - .cloned() - .unwrap(); - nodes_to_types.insert(self.node_id, expression_type_info); - - (nodes_to_types, diagnostics) - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - must_return_type_info: Option<&TypeInfo>, - ) -> Result<(), Vec> { - self.expression.type_check(symbol_table, types_table)?; - - if must_return_type_info.is_some() { - let expression_type = self.expression.type_info(symbol_table, types_table); - 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, - types_table: &TypesTable, - should_return_value: bool, - ) { - let ir_expression = self - .expression - .to_ir_expression(builder, symbol_table, types_table); - if ir_expression.is_some() && should_return_value { - builder - .current_block_mut() - .add_statement(IrStatement::Return(IrReturn::new(ir_expression))); - } - } - - pub fn lower_to_ir( - &self, - builder: &mut IrBuilder, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - is_return_statement: bool, - ) { - let ir_expression = self.expression.lower_to_ir_expression( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ); - if is_return_statement { - builder - .current_block_mut() - .add_statement(IrStatement::Return(IrReturn::new(Some(ir_expression)))); - } - } } diff --git a/dmc-lib/src/ast/extern_function.rs b/dmc-lib/src/ast/extern_function.rs index 6d02aa5..949cd5c 100644 --- a/dmc-lib/src/ast/extern_function.rs +++ b/dmc-lib/src/ast/extern_function.rs @@ -1,18 +1,7 @@ -use crate::ast::fqn_context::FqnContext; -use crate::ast::helpers::{ - collect_diagnostics_into_mut, collect_parameter_symbols_into, resolve_parameter_names_into, -}; +use crate::ast::NodeId; use crate::ast::parameter::Parameter; use crate::ast::type_use::TypeUse; -use crate::ast::{NodeId, NodesToSymbols, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::function_symbol::FunctionSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics}; use std::rc::Rc; pub struct ExternFunction { @@ -21,7 +10,6 @@ pub struct ExternFunction { declared_name_source_range: SourceRange, parameters: Vec, return_type: TypeUse, - scope_id: Option, } impl ExternFunction { @@ -38,7 +26,6 @@ impl ExternFunction { declared_name_source_range, parameters, return_type, - scope_id: None, } } @@ -65,153 +52,4 @@ impl ExternFunction { pub fn return_type(&self) -> &TypeUse { &self.return_type } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - - let function_scope = symbol_table - .push_function_scope(&format!("extern_function_scope({})", self.declared_name)); - - for parameter in &mut self.parameters { - parameter.init_scopes(symbol_table, function_scope); - } - self.return_type.init_scopes(symbol_table, function_scope); - - symbol_table.pop_scope(); - } - - pub fn declared_symbols(&self, fqn_context: &FqnContext) -> (Rc, Vec) { - let mut all_symbols: Vec = Vec::new(); - - let mut parameter_symbols = Vec::new(); - collect_parameter_symbols_into(&self.parameters, &mut all_symbols, &mut parameter_symbols); - - let function_symbol = Rc::new(FunctionSymbol::new( - &self.declared_name, - self.declared_name_source_range.clone(), - fqn_context.resolve(self.declared_name()), - true, - false, - self.scope_id.unwrap(), - parameter_symbols, - )); - all_symbols.push(Symbol::Function(function_symbol.clone())); - - (function_symbol, all_symbols) - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - resolve_parameter_names_into( - &self.parameters, - symbol_table, - &mut names_table, - &mut diagnostics, - ); - - { - let (ns, mut ds) = self.return_type.resolve_names(symbol_table); - for (node_id, symbol) in ns { - names_table.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn declared_types( - &self, - nodes_to_symbols: &NodesToSymbols, - ) -> (SymbolsToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut symbols_to_types = SymbolsToTypes::new(); - - for parameter in &self.parameters { - let (type_info, mut ds) = parameter.declared_type(nodes_to_symbols); - let parameter_symbol = nodes_to_symbols.get(¶meter.node_id()).unwrap(); - symbols_to_types.insert(parameter_symbol.clone(), type_info); - diagnostics.append(&mut ds); - } - - (symbols_to_types, diagnostics) - } - - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - for parameter in &self.parameters { - diagnostics.append(&mut parameter.check_names(symbol_table)); - } - diagnostics.append(&mut self.return_type.check_names(symbol_table)); - diagnostics - } - - 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()) - .unwrap(); - - // self function type - types_table.function_types_mut().insert( - function_symbol.clone(), - TypeInfo::Function(function_symbol.clone()), - ); - - // return type (temporary) - let resolved_return_type = self - .return_type - .type_info(symbol_table, types_table) - .clone(); - types_table - .function_return_types_mut() - .insert(function_symbol, resolved_return_type); - - // parameters - for parameter in &self.parameters { - parameter.gather_types_into(symbol_table, types_table); - } - } - - fn type_check_parameters( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - diagnostics: &mut Vec, - ) { - collect_diagnostics_into_mut( - &mut self.parameters, - |p| p.type_check(symbol_table, types_table), - diagnostics, - ); - } - - fn type_check_return_type( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - diagnostics: &mut Vec, - ) { - handle_diagnostics!( - self.return_type.type_check(symbol_table, types_table), - diagnostics - ); - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - self.type_check_parameters(symbol_table, types_table, &mut diagnostics); - self.type_check_return_type(symbol_table, types_table, &mut diagnostics); - - diagnostics_result!(diagnostics) - } } diff --git a/dmc-lib/src/ast/field.rs b/dmc-lib/src/ast/field.rs index 48b6709..ee5a9f5 100644 --- a/dmc-lib/src/ast/field.rs +++ b/dmc-lib/src/ast/field.rs @@ -1,15 +1,7 @@ +use crate::ast::NodeId; use crate::ast::expression::Expression; -use crate::ast::helpers::insert_resolved_names_into; use crate::ast::type_use::TypeUse; -use crate::ast::{NodeId, NodesToSymbols, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostic_factories::field_has_no_type_or_init; -use crate::ir::ir_class::IrField; use crate::source_range::SourceRange; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::field_symbol::FieldSymbol; -use crate::symbol_table::SymbolTable; -use crate::types_table::TypesTable; use std::rc::Rc; pub struct Field { @@ -20,7 +12,6 @@ pub struct Field { is_mut: bool, declared_type: Option>, initializer: Option>, - scope_id: Option, } impl Field { @@ -41,7 +32,6 @@ impl Field { is_mut, declared_type: declared_type.map(Box::new), initializer: initializer.map(Box::new), - scope_id: None, } } @@ -64,177 +54,4 @@ impl Field { pub fn initializer(&self) -> Option<&Expression> { self.initializer.as_ref().map(Box::as_ref) } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - if let Some(type_use) = &mut self.declared_type { - type_use.init_scopes(symbol_table, container_scope); - } - if let Some(expression) = &mut self.initializer { - expression.init_scopes(symbol_table, container_scope); - } - } - - pub fn scope_id(&self) -> usize { - self.scope_id.unwrap() - } - - pub fn make_symbol(&self, field_index: usize) -> FieldSymbol { - FieldSymbol::new( - &self.declared_name, - self.declared_name_source_range.clone(), - self.is_mut, - self.scope_id.unwrap(), - field_index, - ) - } - - pub fn resolve_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut names_table = NodesToSymbols::new(); - let mut diagnostics = Diagnostics::new(); - - if let Some(type_use) = &self.declared_type { - let (ns, mut ds) = type_use.resolve_names(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - if let Some(initializer) = &self.initializer { - let (ns, mut ds) = initializer.resolve_names_field_init(symbol_table, class_symbol); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - if let Some(type_use) = &self.declared_type { - diagnostics.append(&mut type_use.check_names(symbol_table)); - } - diagnostics - } - - #[deprecated] - pub fn check_field_initializer_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - if let Some(initializer) = &self.initializer { - initializer.check_field_initializer_names(symbol_table, class_symbol) - } else { - vec![] - } - } - - pub fn gather_types( - &self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - // self field - let field_symbol = symbol_table - .get_field_symbol_owned(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - match &self.declared_type { - Some(declared_type) => { - let resolved_type = declared_type.type_info(symbol_table, types_table).clone(); - types_table - .field_types_mut() - .insert(field_symbol, resolved_type); - } - None => match &self.initializer { - Some(initializer) => { - let initializer_type = initializer.type_info(symbol_table, types_table).clone(); - types_table - .field_types_mut() - .insert(field_symbol, initializer_type); - } - None => { - // this is an error - return Err(vec![field_has_no_type_or_init( - self.declared_name(), - self.declared_name_source_range(), - )]); - } - }, - } - Ok(()) - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - if let Some(type_use) = &mut self.declared_type { - if let Some(mut type_use_diagnostics) = - type_use.type_check(symbol_table, types_table).err() - { - diagnostics.append(&mut type_use_diagnostics); - } - } - - if let Some(initializer) = &mut self.initializer { - if let Some(mut initializer_diagnostics) = - initializer.type_check(symbol_table, types_table).err() - { - diagnostics.append(&mut initializer_diagnostics); - } - } - - if !diagnostics.is_empty() { - return Err(diagnostics); - } - - // Now check that types are assignable - match self.declared_type.as_ref() { - Some(type_use) => match self.initializer.as_ref() { - Some(initializer) => { - let initializer_type_info = initializer.type_info(symbol_table, types_table); - let declared_type_info = type_use.type_info(symbol_table, types_table); - if declared_type_info.is_assignable_from(initializer_type_info) { - Ok(()) - } else { - Err(vec![ - Diagnostic::new( - &format!( - "Mismatched types: {} is not assignable to {}", - initializer_type_info, declared_type_info - ), - initializer.source_range().start(), - initializer.source_range().end(), - ) - .with_reporter(file!(), line!()), - ]) - } - } - None => Ok(()), - }, - None => Ok(()), - } - } - - pub fn lower_to_ir_field( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> IrField { - let symbol = nodes_to_symbols.get(&self.node_id).unwrap(); - let field_type = symbols_to_types.get(symbol).unwrap(); - IrField::new( - self.declared_name.clone(), - symbol.unwrap_field_symbol().field_index(), // todo: this needs to be stored NOT in the symbol - field_type.clone(), - ) - } } diff --git a/dmc-lib/src/ast/fqn.rs b/dmc-lib/src/ast/fqn.rs deleted file mode 100644 index 6a645db..0000000 --- a/dmc-lib/src/ast/fqn.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub struct Fqn { - parts: Vec, -} - -impl Fqn { - pub fn new(parts: &[&str]) -> Self { - Self { - parts: parts.iter().map(|s| s.to_string()).collect(), - } - } - - pub fn parts(&self) -> &[String] { - self.parts.as_slice() - } -} diff --git a/dmc-lib/src/ast/fqn_context.rs b/dmc-lib/src/ast/fqn_context.rs deleted file mode 100644 index f90fcfe..0000000 --- a/dmc-lib/src/ast/fqn_context.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::rc::Rc; - -pub struct FqnContext { - parts: Vec>, -} - -impl FqnContext { - pub fn new() -> Self { - Self { parts: vec![] } - } - - pub fn with_part(&self, part: &Rc) -> Self { - let mut new_parts = self.parts.clone(); - new_parts.push(part.clone()); - Self { parts: new_parts } - } - - pub fn resolve(&self, name: &str) -> Vec> { - let mut result = self.parts.clone(); - result.push(name.into()); - result - } -} diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 1e34211..197060a 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -1,29 +1,8 @@ -use crate::ast::fqn_context::FqnContext; -use crate::ast::fqn_util::fqn_parts_to_string; -use crate::ast::helpers::{ - collect_diagnostics_into_enumerated_mut, collect_diagnostics_into_mut, - collect_parameter_symbols_into, insert_declared_types_into, insert_resolved_names_into, - insert_resolved_types_into, resolve_parameter_names_into, -}; -use crate::ast::ir_builder::IrBuilder; +use crate::ast::NodeId; 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::diagnostic::{Diagnostic, Diagnostics}; -use crate::ir::ir_function::IrFunction; -use crate::ir::ir_parameter::IrParameter; -use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::function_symbol::FunctionSymbol; -use crate::symbol::parameter_symbol::ParameterSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics}; -use std::ops::Neg; use std::rc::Rc; pub struct Function { @@ -34,8 +13,6 @@ pub struct Function { parameters: Vec, return_type: Option, statements: Vec, - container_scope_id: Option, - function_scope_id: Option, } impl Function { @@ -56,8 +33,6 @@ impl Function { parameters, return_type, statements, - container_scope_id: None, - function_scope_id: None, } } @@ -88,466 +63,4 @@ impl Function { pub fn statements(&self) -> Vec<&Statement> { self.statements.iter().collect() } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.container_scope_id = Some(container_scope); - let function_scope = - symbol_table.push_function_scope(&format!("function_scope({})", self.declared_name)); - self.function_scope_id = Some(function_scope); - - for parameter in &mut self.parameters { - parameter.init_scopes(symbol_table, function_scope); - } - if let Some(type_use) = &mut self.return_type { - type_use.init_scopes(symbol_table, function_scope); - } - - let body_scope = - symbol_table.push_block_scope(&format!("body_scope({})", self.declared_name)); - - for statement in &mut self.statements { - statement.init_scopes(symbol_table, body_scope); - } - - symbol_table.pop_scope(); // body - symbol_table.pop_scope(); // function - } - - /// Return value contains self FunctionSymbol followed by all symbols (including self symbol). - pub fn declared_symbols( - &self, - fqn_context: &FqnContext, - is_method: bool, - ) -> (Rc, Vec) { - let mut all_symbols: Vec = vec![]; - - let mut parameter_symbols = Vec::new(); - - if is_method { - let self_parameter_symbol = Rc::new(ParameterSymbol::new( - &Rc::from("self"), - None, - self.function_scope_id.unwrap(), - )); - parameter_symbols.push(self_parameter_symbol.clone()); - all_symbols.push(Symbol::Parameter(self_parameter_symbol)) - } - - collect_parameter_symbols_into(&self.parameters, &mut all_symbols, &mut parameter_symbols); - - let function_symbol = Rc::new(FunctionSymbol::new( - &self.declared_name, - self.declared_name_source_range.clone(), - fqn_context.resolve(self.declared_name()), - false, - is_method, - self.container_scope_id.unwrap(), - parameter_symbols, - )); - all_symbols.push(Symbol::Function(function_symbol.clone())); - - (function_symbol, all_symbols) - } - - fn resolve_names_common(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_symbols = NodesToSymbols::new(); - - resolve_parameter_names_into( - &self.parameters, - symbol_table, - &mut nodes_to_symbols, - &mut diagnostics, - ); - - if let Some(type_use) = &self.return_type { - let (ns, mut ds) = type_use.resolve_names(symbol_table); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - // insert self function symbol with this node - let function_symbol = symbol_table - .get_function_symbol_owned(self.container_scope_id.unwrap(), &self.declared_name) - .unwrap(); - nodes_to_symbols.insert(self.node_id, Symbol::Function(function_symbol)); - - (nodes_to_symbols, diagnostics) - } - - pub fn resolve_names_static( - &self, - symbol_table: &mut SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let (mut nodes_to_symbols, mut diagnostics) = self.resolve_names_common(symbol_table); - - for statement in &self.statements { - let (ns, mut ds) = statement.resolve_names_static(symbol_table); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - (nodes_to_symbols, diagnostics) - } - - pub fn resolve_names_method( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let (mut nodes_to_symbols, mut diagnostics) = self.resolve_names_common(symbol_table); - - for statement in &self.statements { - let (ns, mut ds) = statement.resolve_names_method(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - (nodes_to_symbols, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics = Vec::new(); - for parameter in &self.parameters { - diagnostics.append(&mut parameter.check_names(symbol_table)); - } - if let Some(type_use) = &self.return_type { - diagnostics.append(&mut type_use.check_names(symbol_table)); - } - diagnostics - } - - #[deprecated] - pub fn analyze_method_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.statements - .iter() - .flat_map(|statement| statement.analyze_method_local_names(symbol_table, class_symbol)) - .collect() - } - - #[deprecated] - pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec { - self.statements - .iter() - .flat_map(|statement| statement.analyze_static_fn_local_names(symbol_table)) - .collect() - } - - pub fn declared_types( - &self, - nodes_to_symbols: &NodesToSymbols, - ) -> (SymbolsToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut symbols_to_types = SymbolsToTypes::new(); - - for parameter in &self.parameters { - let symbol = nodes_to_symbols.get(¶meter.node_id()).unwrap(); - let (type_info, mut ds) = parameter.declared_type(nodes_to_symbols); - symbols_to_types.insert(symbol.clone(), type_info); - diagnostics.append(&mut ds); - } - - // Insert return type as the type of this function symbol - let symbol = nodes_to_symbols.get(&self.node_id).unwrap().clone(); - let type_info = match &self.return_type { - None => TypeInfo::Void, - Some(type_use) => { - let (type_info, mut ds) = type_use.declared_type(nodes_to_symbols); - diagnostics.append(&mut ds); - type_info - } - }; - symbols_to_types.insert(symbol, type_info); - - (symbols_to_types, diagnostics) - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (SymbolsToTypes, NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_types = NodesToTypes::new(); - let mut symbols_to_types = symbols_to_types.clone(); - - for statement in &self.statements { - let (sts, nts, mut ds) = statement.resolve_types(nodes_to_symbols, &symbols_to_types); - insert_declared_types_into(sts, &mut symbols_to_types); // merge! - insert_resolved_types_into(nts, &mut nodes_to_types); - diagnostics.append(&mut ds); - } - - // todo: check last statement for return type - - (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.container_scope_id.unwrap(), self.declared_name()) - .unwrap(); - - // self type (the signature) - types_table.function_types_mut().insert( - function_symbol.clone(), - TypeInfo::Function(function_symbol.clone()), - ); - - // put return type (temporary, this is deprecated) - if let Some(type_use) = &self.return_type { - let resolved_return_type = type_use.type_info(symbol_table, types_table).clone(); - types_table - .function_return_types_mut() - .insert(function_symbol, resolved_return_type); - } else { - types_table - .function_return_types_mut() - .insert(function_symbol, TypeInfo::Void); - } - - // parameters - for parameter in &self.parameters { - parameter.gather_types_into(symbol_table, types_table); - } - } - - fn get_return_type_info( - types_table: &TypesTable, - function_symbol: &FunctionSymbol, - ) -> TypeInfo { - types_table - .function_return_types() - .get(function_symbol) - .cloned() - .unwrap() - } - - /// Type checks parameters. - fn type_check_parameters( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - diagnostics: &mut Vec, - ) { - collect_diagnostics_into_mut( - &mut self.parameters, - |p| p.type_check(symbol_table, types_table), - diagnostics, - ) - } - - /// Type checks return type. - fn type_check_return_type( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - diagnostics: &mut Vec, - ) { - if let Some(type_use) = &mut self.return_type { - handle_diagnostics!(type_use.type_check(symbol_table, types_table), diagnostics); - } - } - - /// Type checks statements, making sure the last statement matches return type, if necessary. - fn type_check_statements( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - diagnostics: &mut Vec, - function_symbol: &FunctionSymbol, - ) { - let return_type_info = Self::get_return_type_info(types_table, function_symbol); - let statements_len = self.statements.len(); - - collect_diagnostics_into_enumerated_mut( - &mut self.statements, - |i, s| { - let is_last = i == statements_len - 1; - if is_last { - s.type_check(symbol_table, types_table, Some(&return_type_info)) - } else { - s.type_check(symbol_table, types_table, None) - } - }, - diagnostics, - ); - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics = vec![]; - let function_symbol = symbol_table - .get_function_symbol(self.container_scope_id.unwrap(), self.declared_name()) - .unwrap(); - - // parameters - self.type_check_parameters(symbol_table, types_table, &mut diagnostics); - - // return type - self.type_check_return_type(symbol_table, types_table, &mut diagnostics); - - // statements - self.type_check_statements(symbol_table, types_table, &mut diagnostics, function_symbol); - - diagnostics_result!(diagnostics) - } - - /// Converts all parameters to ir. Saves the IrParameter to the associated parameter symbol. - fn parameters_to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) { - for (i, parameter) in self.parameters.iter().enumerate() { - let parameter_symbol = symbol_table - .get_parameter_symbol_owned(parameter.scope_id(), parameter.declared_name()) - .unwrap(); - let parameter_type_info = types_table - .parameter_types() - .get(¶meter_symbol) - .unwrap(); - let stack_offset = (self.parameters.len() as isize).neg() + (i as isize); - let ir_parameter = - IrParameter::new(parameter_symbol.declared_name(), todo!(), stack_offset); - let as_rc = Rc::new(ir_parameter); - builder.push_parameter(¶meter_symbol, as_rc.clone()); - } - } - - /// If `class_context.is_some()`, set parameter 0 to the self parameter/variable on the builder. - fn handle_method_case(&self, builder: &mut IrBuilder, class_context: Option<&ClassSymbol>) { - // if we are a method, we need to set the self parameter on the builder - if class_context.is_some() { - let parameter_0 = builder.parameters()[0].clone(); - // put it in the self parameter - builder.set_self_parameter_or_variable(IrParameterOrVariable::Parameter(todo!())); - } - } - - /// Convert all statements to ir. - fn statements_to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - function_symbol: &FunctionSymbol, - ) { - let return_type_info = Self::get_return_type_info(types_table, function_symbol); - 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.to_ir( - builder, - symbol_table, - types_table, - should_return_value && is_last, - ); - } - } - - #[deprecated] - pub fn to_ir( - &self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - class_context: Option<&ClassSymbol>, - ) -> IrFunction { - let mut builder = IrBuilder::new(); - let function_symbol = symbol_table - .get_function_symbol(self.container_scope_id.unwrap(), self.declared_name()) - .unwrap(); - - // parameters - self.parameters_to_ir(&mut builder, symbol_table, types_table); - - let entry_block_id = builder.new_block(); - - // preamble - self.handle_method_case(&mut builder, class_context); - - // body - self.statements_to_ir(&mut builder, symbol_table, types_table, function_symbol); - - builder.finish_block(); - - let entry_block = builder.get_block(entry_block_id).clone(); - IrFunction::new( - fqn_parts_to_string(function_symbol.fqn_parts()), - todo!(), - todo!(), - todo!(), - todo!(), - todo!(), - ) - } - - pub fn lower_to_ir_static( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - nodes_to_types: &NodesToTypes, - ) -> 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(), - todo!(), - stack_offset, - )); - builder.push_parameter(parameter_symbol, ir_parameter); - } - - let entry_block_id = builder.new_block(); - - // lower statements - let return_type_info = symbols_to_types - .get(&Symbol::Function(function_symbol.clone())) - .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_to_ir( - &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()), - todo!(), - todo!(), - todo!(), - todo!(), - todo!(), - ) - } } diff --git a/dmc-lib/src/ast/generic_parameter.rs b/dmc-lib/src/ast/generic_parameter.rs index 9d5de25..5acf02b 100644 --- a/dmc-lib/src/ast/generic_parameter.rs +++ b/dmc-lib/src/ast/generic_parameter.rs @@ -1,22 +1,11 @@ -use crate::ast::NodesToSymbols; -use crate::ast::helpers::insert_resolved_names_into; use crate::ast::type_use::TypeUse; -use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::source_range::SourceRange; -use crate::symbol::generic_parameter_symbol::GenericParameterSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics}; -use std::cell::RefCell; use std::rc::Rc; pub struct GenericParameter { declared_name: Rc, declared_name_source_range: SourceRange, extends: Vec, - scope_id: Option, - generic_parameter_symbol: Option>>, } impl GenericParameter { @@ -29,82 +18,6 @@ impl GenericParameter { declared_name: declared_name.into(), declared_name_source_range, extends, - scope_id: None, - generic_parameter_symbol: None, } } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - for type_use in &mut self.extends { - type_use.init_scopes(symbol_table, container_scope); - } - } - - pub fn make_symbol(&self) -> GenericParameterSymbol { - GenericParameterSymbol::new( - &self.declared_name, - &self.declared_name_source_range, - self.scope_id.unwrap(), - ) - } - - pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - for type_use in &self.extends { - let (ns, mut ds) = type_use.resolve_names(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - (names_table, diagnostics) - } - - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - self.extends - .iter() - .flat_map(|type_use| type_use.check_names(symbol_table)) - .collect() - } - - pub fn gather_types( - &self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - // self param - let generic_parameter_symbol = symbol_table - .get_generic_parameter_symbol_owned(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - types_table.generic_parameter_types_mut().insert( - generic_parameter_symbol.clone(), - TypeInfo::GenericType(generic_parameter_symbol), - ); - - let mut diagnostics = Vec::new(); - - for type_use in &self.extends { - handle_diagnostics!( - type_use.gather_types(symbol_table, types_table), - diagnostics - ); - } - - diagnostics_result!(diagnostics) - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - // check extends type uses - for type_use in &mut self.extends { - handle_diagnostics!(type_use.type_check(symbol_table, types_table), diagnostics); - } - diagnostics_result!(diagnostics) - } } diff --git a/dmc-lib/src/ast/helpers.rs b/dmc-lib/src/ast/helpers.rs deleted file mode 100644 index fb6de86..0000000 --- a/dmc-lib/src/ast/helpers.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::ast::fqn_context::FqnContext; -use crate::ast::parameter::Parameter; -use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostics_result; -use crate::symbol::Symbol; -use crate::symbol::parameter_symbol::ParameterSymbol; -use crate::symbol_table::SymbolTable; -use std::rc::Rc; - -/// Iterates through all `ts`, running the `f` function, and pushing returned `Diagnostic`s -/// into `diagnostics`. -pub fn collect_diagnostics_into_mut( - ts: &mut [T], - mut f: impl FnMut(&mut T) -> Result<(), Vec>, - diagnostics: &mut Vec, -) { - ts.iter_mut() - .map(|t| f(t)) - .filter_map(Result::err) - .flatten() - .for_each(|d| diagnostics.push(d)); -} - -/// Like `collect_diagnostics_into` but enumerated. -pub fn collect_diagnostics_into_enumerated_mut( - ts: &mut [T], - mut f: impl FnMut(usize, &mut T) -> Result<(), Vec>, - diagnostics: &mut Vec, -) { - ts.iter_mut() - .enumerate() - .map(|(i, t)| f(i, t)) - .filter_map(Result::err) - .flatten() - .for_each(|d| diagnostics.push(d)); -} - -pub fn collect_diagnostics_mut( - ts: &mut [T], - mut f: impl FnMut(&mut T) -> Result<(), Vec>, -) -> Result<(), Vec> { - let diagnostics = ts - .iter_mut() - .map(|t| f(t)) - .filter_map(Result::err) - .flatten() - .collect::>(); - diagnostics_result!(diagnostics) -} - -pub fn collect_diagnostics( - ts: &[T], - f: impl Fn(&T) -> Result<(), Vec>, -) -> Result<(), Vec> { - let diagnostics = ts - .iter() - .map(|t| f(t)) - .filter_map(Result::err) - .flatten() - .collect::>(); - diagnostics_result!(diagnostics) -} - -pub fn collect_diagnostics_single( - ts: &[T], - f: impl Fn(&T) -> Result<(), Diagnostic>, -) -> Result<(), Vec> { - let diagnostics = ts - .iter() - .map(|t| f(t)) - .filter_map(Result::err) - .collect::>(); - diagnostics_result!(diagnostics) -} - -pub fn gather_oks( - ts: &mut [T], - mut f: impl FnMut(&mut T) -> Result>, - diagnostics: &mut Vec, -) -> Vec { - let mut rs: Vec = vec![]; - for t in &mut ts[..] { - match f(t) { - Ok(r) => rs.push(r), - Err(mut t_diagnostics) => { - diagnostics.append(&mut t_diagnostics); - } - } - } - rs -} - -pub fn resolve_ctor_name(fqn_context: &FqnContext) -> Vec> { - fqn_context.resolve("ctor") // ctor is a keyword at the language level, should not be callable via normal means -} - -pub fn collect_parameter_symbols_into( - parameters: &[Parameter], - all_symbols: &mut Vec, - parameter_symbols: &mut Vec>, -) { - for parameter in parameters { - let symbol = Rc::new(parameter.make_symbol()); - all_symbols.push(Symbol::Parameter(symbol.clone())); - parameter_symbols.push(symbol); - } -} - -pub fn resolve_parameter_names_into( - parameters: &[Parameter], - symbol_table: &SymbolTable, - nodes_to_symbols: &mut NodesToSymbols, - diagnostics: &mut Diagnostics, -) { - for parameter in parameters { - let (ns, mut ds) = parameter.resolve_names(symbol_table); - for (node_id, symbol) in ns { - nodes_to_symbols.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } -} - -pub fn insert_resolved_names_into(source: NodesToSymbols, destination: &mut NodesToSymbols) { - for (node_id, symbol) in source { - destination.insert(node_id, symbol); - } -} - -pub fn insert_declared_types_into(source: SymbolsToTypes, destination: &mut SymbolsToTypes) { - for (symbol, type_info) in source { - destination.insert(symbol, type_info); - } -} - -pub fn insert_resolved_types_into(source: NodesToTypes, destination: &mut NodesToTypes) { - for (node_id, type_info) in source { - destination.insert(node_id, type_info); - } -} diff --git a/dmc-lib/src/ast/identifier.rs b/dmc-lib/src/ast/identifier.rs index 56db5e2..8d13ee9 100644 --- a/dmc-lib/src/ast/identifier.rs +++ b/dmc-lib/src/ast/identifier.rs @@ -1,36 +1,11 @@ -use crate::ast::ir_builder::IrBuilder; -use crate::ast::ir_util::get_or_init_field_pointer_variable; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostic_factories::{ - cannot_reassign_immutable_field, not_assignable, outer_class_field_usage, - outer_class_method_usage, self_constructor_used_in_init, self_field_used_in_init, - self_method_used_in_init, symbol_not_found, -}; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_expression::IrExpression; -use crate::ir::ir_operation::IrOperation; -use crate::ir::ir_read_field::IrReadField; -use crate::ir::ir_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; +use crate::ast::NodeId; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::expressible_symbol::ExpressibleSymbol; -use crate::symbol::field_symbol::FieldSymbol; -use crate::symbol::function_symbol::FunctionSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::cell::RefCell; -use std::collections::HashSet; use std::rc::Rc; pub struct Identifier { node_id: NodeId, name: Rc, source_range: SourceRange, - scope_id: Option, } impl Identifier { @@ -39,7 +14,6 @@ impl Identifier { node_id, name: name.into(), source_range, - scope_id: None, } } @@ -51,629 +25,7 @@ impl Identifier { &self.name } - pub fn init_scope_id(&mut self, container_scope: usize) { - self.scope_id = Some(container_scope); - } - - pub fn scope_id(&self) -> usize { - self.scope_id.unwrap() - } - - pub fn resolve_name_static(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - match symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name) { - None => { - diagnostics.push(symbol_not_found(&self.name, &self.source_range)); - } - Some(expressible_symbol) => { - names_table.insert(self.node_id, expressible_symbol.into_symbol()); - } - } - - (names_table, diagnostics) - } - - /// Resolves the name inside an initializer for a field *outside* a constructor. - pub fn resolve_name_field_init( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(class_symbol) => { - self.init_referring_to_class( - self_class_symbol, - &class_symbol, - &mut names_table, - &mut diagnostics, - ); - } - ExpressibleSymbol::Field(field_symbol) => { - self.init_referring_to_field( - self_class_symbol, - &field_symbol, - &mut diagnostics, - ); - } - ExpressibleSymbol::Function(function_symbol) => { - self.init_referring_to_function( - self_class_symbol, - &function_symbol, - &mut names_table, - &mut diagnostics, - ); - } - ExpressibleSymbol::Parameter(_) => { - // Cannot get here, because classes cannot currently be declared in functions - unreachable!() - } - ExpressibleSymbol::Variable(_) => { - // Cannot get here, as classes cannot currently be declared in functions - unreachable!() - } - } - } else { - diagnostics.push(symbol_not_found(&self.name, &self.source_range)); - } - - (names_table, diagnostics) - } - - /// Resolves the name as used in a rhs expression in a constructor. - pub fn resolve_name_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(class_symbol) => { - self.init_referring_to_class( - self_class_symbol, - &class_symbol, - &mut names_table, - &mut diagnostics, - ); - } - ExpressibleSymbol::Field(field_symbol) => { - self.init_referring_to_field( - self_class_symbol, - &field_symbol, - &mut diagnostics, - ); - } - ExpressibleSymbol::Function(function_symbol) => { - self.init_referring_to_function( - self_class_symbol, - &function_symbol, - &mut names_table, - &mut diagnostics, - ); - } - ExpressibleSymbol::Parameter(parameter_symbol) => { - names_table.insert(self.node_id, Symbol::Parameter(parameter_symbol)); - } - ExpressibleSymbol::Variable(variable_symbol) => { - names_table.insert(self.node_id, Symbol::Variable(variable_symbol)); - } - } - } else { - diagnostics.push(symbol_not_found(&self.name, &self.source_range)); - } - - (names_table, diagnostics) - } - - /// Resolves the name as an LValue in a constructor. - pub fn resolve_name_ctor_destination( - &self, - symbol_table: &SymbolTable, - initialized_fields: &mut HashSet>, - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut names_table = NodesToSymbols::new(); - - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(_) => { - // error - diagnostics.push(not_assignable(&self.name, &self.source_range)); - } - ExpressibleSymbol::Field(field_symbol) => { - // ok if field has not been initialized yet OR field is mutable - if !initialized_fields.contains(&self.name) { - initialized_fields.insert(self.name.clone()); - names_table.insert(self.node_id, Symbol::Field(field_symbol)); - } else if !field_symbol.is_mut() { - // error since we are trying to reassign an immutable field - diagnostics.push(cannot_reassign_immutable_field(&self.source_range)); - } else { - // mut is ok - names_table.insert(self.node_id, Symbol::Field(field_symbol)); - } - } - ExpressibleSymbol::Function(_) => { - diagnostics.push(not_assignable(&self.name, &self.source_range)); - } - ExpressibleSymbol::Parameter(_) => { - // assigning to parameter is an error - // we may in the future allow mut on parameters, but it's probably pointless - diagnostics.push(not_assignable(&self.name, &self.source_range)); - } - ExpressibleSymbol::Variable(variable_symbol) => { - // ok - names_table.insert(self.node_id, Symbol::Variable(variable_symbol)); - } - } - } else { - diagnostics.push(symbol_not_found(&self.name, &self.source_range)); - } - - (names_table, diagnostics) - } - - pub fn resolve_name_method( - &self, - symbol_table: &SymbolTable, - _self_class_symbol: &ClassSymbol, // for future when we have paths? - ) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut nodes_to_symbols = NodesToSymbols::new(); - - let maybe_expressible_symbol = - symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - match maybe_expressible_symbol { - None => { - diagnostics.push(symbol_not_found(&self.name, &self.source_range)); - } - Some(expressible_symbol) => { - nodes_to_symbols.insert(self.node_id, expressible_symbol.into_symbol()); - } - } - - (nodes_to_symbols, diagnostics) - } - - fn init_referring_to_class( - &self, - self_class_symbol: &ClassSymbol, - class_symbol: &Rc, - names_table: &mut NodesToSymbols, - diagnostics: &mut Diagnostics, - ) { - // Check against recursively constructing this class. - // This is not future-proof, as we will eventually allow reference to the self class, which - // would (theoretically) be assigned to an instance field. - if self_class_symbol == class_symbol.as_ref() { - diagnostics.push(self_constructor_used_in_init(&self.source_range)); - } else { - names_table.insert(self.node_id, Symbol::Class(class_symbol.clone())); - } - } - - fn init_referring_to_field( - &self, - self_class_symbol: &ClassSymbol, - field_symbol: &FieldSymbol, - diagnostics: &mut Diagnostics, - ) { - if self_class_symbol - .fields() - .contains_key(field_symbol.declared_name()) - { - diagnostics.push(self_field_used_in_init(&self.source_range)); - } else { - diagnostics.push(outer_class_field_usage(&self.source_range)); - } - } - - fn init_referring_to_function( - &self, - self_class_symbol: &ClassSymbol, - function_symbol: &Rc, - names_table: &mut NodesToSymbols, - diagnostics: &mut Diagnostics, - ) { - if self_class_symbol - .functions() - .contains_key(function_symbol.declared_name()) - { - diagnostics.push(self_method_used_in_init(&self.source_range)); - } else if function_symbol.is_method() { - diagnostics.push(outer_class_method_usage(&self.source_range)); - } else { - names_table.insert(self.node_id, Symbol::Function(function_symbol.clone())); - } - } - - /// Check against recursively constructing this class. - #[deprecated] - fn check_self_constructor_use( - &self, - context_class_symbol: &ClassSymbol, - class_symbol: &ClassSymbol, - ) -> Option { - // this is not future-proof, as we will eventually allow reference to the self class, which - // would (theoretically) be assigned to an instance field - if context_class_symbol == class_symbol { - Some(self_constructor_used_in_init(&self.source_range)) - } else { - None - } - } - - /// Check against using this or outer class' bare fields. - #[deprecated] - fn check_self_or_outer_field_use( - &self, - context_class_symbol: &ClassSymbol, - field_symbol: &FieldSymbol, - ) -> Option { - // Usage of a bare field will always be an error, whether in this class or an outer class - if context_class_symbol - .fields() - .contains_key(field_symbol.declared_name()) - { - Some(self_field_used_in_init(&self.source_range)) - } else { - Some(outer_class_field_usage(&self.source_range)) - } - } - - /// Check against using self or outer class methods. - #[deprecated] - fn check_self_or_outer_method_use( - &self, - context_class_symbol: &ClassSymbol, - function_symbol: &FunctionSymbol, - ) -> Option { - if context_class_symbol - .functions() - .contains_key(function_symbol.declared_name()) - { - // Can only use Self static functions, which we don't have yet - Some(self_method_used_in_init(&self.source_range)) - } else if function_symbol.is_method() { - // Can only use outer class static functions, which we don't have yet - Some(outer_class_method_usage(&self.source_range)) - } else { - None - } - } - - #[deprecated] - pub fn check_name_as_field_initializer( - &self, - symbol_table: &SymbolTable, - context_class_symbol: &ClassSymbol, - ) -> Option { - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(class_symbol) => { - self.check_self_constructor_use(context_class_symbol, &class_symbol) - } - ExpressibleSymbol::Field(field_symbol) => { - self.check_self_or_outer_field_use(context_class_symbol, &field_symbol) - } - ExpressibleSymbol::Function(function_symbol) => { - self.check_self_or_outer_method_use(context_class_symbol, &function_symbol) - } - ExpressibleSymbol::Parameter(_) => { - // Cannot get here, because classes cannot currently be declared in functions - unreachable!() - } - ExpressibleSymbol::Variable(_) => { - // Cannot get here, as classes cannot currently be declared in functions - unreachable!() - } - } - } else { - Some(symbol_not_found(&self.name, &self.source_range)) - } - } - - #[deprecated] - pub fn check_constructor_destination_name( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Option { - let expressible_symbol = - symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(expressible_symbol) = expressible_symbol { - match expressible_symbol { - ExpressibleSymbol::Class(_) => { - panic!("Class is not an L value") - } - ExpressibleSymbol::Field(field_symbol) => { - // This is just a stop-gap for now. We need to decide if we are going to do - // field assignment analysis (whether it's initialized already, if it's mut, - // etc.) during name checking or during type checking. - None - } - ExpressibleSymbol::Function(_) => { - panic!("Function is not an L value") - } - ExpressibleSymbol::Parameter(_) => { - panic!("Parameter is not an L value") - } - ExpressibleSymbol::Variable(variable_symbol) => { - // Again, a stop-gap. - None - } - } - } else { - Some(symbol_not_found(&self.name, &self.source_range)) - } - } - - #[deprecated] - pub fn check_constructor_local_name( - &self, - symbol_table: &SymbolTable, - context_class_symbol: &ClassSymbol, - ) -> Option { - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(class_symbol) => { - self.check_self_constructor_use(context_class_symbol, &class_symbol) - } - ExpressibleSymbol::Field(field_symbol) => { - self.check_self_or_outer_field_use(context_class_symbol, &field_symbol) - } - ExpressibleSymbol::Function(function_symbol) => { - self.check_self_or_outer_method_use(context_class_symbol, &function_symbol) - } - ExpressibleSymbol::Parameter(_) => None, - ExpressibleSymbol::Variable(_) => None, - } - } else { - Some(symbol_not_found(&self.name, &self.source_range)) - } - } - - #[deprecated] - pub fn check_method_local_name( - &self, - symbol_table: &SymbolTable, - context_class_symbol: &ClassSymbol, - ) -> Option { - let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); - if let Some(symbol) = symbol { - match symbol { - ExpressibleSymbol::Class(_) => { - None // all class usages should be ok - } - ExpressibleSymbol::Field(field_symbol) => { - // Must be a reference to a field in this class - if context_class_symbol - .fields() - .contains_key(field_symbol.declared_name()) - { - None - } else { - Some(outer_class_field_usage(&self.source_range)) - } - } - ExpressibleSymbol::Function(function_symbol) => { - // Must be a method in this class - if function_symbol.is_method() - && !context_class_symbol - .functions() - .contains_key(function_symbol.declared_name()) - { - Some(outer_class_method_usage(&self.source_range)) - } else { - None - } - } - ExpressibleSymbol::Parameter(_) => { - None // ok - } - ExpressibleSymbol::Variable(_) => { - None // ok - } - } - } else { - Some(symbol_not_found(&self.name, &self.source_range)) - } - } - - /// WARNING: this is not appropriate (yet) for class static functions. - #[deprecated] - pub fn check_static_fn_local_name(&self, symbol_table: &SymbolTable) -> Option { - if symbol_table - .find_expressible_symbol(self.scope_id.unwrap(), &self.name) - .is_some() - { - None - } else { - Some(symbol_not_found(&self.name, &self.source_range)) - } - } - pub fn source_range(&self) -> &SourceRange { &self.source_range } - - pub fn resolve_type( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let self_symbol = nodes_to_symbols.get(&self.node_id).unwrap(); - let type_info = symbols_to_types.get(self_symbol).unwrap(); - - let mut resolved_types = NodesToTypes::new(); - resolved_types.insert(self.node_id, type_info.clone()); - - (resolved_types, Diagnostics::new()) - } - - #[deprecated] - pub fn type_info<'a>( - &self, - symbol_table: &SymbolTable, - types_table: &'a TypesTable, - ) -> &'a TypeInfo { - let expressible_symbol = symbol_table - .find_expressible_symbol(self.scope_id.unwrap(), &self.name) - .unwrap(); - match expressible_symbol { - ExpressibleSymbol::Class(class_symbol) => { - types_table.class_types().get(&class_symbol).unwrap() - } - ExpressibleSymbol::Field(field_symbol) => { - types_table.field_types().get(&field_symbol).unwrap() - } - ExpressibleSymbol::Function(function_symbol) => types_table - .function_types() - .get(&function_symbol) - .expect(&format!( - "Unable to get function type for {:?}", - function_symbol - )), - ExpressibleSymbol::Parameter(parameter_symbol) => types_table - .parameter_types() - .get(¶meter_symbol) - .unwrap(), - ExpressibleSymbol::Variable(variable_symbol) => { - types_table.variable_types().get(&variable_symbol).unwrap() - } - } - } - - 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(todo!())); - let ir_read_field = IrReadField::new(todo!()); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - todo!(), - IrOperation::ReadField(ir_read_field), - ))); - IrExpression::Variable(todo!()) - } - ExpressibleSymbol::Function(_function_symbol) => { - todo!() - } - ExpressibleSymbol::Parameter(parameter_symbol) => IrExpression::Parameter(todo!()), - ExpressibleSymbol::Variable(variable_symbol) => IrExpression::Variable(todo!()), - } - } - - pub fn ir_expression( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrExpression { - let expressible_symbol = symbol_table - .find_expressible_symbol(self.scope_id.unwrap(), &self.name) - .unwrap(); - match expressible_symbol { - ExpressibleSymbol::Class(class_symbol) => { - todo!() - } - ExpressibleSymbol::Field(field_symbol) => { - let field_type = types_table.field_types().get(&field_symbol).unwrap(); - let read_destination = todo!(); - let read_destination_as_rc = Rc::new(RefCell::new(read_destination)); - let ir_read_field = IrReadField::new(todo!()); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - todo!(), - IrOperation::ReadField(ir_read_field), - ))); - IrExpression::Variable(todo!()) - } - ExpressibleSymbol::Function(_) => { - panic!("Cannot yet get ir-variable for FunctionSymbol") - } - ExpressibleSymbol::Parameter(parameter_symbol) => { - let parameters_map = builder.parameters_map(); - let ir_parameter = parameters_map.get(¶meter_symbol).unwrap(); - IrExpression::Parameter(todo!()) - } - ExpressibleSymbol::Variable(variable_symbol) => { - let ir_variable = builder.local_variables().get(&variable_symbol).unwrap(); - IrExpression::Variable(todo!()) - } - } - } -} - -#[cfg(test)] -mod tests { - use crate::ast::identifier::Identifier; - use crate::source_range::SourceRange; - use crate::symbol::Symbol; - use crate::symbol::variable_symbol::VariableSymbol; - use crate::symbol_table::SymbolTable; - use std::rc::Rc; - - #[test] - fn inits_scope_id() { - let mut identifier = Identifier::new(0, "foo", SourceRange::new(0, 0)); - identifier.init_scope_id(42); - assert_eq!(identifier.scope_id(), 42); - } - - #[test] - fn resolves_static_foo() { - let mut identifier = Identifier::new(0, "foo", SourceRange::new(0, 0)); - - let mut symbol_table = SymbolTable::new(); - symbol_table.push_module_scope("foo module"); - symbol_table.push_function_scope("foo function"); - let scope_id = symbol_table.push_block_scope("foo block"); - identifier.init_scope_id(scope_id); - - let variable_symbol = Rc::new(VariableSymbol::new( - &"foo".into(), - &SourceRange::new(0, 0), - false, - scope_id, - )); - symbol_table.insert_variable_symbol(variable_symbol.clone()); - - let (nodes_to_symbols, diagnostics) = identifier.resolve_name_static(&symbol_table); - - assert_eq!(diagnostics.len(), 0); - assert_eq!(nodes_to_symbols.len(), 1); - let symbol = nodes_to_symbols.get(&identifier.node_id()).unwrap(); - match symbol { - Symbol::Variable(matched_variable_symbol) => { - assert_eq!(&variable_symbol, matched_variable_symbol); - } - _ => panic!(), - } - } } diff --git a/dmc-lib/src/ast/ir_builder.rs b/dmc-lib/src/ast/ir_builder.rs deleted file mode 100644 index 1de6770..0000000 --- a/dmc-lib/src/ast/ir_builder.rs +++ /dev/null @@ -1,169 +0,0 @@ -use crate::ir::ir_block::IrBlock; -use crate::ir::ir_parameter::IrParameter; -use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; -use crate::ir::ir_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; -use crate::symbol::parameter_symbol::ParameterSymbol; -use crate::symbol::variable_symbol::VariableSymbol; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; - -pub struct IrBuilder { - parameters: Vec<(Rc, Rc)>, - local_variables: HashMap, Rc>>, - block_counter: usize, - t_var_counter: usize, - blocks: HashMap>>, - current_block_builder: Option, - self_parameter_or_variable: Option, - field_variables: HashMap, Rc>>, - mut_field_variables: HashMap, Rc>>, -} - -impl IrBuilder { - pub fn new() -> Self { - Self { - parameters: vec![], - local_variables: HashMap::new(), - block_counter: 0, - t_var_counter: 0, - blocks: HashMap::new(), - current_block_builder: None, - self_parameter_or_variable: None, - field_variables: HashMap::new(), - mut_field_variables: HashMap::new(), - } - } - - pub fn local_variables(&self) -> &HashMap, Rc>> { - &self.local_variables - } - - pub fn local_variables_mut( - &mut self, - ) -> &mut HashMap, Rc>> { - &mut self.local_variables - } - - pub fn parameters(&self) -> Vec<&Rc> { - self.parameters - .iter() - .map(|(_, ir_parameter)| ir_parameter) - .collect() - } - - pub fn parameters_map(&self) -> HashMap, Rc> { - let mut map = HashMap::new(); - for (name, ir_parameter) in &self.parameters { - map.insert(name.clone(), ir_parameter.clone()); - } - map - } - - pub fn push_parameter( - &mut self, - parameter_symbol: &Rc, - parameter: Rc, - ) { - self.parameters.push((parameter_symbol.clone(), parameter)); - } - - pub fn new_block(&mut self) -> usize { - let block_id = self.block_counter; - self.block_counter += 1; - let block_builder = IrBlockBuilder::new(block_id); - self.current_block_builder = Some(block_builder); - block_id - } - - pub fn get_block(&mut self, block_id: usize) -> &Rc> { - self.blocks - .get(&block_id) - .expect(&format!("Block {} not found", block_id)) - } - - pub fn current_block_mut(&mut self) -> &mut IrBlockBuilder { - self.current_block_builder - .as_mut() - .expect("No current block builder") - } - - pub fn current_block(&self) -> &IrBlockBuilder { - self.current_block_builder - .as_ref() - .expect("No current block") - } - - pub fn finish_block(&mut self) { - let builder = self - .current_block_builder - .take() - .expect("No current block builder"); - let block = builder.build(); - self.blocks.insert(block.id(), Rc::new(RefCell::new(block))); - } - - pub fn new_t_var(&mut self) -> String { - let id = self.t_var_counter; - self.t_var_counter += 1; - format!("t{}", id) - } - - pub fn set_self_parameter_or_variable( - &mut self, - self_parameter_or_variable: IrParameterOrVariable, - ) { - self.self_parameter_or_variable = Some(self_parameter_or_variable); - } - - pub fn self_parameter_or_variable(&self) -> &IrParameterOrVariable { - self.self_parameter_or_variable.as_ref().unwrap() - } - - pub fn field_pointer_variables(&self) -> &HashMap, Rc>> { - &self.field_variables - } - - pub fn field_pointer_variables_mut( - &mut self, - ) -> &mut HashMap, Rc>> { - &mut self.field_variables - } - - pub fn field_mut_pointer_variables(&self) -> &HashMap, Rc>> { - &self.mut_field_variables - } - - pub fn field_mut_pointer_variables_mut( - &mut self, - ) -> &mut HashMap, Rc>> { - &mut self.mut_field_variables - } -} - -pub struct IrBlockBuilder { - id: usize, - statements: Vec, -} - -impl IrBlockBuilder { - pub fn new(id: usize) -> Self { - Self { - id, - statements: vec![], - } - } - - pub fn id(&self) -> usize { - self.id - } - - pub fn add_statement(&mut self, statement: IrStatement) { - self.statements.push(statement); - } - - pub fn build(self) -> IrBlock { - IrBlock::new(self.id, &format!("b{}", self.id), self.statements) - } -} diff --git a/dmc-lib/src/ast/ir_util.rs b/dmc-lib/src/ast/ir_util.rs deleted file mode 100644 index 0f1fe0c..0000000 --- a/dmc-lib/src/ast/ir_util.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::ast::ir_builder::IrBuilder; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_get_field_ref::IrGetFieldRef; -use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut; -use crate::ir::ir_operation::IrOperation; -use crate::ir::ir_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; -use crate::symbol::field_symbol::FieldSymbol; -use crate::type_info::TypeInfo; -use std::cell::RefCell; -use std::rc::Rc; - -pub fn get_or_init_field_pointer_variable<'a>( - builder: &'a mut IrBuilder, - field_symbol: &Rc, - field_type: &TypeInfo, -) -> &'a Rc> { - // This following should work because blocks are flat in the ir; if a variable is defined in the - // ir block from this point forward, it's available to all subsequent blocks. - if !builder - .field_pointer_variables() - .contains_key(field_symbol.declared_name()) - { - let field_ref_variable = todo!(); - let as_rc = Rc::new(RefCell::new(field_ref_variable)); - let to_insert = as_rc.clone(); - let self_parameter_or_variable = builder.self_parameter_or_variable().clone(); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - todo!(), - IrOperation::GetFieldRef(IrGetFieldRef::new( - self_parameter_or_variable.clone(), - field_symbol.field_index(), - )), - ))); - builder - .field_pointer_variables_mut() - .insert(field_symbol.declared_name_owned(), to_insert); - } - builder - .field_pointer_variables() - .get(field_symbol.declared_name()) - .unwrap() -} - -pub fn get_or_init_mut_field_pointer_variable<'a>( - builder: &'a mut IrBuilder, - field_symbol: &Rc, - field_type: &TypeInfo, -) -> &'a Rc> { - if !builder - .field_mut_pointer_variables() - .contains_key(field_symbol.declared_name()) - { - let mut_field_pointer_variable = todo!(); - let as_rc = Rc::new(RefCell::new(mut_field_pointer_variable)); - let to_insert = as_rc.clone(); - let self_parameter_or_variable = builder.self_parameter_or_variable().clone(); - builder - .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - todo!(), - IrOperation::GetFieldRefMut(IrGetFieldRefMut::new( - self_parameter_or_variable.clone(), - field_symbol.field_index(), - )), - ))); - builder - .field_mut_pointer_variables_mut() - .insert(field_symbol.declared_name_owned(), to_insert); - } - builder - .field_mut_pointer_variables() - .get(field_symbol.declared_name()) - .unwrap() -} diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index 87e8ba3..2b24e06 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -1,20 +1,6 @@ +use crate::ast::NodeId; use crate::ast::expression::Expression; -use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into}; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; -use crate::symbol::Symbol; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol::variable_symbol::VariableSymbol; -use crate::symbol_table::SymbolTable; -use crate::symbol_table::util::try_insert_symbol_into; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::cell::RefCell; use std::rc::Rc; pub struct LetStatement { @@ -23,7 +9,6 @@ pub struct LetStatement { declared_name_source_range: SourceRange, is_mut: bool, initializer: Box, - scope_id: Option, } impl LetStatement { @@ -40,7 +25,6 @@ impl LetStatement { declared_name_source_range, is_mut, initializer: initializer.into(), - scope_id: None, } } @@ -67,295 +51,4 @@ impl LetStatement { pub fn initializer(&self) -> &Expression { &self.initializer } - - pub fn initializer_mut(&mut self) -> &mut Expression { - &mut self.initializer - } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - self.initializer.init_scopes(symbol_table, container_scope); - } - - pub fn scope_id(&self) -> usize { - self.scope_id.unwrap() - } - - fn make_and_insert_variable_symbol( - &self, - symbol_table: &mut SymbolTable, - ) -> Option { - let variable_symbol = Rc::new(VariableSymbol::new( - &self.declared_name, - &self.declared_name_source_range, - self.is_mut, - self.scope_id.unwrap(), - )); - try_insert_symbol_into(Symbol::Variable(variable_symbol), symbol_table).err() - } - - pub fn resolve_names_static( - &self, - symbol_table: &mut SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - let mut names_table = NodesToSymbols::new(); - let mut diagnostics = Diagnostics::new(); - - { - let (ns, mut ds) = self.initializer.resolve_names_static(symbol_table); - insert_resolved_names_into(ns, &mut names_table); - diagnostics.append(&mut ds); - } - - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - - (names_table, diagnostics) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut nodes_to_symbols = NodesToSymbols::new(); - let mut diagnostics = Diagnostics::new(); - - { - let (ns, mut ds) = self - .initializer - .resolve_names_ctor(symbol_table, self_class_symbol); - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - - (nodes_to_symbols, diagnostics) - } - - pub fn resolve_names_method( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - let mut nodes_to_symbols = NodesToSymbols::new(); - let mut diagnostics = Diagnostics::new(); - - { - let (ns, mut ds) = self - .initializer - .resolve_names_method(symbol_table, self_class_symbol); // todo - insert_resolved_names_into(ns, &mut nodes_to_symbols); - diagnostics.append(&mut ds); - } - - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - - (nodes_to_symbols, diagnostics) - } - - #[deprecated] - pub fn analyze_constructor_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - let mut diagnostics = Vec::new(); - diagnostics.append( - &mut self - .initializer - .check_constructor_local_names(symbol_table, class_symbol), - ); - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - - diagnostics - } - - #[deprecated] - pub fn analyze_method_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - let mut diagnostics = Vec::new(); - diagnostics.append( - &mut self - .initializer - .check_method_local_names(symbol_table, class_symbol), - ); - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - diagnostics - } - - #[deprecated] - pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec { - let mut diagnostics = Vec::new(); - diagnostics.append(&mut self.initializer.check_static_fn_local_names(symbol_table)); - if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) { - diagnostics.push(diagnostic); - } - diagnostics - } - - pub fn resolve_types( - &self, - resolved_symbols: &NodesToSymbols, - resolved_symbol_type_infos: &SymbolsToTypes, - ) -> (SymbolsToTypes, NodesToTypes, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - let mut resolved_types = NodesToTypes::new(); - - { - let (rts, mut ds) = self - .initializer - .resolve_types(resolved_symbols, resolved_symbol_type_infos); - insert_resolved_types_into(rts, &mut resolved_types); - diagnostics.append(&mut ds); - } - - let initializer_resolved_type = resolved_types.get(&self.initializer.node_id()).unwrap(); - let self_symbol = resolved_symbols.get(&self.node_id).unwrap(); - - let mut resolved_symbol_type_infos = resolved_symbol_type_infos.clone(); - resolved_symbol_type_infos.insert(self_symbol.clone(), initializer_resolved_type.clone()); - - (resolved_symbol_type_infos, resolved_types, diagnostics) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - self.initializer.type_check(symbol_table, types_table)?; - // TODO: this is wrong. We need to check assignability - let initializer_type_info = self - .initializer - .type_info(symbol_table, types_table) - .clone(); - let variable_symbol = symbol_table - .get_variable_symbol_owned(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - types_table - .variable_types_mut() - .insert(variable_symbol, initializer_type_info); - Ok(()) - } - - fn make_vr_variable(&self, builder: &mut IrBuilder, destination_type: &TypeInfo) -> IrVariable { - todo!() - } - - fn make_stack_variable( - &self, - builder: &mut IrBuilder, - destination_type: &TypeInfo, - offset: isize, - ) -> IrVariable { - todo!() - } - - pub fn get_destination_symbol(&self, symbol_table: &SymbolTable) -> Rc { - symbol_table - .get_variable_symbol_owned(self.scope_id.unwrap(), &self.declared_name) - .unwrap() - } - - pub fn to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) { - let init_operation = self - .initializer - .to_ir_operation(builder, symbol_table, types_table); - - let destination_symbol = self.get_destination_symbol(symbol_table); - - let destination_type = types_table - .variable_types() - .get(&destination_symbol) - .unwrap(); - - let destination_vr_variable = self.make_vr_variable(builder, destination_type); - - let as_rc = Rc::new(RefCell::new(destination_vr_variable)); - let ir_assign = IrAssign::new(todo!(), init_operation); - - builder - .local_variables_mut() - .insert(destination_symbol, as_rc.clone()); - - builder - .current_block_mut() - .add_statement(IrStatement::Assign(ir_assign)); - } - - pub fn to_repl_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - destination_stack_offset: isize, - ) -> Rc> { - let init_operation = self - .initializer - .to_ir_operation(builder, symbol_table, types_table); - let destination_symbol = self.get_destination_symbol(symbol_table); - let destination_type = types_table - .variable_types() - .get(&destination_symbol) - .unwrap(); - let destination_stack_variable = - self.make_stack_variable(builder, destination_type, destination_stack_offset); - let as_rc = Rc::new(RefCell::new(destination_stack_variable)); - let ir_assign = IrAssign::new(todo!(), init_operation); - // do not need to save variable to builder as a new one is created for each repl function - builder - .current_block_mut() - .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_symbols, - symbols_to_types, - 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(todo!())); - - // save local variable to builder - builder.local_variables_mut().insert( - destination_symbol.unwrap_variable_symbol().clone(), - vr_variable.clone(), - ); - - let ir_assign = IrAssign::new(todo!(), 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 e02dbb7..a9968e4 100644 --- a/dmc-lib/src/ast/mod.rs +++ b/dmc-lib/src/ast/mod.rs @@ -1,9 +1,3 @@ -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; pub mod call; @@ -15,16 +9,10 @@ pub mod expression; pub mod expression_statement; pub mod extern_function; pub mod field; -pub mod fqn; -pub mod fqn_context; -pub mod fqn_util; pub mod function; pub mod generic_parameter; -mod helpers; pub mod identifier; pub mod integer_literal; -pub mod ir_builder; -pub(crate) mod ir_util; pub mod let_statement; pub mod negative_expression; pub mod parameter; @@ -33,7 +21,3 @@ pub mod string_literal; pub mod type_use; 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 97c009a..52e0e7f 100644 --- a/dmc-lib/src/ast/negative_expression.rs +++ b/dmc-lib/src/ast/negative_expression.rs @@ -1,27 +1,11 @@ +use crate::ast::NodeId; use crate::ast::expression::Expression; -use crate::ast::ir_builder::IrBuilder; -use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostic_factories::unary_incompatible_type; -use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator}; -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::class_symbol::ClassSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::cell::RefCell; -use std::rc::Rc; pub struct NegativeExpression { node_id: NodeId, operand: Box, source_range: SourceRange, - type_info: Option, } impl NegativeExpression { @@ -30,7 +14,6 @@ impl NegativeExpression { node_id, operand: operand.into(), source_range, - type_info: None, } } @@ -45,261 +28,4 @@ impl NegativeExpression { pub fn operand(&self) -> &Expression { &self.operand } - - pub fn operand_mut(&mut self) -> &mut Expression { - &mut self.operand - } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.operand.init_scopes(symbol_table, container_scope); - } - - pub fn resolve_names_static( - &self, - symbol_table: &SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - self.operand.resolve_names_static(symbol_table) - } - - pub fn resolve_names_field_init( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - self.operand - .resolve_names_field_init(symbol_table, self_class_symbol) - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - self.operand - .resolve_names_ctor(symbol_table, self_class_symbol) - } - - pub fn resolve_names_method( - &self, - symbol_table: &SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - self.operand - .resolve_names_method(symbol_table, self_class_symbol) - } - - #[deprecated] - pub fn check_field_initializer_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.operand - .check_field_initializer_names(symbol_table, class_symbol) - } - - #[deprecated] - pub fn check_constructor_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.operand - .check_constructor_local_names(symbol_table, class_symbol) - } - - #[deprecated] - pub fn check_method_local_names( - &self, - symbol_table: &SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - self.operand - .check_method_local_names(symbol_table, class_symbol) - } - - #[deprecated] - pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec { - self.operand.check_static_fn_local_names(symbol_table) - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (NodesToTypes, Diagnostics) { - let (mut nodes_to_types, mut diagnostics) = self - .operand - .resolve_types(nodes_to_symbols, symbols_to_types); - - let type_info = nodes_to_types.get(&self.operand.node_id()).unwrap(); - if type_info.can_negate() { - nodes_to_types.insert(self.node_id, type_info.negate_result()); - } else { - diagnostics.push(unary_incompatible_type( - &self.source_range, - "negation", - type_info, - )); - nodes_to_types.insert(self.node_id, TypeInfo::PlaceholderError); - } - - (nodes_to_types, diagnostics) - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - self.operand.type_check(symbol_table, types_table)?; - - let type_info = self.operand.type_info(symbol_table, types_table); - if type_info.can_negate() { - self.type_info = Some(type_info.negate_result()); - Ok(()) - } else { - Err(vec![Diagnostic::new( - &format!("Cannot negate {}", type_info), - self.source_range.start(), - self.source_range.end(), - )]) - } - } - - 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(todo!())); - todo!() - // let rhs = match todo!() { - // 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) => { - let destination = Rc::new(RefCell::new(todo!())); - todo!() - // let rhs = match ir_variable.borrow().type_info() { - // TypeInfo::Integer => IrExpression::Int(-1), - // TypeInfo::Double => IrExpression::Double(-1.0), - // _ => panic!(), - // }; - // - // let operation = IrOperation::Binary(IrBinaryOperation::new( - // IrExpression::Variable(ir_variable), - // 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::Int(i) => IrExpression::Int(i * -1), - IrExpression::Double(d) => IrExpression::Double(d * -1.0), - IrExpression::String(_) => { - panic!(); - } - } - } - - #[deprecated] - pub fn to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> IrExpression { - let operand_as_ir = self - .operand - .to_ir_expression(builder, symbol_table, types_table) - .expect("Attempt to negate non-value expression"); - - match operand_as_ir { - IrExpression::Parameter(parameter) => { - let destination = Rc::new(RefCell::new(todo!())); - todo!() - // let rhs = match todo!() { - // TypeInfo::Integer => IrExpression::Int(-1), - // TypeInfo::Double => IrExpression::Double(-1.0), - // _ => panic!("Trying to multiply with a non-integer/double"), - // }; - // - // let operation = IrOperation::Binary(IrBinaryOperation::new( - // IrExpression::Parameter(parameter), - // rhs, - // IrBinaryOperator::Multiply, - // )); - // - // let assign = IrAssign::new(destination.clone(), operation); - // builder - // .current_block_mut() - // .add_statement(IrStatement::Assign(assign)); - // - // IrExpression::Variable(destination) - } - IrExpression::Variable(variable) => { - let destination = Rc::new(RefCell::new(todo!())); - todo!() - // let rhs = match variable.borrow().type_info() { - // TypeInfo::Integer => IrExpression::Int(-1), - // TypeInfo::Double => IrExpression::Double(-1.0), - // _ => panic!("Trying to multiply with a non-integer/double"), - // }; - // - // let operation = IrOperation::Binary(IrBinaryOperation::new( - // IrExpression::Variable(variable), - // rhs, - // IrBinaryOperator::Multiply, - // )); - // - // let assign = IrAssign::new(destination.clone(), operation); - // builder - // .current_block_mut() - // .add_statement(IrStatement::Assign(assign)); - // - // IrExpression::Variable(destination) - } - IrExpression::Int(i) => IrExpression::Int(i * -1), - IrExpression::Double(d) => IrExpression::Double(d * -1.0), - IrExpression::String(_) => { - panic!("Attempt to negate IrExpression::String") - } - } - } - - pub fn type_info(&self) -> &TypeInfo { - self.type_info.as_ref().unwrap() - } } diff --git a/dmc-lib/src/ast/parameter.rs b/dmc-lib/src/ast/parameter.rs index 10fadf9..4e26271 100644 --- a/dmc-lib/src/ast/parameter.rs +++ b/dmc-lib/src/ast/parameter.rs @@ -1,11 +1,6 @@ +use crate::ast::NodeId; use crate::ast::type_use::TypeUse; -use crate::ast::{NodeId, NodesToSymbols}; -use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::source_range::SourceRange; -use crate::symbol::parameter_symbol::ParameterSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; use std::rc::Rc; pub struct Parameter { @@ -13,7 +8,6 @@ pub struct Parameter { declared_name: Rc, declared_name_source_range: SourceRange, type_use: TypeUse, - scope_id: Option, } impl Parameter { @@ -28,7 +22,6 @@ impl Parameter { declared_name: declared_name.into(), declared_name_source_range, type_use, - scope_id: None, } } @@ -51,54 +44,4 @@ impl Parameter { pub fn type_use(&self) -> &TypeUse { &self.type_use } - - pub fn scope_id(&self) -> usize { - self.scope_id.unwrap() - } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - self.type_use.init_scopes(symbol_table, container_scope); - } - - pub fn make_symbol(&self) -> ParameterSymbol { - ParameterSymbol::new( - &self.declared_name, - Some(self.declared_name_source_range.clone()), - self.scope_id.unwrap(), - ) - } - - pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) { - self.type_use.resolve_names(symbol_table) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - self.type_use.check_names(symbol_table) - } - - #[deprecated] - pub fn gather_types_into(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) { - let type_info = self.type_use.type_info(symbol_table, types_table).clone(); - let parameter_symbol = symbol_table - .get_parameter_symbol_owned(self.scope_id.unwrap(), &self.declared_name) - .unwrap(); - types_table - .parameter_types_mut() - .insert(parameter_symbol, type_info); - } - - pub fn declared_type(&self, names_table: &NodesToSymbols) -> (TypeInfo, Diagnostics) { - self.type_use.declared_type(names_table) - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - self.type_use.type_check(symbol_table, types_table)?; - Ok(()) - } } diff --git a/dmc-lib/src/ast/statement.rs b/dmc-lib/src/ast/statement.rs index b4a0610..da2047e 100644 --- a/dmc-lib/src/ast/statement.rs +++ b/dmc-lib/src/ast/statement.rs @@ -1,233 +1,9 @@ use crate::ast::assign_statement::AssignStatement; use crate::ast::expression_statement::ExpressionStatement; -use crate::ast::ir_builder::IrBuilder; use crate::ast::let_statement::LetStatement; -use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::symbol::class_symbol::ClassSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use std::collections::HashSet; -use std::rc::Rc; pub enum Statement { Let(LetStatement), Expression(ExpressionStatement), Assign(AssignStatement), } - -impl Statement { - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - match self { - Statement::Let(let_statement) => { - let_statement.init_scopes(symbol_table, container_scope); - } - Statement::Expression(expression_statement) => { - expression_statement.init_scopes(symbol_table, container_scope); - } - Statement::Assign(assign_statement) => { - assign_statement.init_scopes(symbol_table, container_scope); - } - } - } - - pub fn resolve_names_static( - &self, - symbol_table: &mut SymbolTable, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Statement::Let(let_statement) => let_statement.resolve_names_static(symbol_table), - Statement::Expression(expression_statement) => { - expression_statement.resolve_names_static(symbol_table) - } - Statement::Assign(assign_statement) => { - assign_statement.resolve_names_static(symbol_table) - } - } - } - - pub fn resolve_names_ctor( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - initialized_fields: &mut HashSet>, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Statement::Let(let_statement) => { - let_statement.resolve_names_ctor(symbol_table, self_class_symbol) - } - Statement::Expression(expression_statement) => { - expression_statement.resolve_names_ctor(symbol_table, self_class_symbol) - } - Statement::Assign(assign_statement) => assign_statement.resolve_names_ctor( - symbol_table, - self_class_symbol, - initialized_fields, - ), - } - } - - pub fn resolve_names_method( - &self, - symbol_table: &mut SymbolTable, - self_class_symbol: &ClassSymbol, - ) -> (NodesToSymbols, Diagnostics) { - match self { - Statement::Let(let_statement) => { - let_statement.resolve_names_method(symbol_table, self_class_symbol) - } - Statement::Expression(expression_statement) => { - expression_statement.resolve_names_method(symbol_table, self_class_symbol) - } - Statement::Assign(assign_statement) => { - assign_statement.resolve_names_method(symbol_table, self_class_symbol) - } - } - } - - #[deprecated] - pub fn analyze_constructor_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Statement::Let(let_statement) => { - let_statement.analyze_constructor_local_names(symbol_table, class_symbol) - } - Statement::Expression(expression_statement) => { - expression_statement.check_constructor_local_names(symbol_table, class_symbol) - } - Statement::Assign(assign_statement) => { - assign_statement.check_constructor_local_names(symbol_table, class_symbol) - } - } - } - - #[deprecated] - pub fn analyze_method_local_names( - &self, - symbol_table: &mut SymbolTable, - class_symbol: &ClassSymbol, - ) -> Vec { - match self { - Statement::Let(let_statement) => { - let_statement.analyze_method_local_names(symbol_table, class_symbol) - } - Statement::Expression(expression_statement) => { - expression_statement.check_method_local_names(symbol_table, class_symbol) - } - Statement::Assign(assign_statement) => { - assign_statement.check_method_local_names(symbol_table, class_symbol) - } - } - } - - #[deprecated] - pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec { - match self { - Statement::Let(let_statement) => { - let_statement.analyze_static_fn_local_names(symbol_table) - } - Statement::Expression(expression_statement) => { - expression_statement.check_static_fn_local_names(symbol_table) - } - Statement::Assign(assign_statement) => { - assign_statement.check_static_fn_local_names(symbol_table) - } - } - } - - pub fn resolve_types( - &self, - nodes_to_symbols: &NodesToSymbols, - symbols_to_types: &SymbolsToTypes, - ) -> (SymbolsToTypes, NodesToTypes, Diagnostics) { - match self { - Statement::Let(let_statement) => { - let_statement.resolve_types(nodes_to_symbols, symbols_to_types) - } - Statement::Expression(expression_statement) => { - let (nts, ds) = - expression_statement.resolve_types(nodes_to_symbols, symbols_to_types); - (SymbolsToTypes::new(), nts, ds) - } - Statement::Assign(assign_statement) => { - let (nts, ds) = assign_statement.resolve_types(nodes_to_symbols, symbols_to_types); - (SymbolsToTypes::new(), nts, ds) - } - } - } - - #[deprecated] - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - must_return_type_info: Option<&TypeInfo>, - ) -> Result<(), Vec> { - match self { - Statement::Let(let_statement) => let_statement.type_check(symbol_table, types_table), - Statement::Expression(expression_statement) => { - expression_statement.type_check(symbol_table, types_table, must_return_type_info) - } - Statement::Assign(assign_statement) => { - assign_statement.type_check(symbol_table, types_table) - } - } - } - - #[deprecated] - pub fn to_ir( - &self, - builder: &mut IrBuilder, - symbol_table: &SymbolTable, - types_table: &TypesTable, - should_return_value: bool, - ) { - match self { - Statement::Let(let_statement) => { - let_statement.to_ir(builder, symbol_table, types_table); - } - Statement::Expression(expression_statement) => { - expression_statement.to_ir(builder, symbol_table, types_table, should_return_value); - } - Statement::Assign(assign_statement) => { - assign_statement.to_ir(builder, symbol_table, types_table); - } - } - } - - pub fn lower_to_ir( - &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) => { - expression_statement.lower_to_ir( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - is_return_statement, - ); - } - Statement::Assign(assign_statement) => { - assign_statement.lower_to_ir( - builder, - nodes_to_symbols, - symbols_to_types, - nodes_to_types, - ); - } - } - } -} diff --git a/dmc-lib/src/ast/type_use.rs b/dmc-lib/src/ast/type_use.rs index e124525..e361b53 100644 --- a/dmc-lib/src/ast/type_use.rs +++ b/dmc-lib/src/ast/type_use.rs @@ -1,14 +1,5 @@ -use crate::ast::{NodeId, NodesToSymbols}; -use crate::diagnostic::{Diagnostic, Diagnostics}; -use crate::diagnostic_factories::{cannot_provide_generic_args_generic_type, symbol_not_found}; -use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS; +use crate::ast::NodeId; use crate::source_range::SourceRange; -use crate::symbol::type_symbol::TypeSymbol; -use crate::symbol_table::SymbolTable; -use crate::type_info::TypeInfo; -use crate::types_table::TypesTable; -use crate::{diagnostics_result, handle_diagnostics, maybe_return_diagnostics}; -use std::collections::HashMap; use std::rc::Rc; pub struct TypeUse { @@ -16,7 +7,6 @@ pub struct TypeUse { declared_name: Rc, declared_name_source_range: SourceRange, generic_arguments: Vec, - scope_id: Option, } impl TypeUse { @@ -31,7 +21,6 @@ impl TypeUse { declared_name: declared_name.into(), declared_name_source_range, generic_arguments, - scope_id: None, } } @@ -42,236 +31,4 @@ impl TypeUse { pub fn node_id(&self) -> NodeId { self.node_id } - - pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); - for type_use in &mut self.generic_arguments { - type_use.init_scopes(symbol_table, container_scope); - } - } - - pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) { - let mut diagnostics = Vec::new(); - let mut resolved_names = HashMap::new(); - - // resolve this name - match symbol_table.find_type_symbol(self.scope_id.unwrap(), &self.declared_name) { - None => { - diagnostics.push(symbol_not_found( - &self.declared_name, - &self.declared_name_source_range, - )); - } - Some(type_symbol) => { - resolved_names.insert(self.node_id, type_symbol.into_symbol()); - } - } - - // check generic args - for type_use in &self.generic_arguments { - let (ns, mut ds) = type_use.resolve_names(symbol_table); - for (node_id, symbol) in ns { - resolved_names.insert(node_id, symbol); - } - diagnostics.append(&mut ds); - } - - (resolved_names, diagnostics) - } - - #[deprecated] - pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics: Vec = Vec::new(); - - // find this name - let maybe_type_symbol = - symbol_table.find_type_symbol(self.scope_id.unwrap(), &self.declared_name); - if maybe_type_symbol.is_none() { - diagnostics.push(symbol_not_found( - self.declared_name(), - &self.declared_name_source_range, - )); - } - - // check generic args - for type_use in &self.generic_arguments { - diagnostics.append(&mut type_use.check_names(symbol_table)); - } - - diagnostics - } - - #[deprecated] - pub fn gather_types( - &self, - symbol_table: &SymbolTable, - types_table: &mut TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics = Vec::new(); - for type_use in &self.generic_arguments { - handle_diagnostics!( - type_use.gather_types(symbol_table, types_table), - diagnostics - ); - } - diagnostics_result!(diagnostics) - } - - pub fn declared_type(&self, names_table: &NodesToSymbols) -> (TypeInfo, Diagnostics) { - let mut diagnostics = Diagnostics::new(); - - let mut generic_argument_type_infos = Vec::new(); - for type_use in &self.generic_arguments { - let (type_info, mut ds) = type_use.declared_type(names_table); - generic_argument_type_infos.push(type_info); - diagnostics.append(&mut ds); - } - - let base_type_symbol = names_table.get(&self.node_id).unwrap().unwrap_type_symbol(); - - match base_type_symbol { - TypeSymbol::Class(class_symbol) => ( - TypeInfo::ParameterizedClass(class_symbol, generic_argument_type_infos), - diagnostics, - ), - TypeSymbol::GenericParameter(generic_parameter_symbol) => { - if generic_argument_type_infos.is_empty() { - (TypeInfo::GenericType(generic_parameter_symbol), diagnostics) - } else { - diagnostics.push(cannot_provide_generic_args_generic_type( - &self.declared_name_source_range, - )); - (TypeInfo::PlaceholderError, diagnostics) - } - } - } - } - - pub fn type_info<'a>( - &self, - symbol_table: &SymbolTable, - types_table: &'a TypesTable, - ) -> &'a TypeInfo { - let type_symbol = symbol_table - .find_type_symbol(self.scope_id.unwrap(), self.declared_name()) - .unwrap(); - match type_symbol { - TypeSymbol::Class(class_symbol) => { - types_table - .class_types() - .get(&class_symbol) - .expect(&format!( - "Could not get TypeInfo for {}", - self.declared_name - )) - } - TypeSymbol::GenericParameter(generic_parameter_symbol) => types_table - .generic_parameter_types() - .get(&generic_parameter_symbol) - .expect(&format!( - "Could not get TypeInfo for {}", - self.declared_name - )), - } - } - - pub fn type_check( - &mut self, - symbol_table: &SymbolTable, - types_table: &TypesTable, - ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - match self.type_info(symbol_table, types_table) { - TypeInfo::Class(class_symbol) => { - // check number of params/args match - let generic_parameters = class_symbol.generic_parameters(); - if generic_parameters.len() != self.generic_arguments.len() { - let diagnostic = Diagnostic::new( - &format!( - "Expected {} generic arguments; found {}.", - generic_parameters.len(), - self.generic_arguments.len() - ), - self.declared_name_source_range.start(), - self.declared_name_source_range.end(), - ) - .with_reporter(file!(), line!()) - .with_error_code(INCORRECT_GENERIC_ARGUMENTS); - diagnostics.push(diagnostic); - } - - maybe_return_diagnostics!(diagnostics); - - // check that each arg is assignable to the param's extends - // for i in 0..self.generic_arguments.len() { - // let generic_parameter_symbol = &generic_parameters[i]; - // if generic_parameter_symbol.extends().len() > 0 { - // unimplemented!("Generic extends not implemented yet.") - // } - // } - } - _ => { - // cannot extend a non-class type (except for Any) - if self.generic_arguments.len() > 0 { - let diagnostic = Diagnostic::new( - &format!( - "Type {} does not accept generic arguments.", - self.type_info(symbol_table, types_table) - ), - self.declared_name_source_range.start(), - self.declared_name_source_range.end(), - ) - .with_reporter(file!(), line!()) - .with_error_code(INCORRECT_GENERIC_ARGUMENTS); - diagnostics.push(diagnostic); - } - } - } - - // recurse on generic arguments - for generic_argument in &mut self.generic_arguments { - handle_diagnostics!( - generic_argument.type_check(symbol_table, types_table), - diagnostics - ); - } - - diagnostics_result!(diagnostics) - } -} - -#[cfg(test)] -mod tests { - use crate::diagnostic::Diagnostic; - use crate::parser::get_compilation_unit; - use crate::symbol_table::SymbolTable; - use crate::types_table::TypesTable; - - #[test] - fn type_check_generics() -> Result<(), Vec> { - let mut compilation_unit = get_compilation_unit( - " - class String end - - class Foo - ctor(t: T) end - end - - fn useFoo(foo: Foo) end - ", - None, - )?; - - let mut symbol_table = SymbolTable::new(); - let mut types_table = TypesTable::new(); - - compilation_unit.init_scopes(&mut symbol_table); - compilation_unit.gather_symbols_into(&mut symbol_table)?; - compilation_unit.check_names(&mut symbol_table)?; - compilation_unit.gather_types_into(&symbol_table, &mut types_table)?; - compilation_unit.type_check(&mut symbol_table, &mut types_table)?; - - Ok(()) - } } diff --git a/dmc-lib/src/compile_pipeline.rs b/dmc-lib/src/compile_pipeline.rs deleted file mode 100644 index d64cc94..0000000 --- a/dmc-lib/src/compile_pipeline.rs +++ /dev/null @@ -1,146 +0,0 @@ -use crate::ast::compilation_unit::CompilationUnit; -use crate::diagnostic::Diagnostics; -use crate::ir::ir_class::IrClass; -use crate::ir::ir_function::IrFunction; -use crate::parser::parse_compilation_unit; -use crate::symbol_table::SymbolTable; -use crate::symbol_table::util::try_insert_symbols_into; -use std::collections::HashMap; -use std::rc::Rc; - -pub type Filename = Rc; -pub type FileId = usize; - -fn parse_compilation_units( - inputs: &HashMap, -) -> Result, Diagnostics> { - let mut parse_diagnostics = Vec::new(); - let mut compilation_units = HashMap::new(); - for (file_id, source) in inputs { - let (compilation_unit, mut ds) = parse_compilation_unit(source, Some(*file_id)); - parse_diagnostics.append(&mut ds); - compilation_units.insert(*file_id, compilation_unit); - } - if parse_diagnostics.is_empty() { - Ok(compilation_units) - } else { - Err(parse_diagnostics) - } -} - -pub fn compile_compilation_units( - inputs: &HashMap, - symbol_table: &mut SymbolTable, -) -> Result<(Vec, Vec), Diagnostics> { - let mut compilation_units = parse_compilation_units(inputs)?; - - // init scopes - for compilation_unit in compilation_units.values_mut() { - compilation_unit.init_scopes(symbol_table); - } - - // gather unordered symbols - let all_symbols = compilation_units - .values() - .flat_map(|compilation_unit| compilation_unit.declared_symbols()) - .collect::>(); - try_insert_symbols_into(all_symbols, symbol_table)?; - - // now we can just finish each compilation unit, since we have the symbols - let mut ir_classes = Vec::new(); - let mut ir_functions = Vec::new(); - let mut diagnostics = Vec::new(); - for compilation_unit in compilation_units.values() { - let (nodes_to_symbols, mut ds) = compilation_unit.resolve_names(symbol_table); - - // in the future, we'll ideally be able to *actually* continue with the following steps - // instead of aborting here, but this needs to be tested :) - if !ds.is_empty() { - diagnostics.append(&mut ds); - continue; - } - - let (mut symbols_to_types, mut ds) = compilation_unit.declared_types(&nodes_to_symbols); - if !ds.is_empty() { - diagnostics.append(&mut ds); - continue; - } - - let (sts, nodes_to_types, mut ds) = - compilation_unit.resolve_types(&nodes_to_symbols, &symbols_to_types); - if !ds.is_empty() { - diagnostics.append(&mut ds); - continue; - } - - // merge - for (symbol, type_info) in sts { - symbols_to_types.insert(symbol, type_info); - } - - let (mut classes, mut functions) = - compilation_unit.lower_to_ir(&nodes_to_symbols, &symbols_to_types, &nodes_to_types); - ir_classes.append(&mut classes); - ir_functions.append(&mut functions); - } - - if diagnostics.is_empty() { - Ok((ir_classes, ir_functions)) - } else { - Err(diagnostics) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::symbol::class_symbol::ClassSymbol; - - fn prepare_symbol_table(symbol_table: &mut SymbolTable) { - let global_scope = symbol_table.push_module_scope("global scope"); - let any_symbol = ClassSymbol::new( - &"Any".into(), - None, - vec!["Any".into()], - false, - global_scope, - Vec::new(), - None, - Vec::new(), - Vec::new(), - ); - symbol_table.insert_class_symbol(Rc::new(any_symbol)); - - let void_symbol = ClassSymbol::new( - &"Void".into(), - None, - vec!["Void".into()], - false, - global_scope, - Vec::new(), - None, - Vec::new(), - Vec::new(), - ); - symbol_table.insert_class_symbol(Rc::new(void_symbol)); - } - - #[test] - fn hello_world() -> Result<(), Diagnostics> { - let input = " - extern fn println(msg: Any) -> Void - - fn main() - println(\"Hello, World!\") - end - "; - let mut inputs = HashMap::new(); - inputs.insert(0, input); - let mut symbol_table = SymbolTable::new(); - prepare_symbol_table(&mut symbol_table); - let (ir_classes, ir_functions) = compile_compilation_units(&inputs, &mut symbol_table)?; - assert_eq!(ir_classes.len(), 0); - assert_eq!(ir_functions.len(), 1); - Ok(()) - } -} diff --git a/dmc-lib/src/ast/fqn_util.rs b/dmc-lib/src/fqn_util.rs similarity index 100% rename from dmc-lib/src/ast/fqn_util.rs rename to dmc-lib/src/fqn_util.rs diff --git a/dmc-lib/src/ir/ir_class.rs b/dmc-lib/src/ir/ir_class.rs index b5c13fe..58cf76d 100644 --- a/dmc-lib/src/ir/ir_class.rs +++ b/dmc-lib/src/ir/ir_class.rs @@ -1,4 +1,4 @@ -use crate::ast::fqn_util::fqn_parts_to_string; +use crate::fqn_util::fqn_parts_to_string; use crate::type_info::TypeInfo; use dvm_lib::vm::class::{Class, Field}; use dvm_lib::vm::type_info::TypeInfo as VmTypeInfo; diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index ae5d1b1..9d861d7 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -14,11 +14,11 @@ use std::collections::HashMap; use std::rc::Rc; pub mod ast; -pub mod compile_pipeline; pub mod constants_table; pub mod diagnostic; mod diagnostic_factories; pub mod error_codes; +pub mod fqn_util; pub mod intrinsics; pub mod ir; pub mod lexer; diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index 1beb902..639c4be 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -1,3 +1,4 @@ +use crate::FileId; use crate::ast::assign_statement::AssignStatement; use crate::ast::binary_expression::{BinaryExpression, BinaryOperation}; use crate::ast::call::Call; @@ -19,7 +20,6 @@ use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::ast::string_literal::StringLiteral; use crate::ast::type_use::TypeUse; -use crate::compile_pipeline::FileId; use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::error_codes::{LEXER_ERROR, PARSE_ERROR}; use crate::lexer::{Lexer, LexerErrorKind}; @@ -988,7 +988,7 @@ impl<'a> Parser<'a> { (Statement::Assign(assign_statement), diagnostics) } else { ( - Statement::Expression(ExpressionStatement::new(self.next_node_id(), base)), + Statement::Expression(ExpressionStatement::new(base)), diagnostics, ) } diff --git a/dmc-lib/src/symbol/class_symbol.rs b/dmc-lib/src/symbol/class_symbol.rs index 98bfa1c..e4e51ec 100644 --- a/dmc-lib/src/symbol/class_symbol.rs +++ b/dmc-lib/src/symbol/class_symbol.rs @@ -1,4 +1,4 @@ -use crate::ast::fqn_util::fqn_parts_to_string; +use crate::fqn_util::fqn_parts_to_string; use crate::source_range::SourceRange; use crate::symbol::constructor_symbol::ConstructorSymbol; use crate::symbol::field_symbol::FieldSymbol; diff --git a/dmc-lib/src/symbol/function_symbol.rs b/dmc-lib/src/symbol/function_symbol.rs index f092bf3..c9cc641 100644 --- a/dmc-lib/src/symbol/function_symbol.rs +++ b/dmc-lib/src/symbol/function_symbol.rs @@ -1,4 +1,4 @@ -use crate::ast::fqn_util::fqn_parts_to_string; +use crate::fqn_util::fqn_parts_to_string; use crate::source_range::SourceRange; use crate::symbol::parameter_symbol::ParameterSymbol; use std::fmt::{Debug, Formatter};