More fixes to type info, etc. WIP.

This commit is contained in:
Jesse Brault 2026-03-21 17:42:10 -05:00
parent fc83cf7827
commit 344761022b
18 changed files with 195 additions and 47 deletions

View File

@ -262,11 +262,12 @@ mod tests {
fn compile_up_to_type_check(
compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable,
) -> Result<TypesTable, Vec<Diagnostic>> {
types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> {
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();

View File

@ -125,8 +125,7 @@ impl Call {
TypeInfo::Function(function_symbol) => {
CallableSymbol::Function(function_symbol.clone())
}
TypeInfo::ClassInstance(class_symbol) => {
match class_symbol.constructor_symbol_owned() {
TypeInfo::Class(class_symbol) => match class_symbol.constructor_symbol_owned() {
None => {
diagnostics.push(class_has_no_constructor(
class_symbol.declared_name(),
@ -135,8 +134,7 @@ impl Call {
return Err(diagnostics);
}
Some(constructor_symbol) => CallableSymbol::Constructor(constructor_symbol),
}
}
},
_ => {
diagnostics.push(Diagnostic::new(
&format!(

View File

@ -203,12 +203,11 @@ impl Class {
symbol_table: &SymbolTable,
types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> {
// 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

View File

@ -95,26 +95,26 @@ impl CompilationUnit {
diagnostics_result!(diagnostics)
}
pub fn gather_types(&self, symbol_table: &SymbolTable) -> Result<TypesTable, Vec<Diagnostic>> {
let mut types_table = TypesTable::new();
pub fn gather_types_into(
&self,
symbol_table: &SymbolTable,
types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> {
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(

View File

@ -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(),
)
}

View File

@ -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(

View File

@ -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(

View File

@ -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(&parameter_symbol)
.unwrap(),
ExpressibleSymbol::Variable(variable_symbol) => {
types_table.variable_types().get(&variable_symbol).unwrap()
}
}
}
pub fn ir_expression(

View File

@ -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,

View File

@ -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<Diagnostic> = 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<Diagnostic>> {
@ -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(())

View File

@ -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);
}
}

View File

@ -1,3 +0,0 @@
use crate::symbol_table::SymbolTable;
pub fn add_intrinsic_symbols(symbol_table: &mut SymbolTable) {}

View File

@ -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<Diagnostic>> {
@ -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()

View File

@ -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,

View File

@ -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;

View File

@ -11,7 +11,11 @@ pub enum TypeInfo {
Double,
String,
Function(Rc<FunctionSymbol>),
Class(Rc<ClassSymbol>),
#[deprecated]
ClassInstance(Rc<ClassSymbol>),
GenericType(Rc<GenericParameterSymbol>),
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) => {

View File

@ -10,10 +10,12 @@ use std::collections::HashMap;
use std::rc::Rc;
pub struct TypesTable {
class_types: HashMap<Rc<ClassSymbol>, TypeInfo>,
class_instance_types: HashMap<Rc<ClassSymbol>, TypeInfo>,
generic_parameter_types: HashMap<Rc<GenericParameterSymbol>, TypeInfo>,
field_types: HashMap<Rc<FieldSymbol>, TypeInfo>,
constructor_return_types: HashMap<Rc<ConstructorSymbol>, TypeInfo>,
function_types: HashMap<Rc<FunctionSymbol>, TypeInfo>,
function_return_types: HashMap<Rc<FunctionSymbol>, TypeInfo>,
parameter_types: HashMap<Rc<ParameterSymbol>, TypeInfo>,
variable_types: HashMap<Rc<VariableSymbol>, 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<Rc<ClassSymbol>, TypeInfo> {
&self.class_types
}
pub fn class_types_mut(&mut self) -> &mut HashMap<Rc<ClassSymbol>, TypeInfo> {
&mut self.class_types
}
pub fn class_instance_types(&self) -> &HashMap<Rc<ClassSymbol>, TypeInfo> {
&self.class_instance_types
}
@ -74,18 +86,30 @@ impl TypesTable {
&mut self.variable_types
}
pub fn function_types(&self) -> &HashMap<Rc<FunctionSymbol>, TypeInfo> {
&self.function_types
}
pub fn function_types_mut(&mut self) -> &mut HashMap<Rc<FunctionSymbol>, TypeInfo> {
&mut self.function_types
}
#[deprecated]
pub fn function_return_types(&self) -> &HashMap<Rc<FunctionSymbol>, TypeInfo> {
&self.function_return_types
}
#[deprecated]
pub fn function_return_types_mut(&mut self) -> &mut HashMap<Rc<FunctionSymbol>, TypeInfo> {
&mut self.function_return_types
}
#[deprecated]
pub fn constructor_return_types(&self) -> &HashMap<Rc<ConstructorSymbol>, TypeInfo> {
&self.constructor_return_types
}
#[deprecated]
pub fn constructor_return_types_mut(
&mut self,
) -> &mut HashMap<Rc<ConstructorSymbol>, TypeInfo> {

View File

@ -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);