From 01df9a708f78fb4e01474016d8a068d6f809ae54 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 25 Jun 2026 14:49:32 -0500 Subject: [PATCH] Complete sketch of interface between dmc-lib compile functions and other modules. --- dmc-lib/src/ir/assemble.rs | 4 +- dmc-lib/src/ir/ir_function.rs | 2 + dmc-lib/src/ir/mod.rs | 43 ++++++++++ dmc-lib/src/lib.rs | 52 ++++++++++++ dmc-lib/src/semantic_analysis/mod.rs | 114 +++++++++------------------ e2e-tests/src/lib.rs | 60 ++------------ 6 files changed, 144 insertions(+), 131 deletions(-) diff --git a/dmc-lib/src/ir/assemble.rs b/dmc-lib/src/ir/assemble.rs index 545aa74..ae69801 100644 --- a/dmc-lib/src/ir/assemble.rs +++ b/dmc-lib/src/ir/assemble.rs @@ -19,7 +19,7 @@ use dvm_lib::instruction::{ use std::collections::HashMap; struct FunctionAssemblyContext<'a> { - type_infos: &'a Vec, + type_infos: &'a [IrTypeInfo], variables_to_type_infos: &'a HashMap, variable_locations: &'a VariableLocations, parameters: &'a [IrParameter], @@ -29,7 +29,7 @@ struct FunctionAssemblyContext<'a> { pub fn assemble_ir_function( ir_function: &IrFunction, - type_infos: &Vec, + type_infos: &[IrTypeInfo], variables_to_type_infos: &HashMap, variable_locations: &VariableLocations, constants_table: &mut ConstantsTable, diff --git a/dmc-lib/src/ir/ir_function.rs b/dmc-lib/src/ir/ir_function.rs index 048d818..fdd37eb 100644 --- a/dmc-lib/src/ir/ir_function.rs +++ b/dmc-lib/src/ir/ir_function.rs @@ -55,6 +55,7 @@ impl IrFunction { self.return_type_info.as_ref() } + #[deprecated] pub fn assign_registers(&self, register_count: usize) -> VariableLocations { if self.blocks.is_empty() { return VariableLocations::new(HashMap::new(), HashMap::new()); @@ -66,6 +67,7 @@ impl IrFunction { block_assign_registers(block, register_count) } + #[deprecated] pub fn assemble( &self, type_infos: &Vec, diff --git a/dmc-lib/src/ir/mod.rs b/dmc-lib/src/ir/mod.rs index a4ea96f..2a9c61a 100644 --- a/dmc-lib/src/ir/mod.rs +++ b/dmc-lib/src/ir/mod.rs @@ -1,3 +1,13 @@ +use crate::constants_table::ConstantsTable; +use crate::ir::assemble::assemble_ir_function; +use crate::ir::ir_function::IrFunction; +use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId}; +use crate::ir::ir_variable::IrVariableId; +use crate::ir::register_allocation::block_assign_registers; +use crate::ir::variable_locations::VariableLocations; +use dvm_lib::vm::function::Function; +use std::collections::HashMap; + mod assemble; mod debug_print; pub mod ir_allocate; @@ -22,3 +32,36 @@ pub mod ir_variable; mod register_allocation; mod util; mod variable_locations; + +pub fn compile_dvm_function( + ir_function: &IrFunction, + ir_type_infos: &[IrTypeInfo], + ir_variables_to_ir_type_infos: &HashMap, + constants_table: &mut ConstantsTable, +) -> Function { + let variable_locations = assign_registers(ir_function); + let instructions = assemble_ir_function( + ir_function, + ir_type_infos, + ir_variables_to_ir_type_infos, + &variable_locations, + constants_table, + ); + Function::new( + ir_function.fqn().into(), + ir_function.parameters().len(), + variable_locations.stack_size(), + instructions, + ) +} + +fn assign_registers(ir_function: &IrFunction) -> VariableLocations { + if ir_function.blocks().is_empty() { + return VariableLocations::new(HashMap::new(), HashMap::new()); + } + if ir_function.blocks().len() > 1 { + unimplemented!("having more than one block in a function is not yet implemented.") + } + let block = &ir_function.blocks()[0]; + block_assign_registers(block, 16) // TODO: make this configurable +} diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index 5434c73..c0bcaa2 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -1,3 +1,13 @@ +use crate::constants_table::ConstantsTable; +use crate::diagnostic::Diagnostics; +use crate::ir::compile_dvm_function; +use crate::lowering::lower_to_ir; +use crate::parser::parse_compilation_unit; +use crate::semantic_analysis::analyze_compilation_unit; +use dvm_lib::vm::function::Function; +use std::collections::HashMap; +use std::rc::Rc; + pub mod ast; pub mod compile_pipeline; pub mod constants_table; @@ -19,3 +29,45 @@ pub mod token; pub mod type_info; pub mod types_table; mod util; + +pub type Filename = Rc; +pub type FileId = usize; + +pub struct CompileCompilationUnitResult { + pub functions: HashMap, Function>, +} + +pub fn compile_compilation_unit( + input: &str, + constants_table: &mut ConstantsTable, +) -> Result { + let (compilation_unit, diagnostics) = parse_compilation_unit(input, None); + if !diagnostics.is_empty() { + return Err(diagnostics); + } + + let (analysis_result, diagnostics) = analyze_compilation_unit(&compilation_unit); + if !diagnostics.is_empty() { + return Err(diagnostics); + } + + let lower_to_ir_result = lower_to_ir( + &compilation_unit, + &analysis_result.symbols, + &analysis_result.nodes_to_symbols, + &analysis_result.type_infos, + &analysis_result.symbols_to_type_infos, + &analysis_result.nodes_to_type_infos, + ); + + let mut dvm_functions = HashMap::new(); + + for ir_function in &lower_to_ir_result.functions { + let dvm_function = compile_dvm_function(ir_function, todo!(), todo!(), constants_table); + dvm_functions.insert(dvm_function.name_owned(), dvm_function); + } + + Ok(CompileCompilationUnitResult { + functions: dvm_functions, + }) +} diff --git a/dmc-lib/src/semantic_analysis/mod.rs b/dmc-lib/src/semantic_analysis/mod.rs index 2e84180..531e629 100644 --- a/dmc-lib/src/semantic_analysis/mod.rs +++ b/dmc-lib/src/semantic_analysis/mod.rs @@ -1,13 +1,11 @@ use crate::ast::NodeId; use crate::ast::compilation_unit::CompilationUnit; -use crate::compile_pipeline::FileId; use crate::diagnostic::Diagnostics; use crate::semantic_analysis::collect_scopes::collect_scopes; use crate::semantic_analysis::collect_symbols::collect_symbols; use crate::semantic_analysis::collect_types::collect_types; use crate::semantic_analysis::resolve_names::resolve_names; use crate::semantic_analysis::resolve_types::resolve_types; -use crate::semantic_analysis::scope::{Scope, ScopeId}; use crate::semantic_analysis::symbol::{Symbol, SymbolId}; use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId}; use std::collections::HashMap; @@ -24,89 +22,53 @@ pub mod symbol; pub mod type_info; pub struct AnalysisResult { + pub symbols: Vec, + pub nodes_to_symbols: HashMap, pub type_infos: Vec, + pub symbols_to_type_infos: HashMap, pub nodes_to_type_infos: HashMap, } -pub fn analyze( - compilation_units: &HashMap, -) -> HashMap { +pub fn analyze_compilation_unit( + compilation_unit: &CompilationUnit, +) -> (AnalysisResult, Diagnostics) { let mut diagnostics = Diagnostics::new(); - let mut files_to_scopes: HashMap> = HashMap::new(); - let mut files_to_nodes_to_scopes: HashMap> = HashMap::new(); + let mut scopes_result = collect_scopes(compilation_unit); - for (file_id, compilation_unit) in compilation_units { - let result = collect_scopes(compilation_unit); - files_to_scopes.insert(*file_id, result.scopes); - files_to_nodes_to_scopes.insert(*file_id, result.nodes_to_scopes); - } + let mut symbols_result = collect_symbols( + compilation_unit, + &mut scopes_result.scopes, + &scopes_result.nodes_to_scopes, + ); + diagnostics.append(&mut symbols_result.diagnostics); - let mut files_to_symbols: HashMap> = HashMap::new(); + let mut names_result = resolve_names( + compilation_unit, + &mut scopes_result.scopes, + &mut symbols_result.symbols, + &scopes_result.nodes_to_scopes, + ); + diagnostics.append(&mut names_result.diagnostics); - for (file_id, compilation_unit) in compilation_units { - let scopes = files_to_scopes.get_mut(file_id).unwrap(); - let nodes_to_scopes = files_to_nodes_to_scopes.get(file_id).unwrap(); - let mut result = collect_symbols(compilation_unit, scopes, nodes_to_scopes); - files_to_symbols.insert(*file_id, result.symbols); - diagnostics.append(&mut result.diagnostics); - } + let mut collect_types_result = collect_types(compilation_unit, &names_result.nodes_to_symbols); - let mut files_to_nodes_to_symbols: HashMap> = HashMap::new(); + let mut resolve_types_result = resolve_types( + compilation_unit, + &names_result.nodes_to_symbols, + &mut collect_types_result.type_infos, + &mut collect_types_result.symbols_to_type_infos, + ); + diagnostics.append(&mut resolve_types_result.diagnostics); - for (file_id, compilation_unit) in compilation_units { - let scopes = files_to_scopes.get_mut(file_id).unwrap(); - let symbols = files_to_symbols.get_mut(file_id).unwrap(); - let nodes_to_scopes = files_to_nodes_to_scopes.get(file_id).unwrap(); - - let mut result = resolve_names(compilation_unit, scopes, symbols, nodes_to_scopes); - - files_to_nodes_to_symbols.insert(*file_id, result.nodes_to_symbols); - diagnostics.append(&mut result.diagnostics); - } - - let mut files_to_type_infos: HashMap> = HashMap::new(); - let mut files_to_symbols_to_type_infos: HashMap> = - HashMap::new(); - - for (file_id, compilation_unit) in compilation_units { - let nodes_to_symbols = files_to_nodes_to_symbols.get(&file_id).unwrap(); - let result = collect_types(compilation_unit, nodes_to_symbols); - - files_to_type_infos.insert(*file_id, result.type_infos); - files_to_symbols_to_type_infos.insert(*file_id, result.symbols_to_type_infos); - } - - let mut files_to_nodes_to_type_infos: HashMap> = - HashMap::new(); - - for (file_id, compilation_unit) in compilation_units { - let nodes_to_symbols = files_to_nodes_to_symbols.get_mut(file_id).unwrap(); - let type_infos = files_to_type_infos.get_mut(file_id).unwrap(); - let symbols_to_type_infos = files_to_symbols_to_type_infos.get_mut(file_id).unwrap(); - - let mut result = resolve_types( - compilation_unit, - nodes_to_symbols, - type_infos, - symbols_to_type_infos, - ); - - files_to_nodes_to_type_infos.insert(*file_id, result.nodes_to_type_infos); - diagnostics.append(&mut result.diagnostics); - } - - let mut files_to_results: HashMap = HashMap::new(); - - for (file_id, _) in compilation_units { - let type_infos = files_to_type_infos.remove(file_id).unwrap(); - let nodes_to_type_infos = files_to_nodes_to_type_infos.remove(file_id).unwrap(); - let analysis_result = AnalysisResult { - type_infos, - nodes_to_type_infos, - }; - files_to_results.insert(*file_id, analysis_result); - } - - files_to_results + ( + AnalysisResult { + symbols: symbols_result.symbols, + nodes_to_symbols: names_result.nodes_to_symbols, + type_infos: collect_types_result.type_infos, + symbols_to_type_infos: collect_types_result.symbols_to_type_infos, + nodes_to_type_infos: resolve_types_result.nodes_to_type_infos, + }, + diagnostics, + ) } diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index e755890..c43843b 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -1,20 +1,14 @@ #[cfg(test)] mod e2e_tests { + use dmc_lib::compile_compilation_unit; use dmc_lib::constants_table::ConstantsTable; - use dmc_lib::diagnostic::Diagnostic; - use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types}; - use dmc_lib::offset_counter::OffsetCounter; - use dmc_lib::parser::parse_compilation_unit; - use dmc_lib::symbol_table::SymbolTable; - use dmc_lib::types_table::TypesTable; - use dvm_lib::vm::class::Class; + use dmc_lib::diagnostic::{Diagnostic, Diagnostics}; use dvm_lib::vm::constant::{Constant, StringConstant}; - use dvm_lib::vm::function::Function; use dvm_lib::vm::value::Value; use dvm_lib::vm::{DvmContext, call}; use std::rc::Rc; - const REGISTER_COUNT: usize = 8; + const REGISTER_COUNT: usize = 16; fn report_diagnostics(diagnostics: &[Diagnostic]) -> ! { eprintln!( @@ -28,55 +22,15 @@ mod e2e_tests { panic!("There were diagnostics."); } - fn prepare_context(input: &str) -> Result> { - let (mut compilation_unit, diagnostics) = parse_compilation_unit(input, None); - if !diagnostics.is_empty() { - return Err(diagnostics); - } - - let mut symbol_table = SymbolTable::new(); - symbol_table.push_module_scope("global_scope"); - insert_intrinsic_symbols(&mut symbol_table); - - let mut types_table = TypesTable::new(); - insert_intrinsic_types(&symbol_table, &mut types_table); - - 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(&symbol_table, &mut types_table)?; - - let (ir_classes, mut ir_functions) = compilation_unit.to_ir(&symbol_table, &types_table); - - let mut functions: Vec = vec![]; + fn prepare_context(input: &str) -> Result { let mut constants_table = ConstantsTable::new(); - for ir_function in &mut ir_functions { - let mut offset_counter = OffsetCounter::new(); - ir_function.assign_registers(REGISTER_COUNT, &mut offset_counter); - let stack_size = offset_counter.get_count(); - let function = ir_function.assemble(stack_size, &mut constants_table); - functions.push(function); - } - - let mut classes: Vec = vec![]; - for ir_class in &ir_classes { - classes.push(ir_class.to_vm_class()); - } + let compile_compilation_unit_result = compile_compilation_unit(input, &mut constants_table); let mut dvm_context = DvmContext::new(); - for class in classes { - dvm_context - .classes_mut() - .insert(class.fqn().into(), Rc::new(class)); - } - - for function in functions { - dvm_context - .functions_mut() - .insert(function.name_owned(), function); + for (name, function) in compile_compilation_unit_result?.functions { + dvm_context.functions_mut().insert(name, function); } for (name, content) in &constants_table.string_constants() {