From 344761022b2a9aa9f1fececd819d70e343436250 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sat, 21 Mar 2026 17:42:10 -0500 Subject: [PATCH] More fixes to type info, etc. WIP. --- dmc-lib/src/ast/assign_statement.rs | 14 ++++++--- dmc-lib/src/ast/call.rs | 20 ++++++------ dmc-lib/src/ast/class.rs | 14 ++++++--- dmc-lib/src/ast/compilation_unit.rs | 18 +++++------ dmc-lib/src/ast/constructor.rs | 10 ++++-- dmc-lib/src/ast/extern_function.rs | 5 +++ dmc-lib/src/ast/function.rs | 13 ++++++++ dmc-lib/src/ast/identifier.rs | 23 ++++++++++++-- dmc-lib/src/ast/parameter.rs | 10 ++++++ dmc-lib/src/ast/type_use.rs | 11 +++++-- dmc-lib/src/intrinsics/mod.rs | 47 ++++++++++++++++++++++++++++- dmc-lib/src/intrinsics/symbols.rs | 3 -- dmc-lib/src/ir/ir_block.rs | 6 ++-- dmc-lib/src/ir/ir_class.rs | 2 +- dmc-lib/src/lib.rs | 2 +- dmc-lib/src/type_info.rs | 11 +++++++ dmc-lib/src/types_table.rs | 24 +++++++++++++++ e2e-tests/src/lib.rs | 9 +++++- 18 files changed, 195 insertions(+), 47 deletions(-) delete mode 100644 dmc-lib/src/intrinsics/symbols.rs diff --git a/dmc-lib/src/ast/assign_statement.rs b/dmc-lib/src/ast/assign_statement.rs index 5759f45..d27dfde 100644 --- a/dmc-lib/src/ast/assign_statement.rs +++ b/dmc-lib/src/ast/assign_statement.rs @@ -262,11 +262,12 @@ mod tests { fn compile_up_to_type_check( compilation_unit: &mut CompilationUnit, symbol_table: &mut SymbolTable, - ) -> Result> { + 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(symbol_table) + compilation_unit.gather_types_into(symbol_table, types_table) } #[test] @@ -281,7 +282,8 @@ mod tests { ) .unwrap(); let mut symbol_table = SymbolTable::new(); - let mut types_table = compile_up_to_type_check(&mut compilation_unit, &mut symbol_table)?; + 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(); @@ -303,7 +305,8 @@ mod tests { ", )?; let mut symbol_table = SymbolTable::new(); - let mut types_table = compile_up_to_type_check(&mut compilation_unit, &mut symbol_table)?; + 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(); @@ -323,7 +326,8 @@ mod tests { ", )?; let mut symbol_table = SymbolTable::new(); - let mut types_table = compile_up_to_type_check(&mut compilation_unit, &mut symbol_table)?; + 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(); diff --git a/dmc-lib/src/ast/call.rs b/dmc-lib/src/ast/call.rs index bbd3dac..7aafa64 100644 --- a/dmc-lib/src/ast/call.rs +++ b/dmc-lib/src/ast/call.rs @@ -125,18 +125,16 @@ impl Call { TypeInfo::Function(function_symbol) => { CallableSymbol::Function(function_symbol.clone()) } - TypeInfo::ClassInstance(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), + 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!( diff --git a/dmc-lib/src/ast/class.rs b/dmc-lib/src/ast/class.rs index 8e8a986..4fb8b63 100644 --- a/dmc-lib/src/ast/class.rs +++ b/dmc-lib/src/ast/class.rs @@ -203,12 +203,11 @@ impl Class { symbol_table: &SymbolTable, types_table: &mut TypesTable, ) -> Result<(), Vec> { - // instance type + // class type let class_symbol = self.get_class_symbol_owned(symbol_table); - types_table.class_instance_types_mut().insert( - class_symbol.clone(), - TypeInfo::ClassInstance(class_symbol.clone()), - ); + 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 @@ -219,6 +218,11 @@ impl Class { .constructor_return_types_mut() .insert(constructor_symbol, TypeInfo::ClassInstance(class_symbol)); + // now the constructor (parameters, etc.) + if let Some(constructor) = &self.constructor { + constructor.gather_types_into(symbol_table, types_table); + } + let mut diagnostics = Vec::new(); // generic params diff --git a/dmc-lib/src/ast/compilation_unit.rs b/dmc-lib/src/ast/compilation_unit.rs index 008a633..fef33ec 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -95,26 +95,26 @@ impl CompilationUnit { diagnostics_result!(diagnostics) } - pub fn gather_types(&self, symbol_table: &SymbolTable) -> Result> { - let mut types_table = TypesTable::new(); + 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, &mut types_table), - diagnostics - ); + handle_diagnostics!(class.gather_types(symbol_table, types_table), diagnostics); } for function in &self.functions { - function.gather_types(symbol_table, &mut types_table); + function.gather_types(symbol_table, types_table); } for extern_function in &self.extern_functions { - extern_function.gather_types(symbol_table, &mut types_table); + extern_function.gather_types(symbol_table, types_table); } - ok_or_err_diagnostics!(types_table, diagnostics) + diagnostics_result!(diagnostics) } pub fn type_check( diff --git a/dmc-lib/src/ast/constructor.rs b/dmc-lib/src/ast/constructor.rs index a58753d..d0f393c 100644 --- a/dmc-lib/src/ast/constructor.rs +++ b/dmc-lib/src/ast/constructor.rs @@ -113,6 +113,12 @@ impl Constructor { .collect() } + 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); + } + } + pub fn type_check( &mut self, symbol_table: &SymbolTable, @@ -187,7 +193,7 @@ impl Constructor { let alloc_assign_destination = IrVariable::new_vr( ir_builder.new_t_var().into(), ir_builder.current_block().id(), - &TypeInfo::ClassInstance(class_symbol.clone()), + &TypeInfo::Class(class_symbol.clone()), ); let self_variable = Rc::new(RefCell::new(alloc_assign_destination)); @@ -276,7 +282,7 @@ impl Constructor { IrFunction::new( fqn_parts_to_string(constructor_symbol.fqn_parts()), ir_parameters, - &TypeInfo::ClassInstance(class_symbol.clone()), + &TypeInfo::Class(class_symbol.clone()), entry_block.clone(), ) } diff --git a/dmc-lib/src/ast/extern_function.rs b/dmc-lib/src/ast/extern_function.rs index c521a80..408206b 100644 --- a/dmc-lib/src/ast/extern_function.rs +++ b/dmc-lib/src/ast/extern_function.rs @@ -92,6 +92,11 @@ impl ExternFunction { 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( diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 5fd78e5..2533661 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -141,6 +141,14 @@ impl Function { let function_symbol = symbol_table .get_function_symbol_owned(self.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 @@ -151,6 +159,11 @@ impl Function { .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( diff --git a/dmc-lib/src/ast/identifier.rs b/dmc-lib/src/ast/identifier.rs index 7511f2b..89b5e8e 100644 --- a/dmc-lib/src/ast/identifier.rs +++ b/dmc-lib/src/ast/identifier.rs @@ -224,10 +224,27 @@ impl Identifier { symbol_table: &SymbolTable, types_table: &'a TypesTable, ) -> &'a TypeInfo { - let variable_symbol = symbol_table - .get_variable_symbol(self.scope_id.unwrap(), &self.name) + let expressible_symbol = symbol_table + .find_expressible_symbol(self.scope_id.unwrap(), &self.name) .unwrap(); - types_table.variable_types().get(variable_symbol).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).unwrap() + } + 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 ir_expression( diff --git a/dmc-lib/src/ast/parameter.rs b/dmc-lib/src/ast/parameter.rs index 61b0079..a2617bc 100644 --- a/dmc-lib/src/ast/parameter.rs +++ b/dmc-lib/src/ast/parameter.rs @@ -52,6 +52,16 @@ impl Parameter { self.type_use.check_names(symbol_table) } + 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 type_check( &mut self, symbol_table: &SymbolTable, diff --git a/dmc-lib/src/ast/type_use.rs b/dmc-lib/src/ast/type_use.rs index 75be815..08097e6 100644 --- a/dmc-lib/src/ast/type_use.rs +++ b/dmc-lib/src/ast/type_use.rs @@ -89,7 +89,10 @@ impl TypeUse { TypeSymbol::Class(class_symbol) => types_table .class_instance_types() .get(&class_symbol) - .unwrap(), + .expect(&format!( + "Could not get TypeInfo for {}", + self.declared_name + )), TypeSymbol::GenericParameter(generic_parameter_symbol) => types_table .generic_parameter_types() .get(&generic_parameter_symbol) @@ -105,7 +108,7 @@ impl TypeUse { let mut diagnostics: Vec = vec![]; match self.type_info(symbol_table, types_table) { - TypeInfo::ClassInstance(class_symbol) => { + 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() { @@ -168,6 +171,7 @@ mod tests { use crate::diagnostic::Diagnostic; use crate::parser::parse_compilation_unit; use crate::symbol_table::SymbolTable; + use crate::types_table::TypesTable; #[test] fn type_check_generics() -> Result<(), Vec> { @@ -184,11 +188,12 @@ mod tests { )?; 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)?; - let mut types_table = compilation_unit.gather_types(&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/intrinsics/mod.rs b/dmc-lib/src/intrinsics/mod.rs index 6eb441d..b9407dd 100644 --- a/dmc-lib/src/intrinsics/mod.rs +++ b/dmc-lib/src/intrinsics/mod.rs @@ -1 +1,46 @@ -mod symbols; +use crate::symbol::class_symbol::ClassSymbol; +use crate::symbol_table::SymbolTable; +use crate::type_info::TypeInfo; +use crate::types_table::TypesTable; +use std::rc::Rc; + +fn create_simple_primitive(name: &str) -> ClassSymbol { + ClassSymbol::new( + &Rc::from(name), + None, + vec![Rc::from(name)], + true, + 0, // global + vec![], + None, + vec![], + vec![], + ) +} + +pub fn insert_intrinsic_symbols(symbol_table: &mut SymbolTable) { + let primitives = [ + create_simple_primitive("Int"), + create_simple_primitive("Double"), + create_simple_primitive("String"), + ]; + for primitive in primitives { + symbol_table.insert_class_symbol(Rc::new(primitive)); + } +} + +pub fn insert_intrinsic_types(symbol_table: &SymbolTable, types_table: &mut TypesTable) { + let primitives = ["Int", "Double", "String"]; + for primitive in primitives { + let symbol = symbol_table.get_class_symbol(0, primitive).unwrap().clone(); + let type_info = match primitive { + "Int" => TypeInfo::Integer, + "Double" => TypeInfo::Double, + "String" => TypeInfo::String, + _ => unreachable!(), + }; + types_table + .class_instance_types_mut() + .insert(symbol, type_info); + } +} diff --git a/dmc-lib/src/intrinsics/symbols.rs b/dmc-lib/src/intrinsics/symbols.rs deleted file mode 100644 index f6d9e47..0000000 --- a/dmc-lib/src/intrinsics/symbols.rs +++ /dev/null @@ -1,3 +0,0 @@ -use crate::symbol_table::SymbolTable; - -pub fn add_intrinsic_symbols(symbol_table: &mut SymbolTable) {} diff --git a/dmc-lib/src/ir/ir_block.rs b/dmc-lib/src/ir/ir_block.rs index 78933d7..626c7d9 100644 --- a/dmc-lib/src/ir/ir_block.rs +++ b/dmc-lib/src/ir/ir_block.rs @@ -124,6 +124,7 @@ mod tests { use crate::diagnostic::Diagnostic; use crate::parser::parse_compilation_unit; use crate::symbol_table::SymbolTable; + use crate::types_table::TypesTable; #[test] fn overlapping_assignments_bug_when_k_2() -> Result<(), Vec> { @@ -139,12 +140,13 @@ mod tests { )?; 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)?; - let mut types_table = compilation_unit.gather_types(&symbol_table)?; - compilation_unit.type_check(&mut symbol_table, &mut types_table)?; + compilation_unit.gather_types_into(&symbol_table, &mut types_table)?; + compilation_unit.type_check(&symbol_table, &mut types_table)?; let main = compilation_unit .functions() diff --git a/dmc-lib/src/ir/ir_class.rs b/dmc-lib/src/ir/ir_class.rs index bedba4c..b5c13fe 100644 --- a/dmc-lib/src/ir/ir_class.rs +++ b/dmc-lib/src/ir/ir_class.rs @@ -51,7 +51,7 @@ impl IrField { TypeInfo::Integer => VmTypeInfo::Int, TypeInfo::Double => VmTypeInfo::Double, TypeInfo::String => VmTypeInfo::String, - TypeInfo::ClassInstance(class_symbol) => { + TypeInfo::Class(class_symbol) => { VmTypeInfo::ClassInstance(fqn_parts_to_string(class_symbol.fqn_parts()).into()) } TypeInfo::GenericType(_) => VmTypeInfo::Any, diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index 80bb9a0..610ba90 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -2,7 +2,7 @@ pub mod ast; pub mod constants_table; pub mod diagnostic; pub mod error_codes; -mod intrinsics; +pub mod intrinsics; pub mod ir; pub mod lexer; pub mod parser; diff --git a/dmc-lib/src/type_info.rs b/dmc-lib/src/type_info.rs index f30c0aa..bfb0cae 100644 --- a/dmc-lib/src/type_info.rs +++ b/dmc-lib/src/type_info.rs @@ -11,7 +11,11 @@ pub enum TypeInfo { Double, String, Function(Rc), + Class(Rc), + + #[deprecated] ClassInstance(Rc), + GenericType(Rc), Void, } @@ -33,6 +37,9 @@ impl Display for TypeInfo { } write!(f, ")") } + TypeInfo::Class(class_symbol) => { + write!(f, "Class({:?})", class_symbol) + } TypeInfo::ClassInstance(class_symbol) => { write!(f, "{}", class_symbol.declared_name()) } @@ -68,6 +75,10 @@ impl TypeInfo { TypeInfo::Function(_) => { unimplemented!("Type matching on Functions not yet supported.") } + TypeInfo::Class(class_symbol) => match other { + TypeInfo::Class(other_class_symbol) => class_symbol == other_class_symbol, + _ => false, + }, TypeInfo::ClassInstance(class_symbol) => { match other { TypeInfo::ClassInstance(other_class_symbol) => { diff --git a/dmc-lib/src/types_table.rs b/dmc-lib/src/types_table.rs index 81cf5d3..2ff5775 100644 --- a/dmc-lib/src/types_table.rs +++ b/dmc-lib/src/types_table.rs @@ -10,10 +10,12 @@ use std::collections::HashMap; use std::rc::Rc; pub struct TypesTable { + class_types: HashMap, TypeInfo>, class_instance_types: HashMap, TypeInfo>, generic_parameter_types: HashMap, TypeInfo>, field_types: HashMap, TypeInfo>, constructor_return_types: HashMap, TypeInfo>, + function_types: HashMap, TypeInfo>, function_return_types: HashMap, TypeInfo>, parameter_types: HashMap, TypeInfo>, variable_types: HashMap, TypeInfo>, @@ -22,16 +24,26 @@ pub struct TypesTable { impl TypesTable { pub fn new() -> Self { Self { + class_types: HashMap::new(), class_instance_types: HashMap::new(), generic_parameter_types: HashMap::new(), field_types: HashMap::new(), parameter_types: HashMap::new(), variable_types: HashMap::new(), + function_types: HashMap::new(), function_return_types: HashMap::new(), constructor_return_types: HashMap::new(), } } + pub fn class_types(&self) -> &HashMap, TypeInfo> { + &self.class_types + } + + pub fn class_types_mut(&mut self) -> &mut HashMap, TypeInfo> { + &mut self.class_types + } + pub fn class_instance_types(&self) -> &HashMap, TypeInfo> { &self.class_instance_types } @@ -74,18 +86,30 @@ impl TypesTable { &mut self.variable_types } + pub fn function_types(&self) -> &HashMap, TypeInfo> { + &self.function_types + } + + pub fn function_types_mut(&mut self) -> &mut HashMap, TypeInfo> { + &mut self.function_types + } + + #[deprecated] pub fn function_return_types(&self) -> &HashMap, TypeInfo> { &self.function_return_types } + #[deprecated] pub fn function_return_types_mut(&mut self) -> &mut HashMap, TypeInfo> { &mut self.function_return_types } + #[deprecated] pub fn constructor_return_types(&self) -> &HashMap, TypeInfo> { &self.constructor_return_types } + #[deprecated] pub fn constructor_return_types_mut( &mut self, ) -> &mut HashMap, TypeInfo> { diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index 526ea53..e5a7770 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -2,8 +2,10 @@ mod e2e_tests { use dmc_lib::constants_table::ConstantsTable; use dmc_lib::diagnostic::Diagnostic; + use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types}; 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 dvm_lib::vm::constant::{Constant, StringConstant}; use dvm_lib::vm::function::Function; @@ -36,11 +38,16 @@ mod e2e_tests { }; 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)?; - let mut types_table = compilation_unit.gather_types(&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);