From 1bd1e5c23a614308d5e5179a19416004446550ad Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 1 May 2026 14:53:01 -0500 Subject: [PATCH] Work on classes and lowering to IR. WIP. --- dmc-lib/src/ast/class.rs | 46 +++++++++++++++++++++++- dmc-lib/src/ast/compilation_unit.rs | 16 +++++++-- dmc-lib/src/ast/field.rs | 20 ++++++++++- dmc-lib/src/ast/function.rs | 32 ++++++++++++----- dmc-lib/src/ast/parameter.rs | 2 +- dmc-lib/src/parser.rs | 1 + dmc-lib/src/symbol/expressible_symbol.rs | 2 +- dmc-lib/src/symbol/mod.rs | 18 ++++++++-- dmc-lib/src/symbol/parameter_symbol.rs | 9 +++-- 9 files changed, 124 insertions(+), 22 deletions(-) diff --git a/dmc-lib/src/ast/class.rs b/dmc-lib/src/ast/class.rs index 8b735c2..673ffa8 100644 --- a/dmc-lib/src/ast/class.rs +++ b/dmc-lib/src/ast/class.rs @@ -11,7 +11,7 @@ use crate::ast::helpers::{ resolve_ctor_name, }; use crate::ast::statement::Statement; -use crate::ast::{NodeId, NodesToSymbols}; +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}; @@ -187,6 +187,7 @@ impl Class { (names_table, diagnostics) } + #[deprecated] pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec { let mut diagnostics: Vec = Vec::new(); @@ -231,6 +232,7 @@ impl Class { .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(); @@ -244,6 +246,7 @@ impl Class { diagnostics } + #[deprecated] pub fn gather_types( &self, symbol_table: &SymbolTable, @@ -472,6 +475,7 @@ impl Class { Ok(()) } + #[deprecated] pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -485,6 +489,7 @@ impl Class { Ok(()) } + #[deprecated] pub fn to_ir( &self, symbol_table: &SymbolTable, @@ -529,4 +534,43 @@ impl Class { (ir_class, ir_functions) } + + pub fn lower_to_ir( + &self, + nodes_to_symbols: &NodesToSymbols, + symbols_to_types: &SymbolsToTypes, + nodes_to_types: &NodesToTypes, + function_return_types: &FunctionReturnTypes, + ) -> (IrClass, Vec) { + let mut ir_functions = Vec::new(); + + if let Some(constructor) = &self.constructor { + // todo + } + + for function in &self.functions { + ir_functions.push(function.lower_to_ir_static( + nodes_to_symbols, + symbols_to_types, + nodes_to_types, + function_return_types, + )); + } + + let self_class_symbol = nodes_to_symbols + .get(&self.node_id) + .unwrap() + .unwrap_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| 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 a5488cf..2d4bfbe 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -245,7 +245,7 @@ impl CompilationUnit { diagnostics_result!(diagnostics) } - pub fn lower( + pub fn lower_to_ir( &self, nodes_to_symbols: &NodesToSymbols, symbols_to_types: &SymbolsToTypes, @@ -256,7 +256,7 @@ impl CompilationUnit { let mut ir_functions = Vec::new(); for function in &self.functions { - ir_functions.push(function.lower_static( + ir_functions.push(function.lower_to_ir_static( nodes_to_symbols, symbols_to_types, nodes_to_types, @@ -264,9 +264,21 @@ impl CompilationUnit { )); } + 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, + function_return_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, diff --git a/dmc-lib/src/ast/field.rs b/dmc-lib/src/ast/field.rs index 801690c..bb7fa9d 100644 --- a/dmc-lib/src/ast/field.rs +++ b/dmc-lib/src/ast/field.rs @@ -1,9 +1,10 @@ -use crate::ast::NodesToSymbols; 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; @@ -12,6 +13,7 @@ use crate::types_table::TypesTable; use std::rc::Rc; pub struct Field { + node_id: NodeId, declared_name: Rc, declared_name_source_range: SourceRange, is_public: bool, @@ -23,6 +25,7 @@ pub struct Field { impl Field { pub fn new( + node_id: NodeId, declared_name: &str, declared_name_source_range: SourceRange, is_public: bool, @@ -31,6 +34,7 @@ impl Field { initializer: Option, ) -> Self { Self { + node_id, declared_name: declared_name.into(), declared_name_source_range, is_public, @@ -215,4 +219,18 @@ impl Field { 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/function.rs b/dmc-lib/src/ast/function.rs index ee06366..cb1cf54 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -18,6 +18,7 @@ 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; @@ -33,7 +34,8 @@ pub struct Function { parameters: Vec, return_type: Option, statements: Vec, - scope_id: Option, + container_scope_id: Option, + function_scope_id: Option, } impl Function { @@ -54,7 +56,8 @@ impl Function { parameters, return_type, statements, - scope_id: None, + container_scope_id: None, + function_scope_id: None, } } @@ -71,9 +74,10 @@ impl Function { } pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) { - self.scope_id = Some(container_scope); + 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); @@ -102,6 +106,17 @@ impl Function { 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( @@ -110,7 +125,7 @@ impl Function { fqn_context.resolve(self.declared_name()), false, is_method, - self.scope_id.unwrap(), + self.container_scope_id.unwrap(), parameter_symbols, )); all_symbols.push(Symbol::Function(function_symbol.clone())); @@ -239,7 +254,7 @@ impl Function { #[deprecated] pub fn gather_types(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) { let function_symbol = symbol_table - .get_function_symbol_owned(self.scope_id.unwrap(), self.declared_name()) + .get_function_symbol_owned(self.container_scope_id.unwrap(), self.declared_name()) .unwrap(); // self type (the signature) @@ -336,7 +351,7 @@ impl Function { ) -> Result<(), Vec> { let mut diagnostics = vec![]; let function_symbol = symbol_table - .get_function_symbol(self.scope_id.unwrap(), self.declared_name()) + .get_function_symbol(self.container_scope_id.unwrap(), self.declared_name()) .unwrap(); // parameters @@ -408,6 +423,7 @@ impl Function { } } + #[deprecated] pub fn to_ir( &self, symbol_table: &SymbolTable, @@ -416,7 +432,7 @@ impl Function { ) -> IrFunction { let mut builder = IrBuilder::new(); let function_symbol = symbol_table - .get_function_symbol(self.scope_id.unwrap(), self.declared_name()) + .get_function_symbol(self.container_scope_id.unwrap(), self.declared_name()) .unwrap(); // parameters @@ -441,7 +457,7 @@ impl Function { ) } - pub fn lower_static( + pub fn lower_to_ir_static( &self, nodes_to_symbols: &NodesToSymbols, symbols_to_types: &SymbolsToTypes, diff --git a/dmc-lib/src/ast/parameter.rs b/dmc-lib/src/ast/parameter.rs index 1fed46d..87d1e4a 100644 --- a/dmc-lib/src/ast/parameter.rs +++ b/dmc-lib/src/ast/parameter.rs @@ -52,7 +52,7 @@ impl Parameter { pub fn make_symbol(&self) -> ParameterSymbol { ParameterSymbol::new( &self.declared_name, - self.declared_name_source_range.clone(), + Some(self.declared_name_source_range.clone()), self.scope_id.unwrap(), ) } diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index 8c8a767..b0ad4c3 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -899,6 +899,7 @@ impl<'a> Parser<'a> { if let Some(identifier) = identifier { let field = Field::new( + self.next_node_id(), self.token_text(&identifier), SourceRange::new(identifier.start(), identifier.end()), is_public, diff --git a/dmc-lib/src/symbol/expressible_symbol.rs b/dmc-lib/src/symbol/expressible_symbol.rs index 7707274..7880b0f 100644 --- a/dmc-lib/src/symbol/expressible_symbol.rs +++ b/dmc-lib/src/symbol/expressible_symbol.rs @@ -36,7 +36,7 @@ impl ExpressibleSymbol { Some(function_symbol.declared_name_source_range()) } ExpressibleSymbol::Parameter(parameter_symbol) => { - Some(parameter_symbol.declared_name_source_range()) + parameter_symbol.declared_name_source_range() } ExpressibleSymbol::Variable(variable_symbol) => { Some(variable_symbol.declared_name_source_range()) diff --git a/dmc-lib/src/symbol/mod.rs b/dmc-lib/src/symbol/mod.rs index 1a63546..f4d42fe 100644 --- a/dmc-lib/src/symbol/mod.rs +++ b/dmc-lib/src/symbol/mod.rs @@ -72,9 +72,7 @@ impl Symbol { Some(constructor_symbol.declared_name_source_range()) } Symbol::Function(function_symbol) => Some(function_symbol.declared_name_source_range()), - Symbol::Parameter(parameter_symbol) => { - Some(parameter_symbol.declared_name_source_range()) - } + Symbol::Parameter(parameter_symbol) => parameter_symbol.declared_name_source_range(), Symbol::Variable(variable_symbol) => Some(variable_symbol.declared_name_source_range()), } } @@ -119,4 +117,18 @@ impl Symbol { _ => panic!(), } } + + pub fn unwrap_class_symbol(&self) -> &Rc { + match self { + Symbol::Class(class_symbol) => class_symbol, + _ => panic!(), + } + } + + pub fn unwrap_field_symbol(&self) -> &Rc { + match self { + Symbol::Field(field_symbol) => field_symbol, + _ => panic!(), + } + } } diff --git a/dmc-lib/src/symbol/parameter_symbol.rs b/dmc-lib/src/symbol/parameter_symbol.rs index 3b20621..18d4e1d 100644 --- a/dmc-lib/src/symbol/parameter_symbol.rs +++ b/dmc-lib/src/symbol/parameter_symbol.rs @@ -1,18 +1,17 @@ use crate::source_range::SourceRange; -use crate::symbol::Symbol; use std::hash::{Hash, Hasher}; use std::rc::Rc; pub struct ParameterSymbol { declared_name: Rc, - declared_name_source_range: SourceRange, + declared_name_source_range: Option, scope_id: usize, } impl ParameterSymbol { pub fn new( declared_name: &Rc, - declared_name_source_range: SourceRange, + declared_name_source_range: Option, scope_id: usize, ) -> Self { Self { @@ -30,8 +29,8 @@ impl ParameterSymbol { self.declared_name.clone() } - pub fn declared_name_source_range(&self) -> &SourceRange { - &self.declared_name_source_range + pub fn declared_name_source_range(&self) -> Option<&SourceRange> { + self.declared_name_source_range.as_ref() } pub fn scope_id(&self) -> usize {