From 0b270c186bb17c533c6310a2739223e69164291b Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 21 May 2026 17:06:43 -0500 Subject: [PATCH] WIP. --- dmc-lib/src/ast/compilation_unit.rs | 19 +++++--- dmc-lib/src/ast/extern_function.rs | 19 +++++++- dmc-lib/src/ast/function.rs | 6 +++ dmc-lib/src/ast/identifier.rs | 8 ++-- dmc-lib/src/compile_pipeline.rs | 69 ++++++++++++++++++++++++++--- 5 files changed, 105 insertions(+), 16 deletions(-) diff --git a/dmc-lib/src/ast/compilation_unit.rs b/dmc-lib/src/ast/compilation_unit.rs index 16a3f9e..ebd20de 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -159,17 +159,26 @@ impl CompilationUnit { } /// Associate each declared symbol with a TypeInfo. - pub fn declared_types(&self, names_table: &NodesToSymbols) -> (SymbolsToTypes, Diagnostics) { + pub fn declared_types( + &self, + nodes_to_symbols: &NodesToSymbols, + ) -> (SymbolsToTypes, Diagnostics) { let mut diagnostics = Diagnostics::new(); - let mut declared_types = SymbolsToTypes::new(); + let mut symbols_to_types = SymbolsToTypes::new(); for function in &self.functions { - let (dts, mut ds) = function.declared_types(names_table); - insert_declared_types_into(dts, &mut declared_types); + let (sts, mut ds) = function.declared_types(nodes_to_symbols); + insert_declared_types_into(sts, &mut symbols_to_types); diagnostics.append(&mut ds); } - (declared_types, diagnostics) + 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 diff --git a/dmc-lib/src/ast/extern_function.rs b/dmc-lib/src/ast/extern_function.rs index 8480f0b..b89bdde 100644 --- a/dmc-lib/src/ast/extern_function.rs +++ b/dmc-lib/src/ast/extern_function.rs @@ -4,7 +4,7 @@ use crate::ast::helpers::{ }; use crate::ast::parameter::Parameter; use crate::ast::type_use::TypeUse; -use crate::ast::{NodeId, NodesToSymbols}; +use crate::ast::{NodeId, NodesToSymbols, SymbolsToTypes}; use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::source_range::SourceRange; use crate::symbol::Symbol; @@ -105,6 +105,23 @@ impl ExternFunction { (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 { diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 1dba1d4..f63d167 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -150,6 +150,12 @@ impl Function { 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) } diff --git a/dmc-lib/src/ast/identifier.rs b/dmc-lib/src/ast/identifier.rs index 4b59564..e554b23 100644 --- a/dmc-lib/src/ast/identifier.rs +++ b/dmc-lib/src/ast/identifier.rs @@ -512,11 +512,11 @@ impl Identifier { pub fn resolve_type( &self, - resolved_symbols: &NodesToSymbols, - resolved_symbol_type_infos: &SymbolsToTypes, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, ) -> (NodesToTypes, Diagnostics) { - let self_symbol = resolved_symbols.get(&self.node_id).unwrap(); - let type_info = resolved_symbol_type_infos.get(self_symbol).unwrap(); + 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()); diff --git a/dmc-lib/src/compile_pipeline.rs b/dmc-lib/src/compile_pipeline.rs index cbcda21..d64cc94 100644 --- a/dmc-lib/src/compile_pipeline.rs +++ b/dmc-lib/src/compile_pipeline.rs @@ -30,14 +30,13 @@ fn parse_compilation_units( pub fn compile_compilation_units( inputs: &HashMap, + symbol_table: &mut SymbolTable, ) -> Result<(Vec, Vec), Diagnostics> { let mut compilation_units = parse_compilation_units(inputs)?; - let mut symbol_table = SymbolTable::new(); - // init scopes for compilation_unit in compilation_units.values_mut() { - compilation_unit.init_scopes(&mut symbol_table); + compilation_unit.init_scopes(symbol_table); } // gather unordered symbols @@ -45,14 +44,14 @@ pub fn compile_compilation_units( .values() .flat_map(|compilation_unit| compilation_unit.declared_symbols()) .collect::>(); - try_insert_symbols_into(all_symbols, &mut symbol_table)?; + 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(&mut symbol_table); + 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 :) @@ -85,5 +84,63 @@ pub fn compile_compilation_units( ir_functions.append(&mut functions); } - Ok((ir_classes, ir_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(()) + } }