Fixing bugs. WIP.

This commit is contained in:
Jesse Brault 2026-03-20 23:57:09 -05:00
parent 4e8fa159c0
commit 912f208705
8 changed files with 79 additions and 64 deletions

View File

@ -205,6 +205,14 @@ impl Class {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
// generic params
for generic_parameter in &self.generic_parameters {
handle_diagnostics!(
generic_parameter.gather_types(symbol_table, types_table),
diagnostics
);
}
// field types // field types
for field in &self.fields { for field in &self.fields {
handle_diagnostics!(field.gather_types(symbol_table, types_table), diagnostics); handle_diagnostics!(field.gather_types(symbol_table, types_table), diagnostics);

View File

@ -3,6 +3,7 @@ use crate::diagnostic::Diagnostic;
use crate::source_range::SourceRange; use crate::source_range::SourceRange;
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol; use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo;
use crate::types_table::TypesTable; use crate::types_table::TypesTable;
use crate::{diagnostics_result, handle_diagnostics}; use crate::{diagnostics_result, handle_diagnostics};
use std::cell::RefCell; use std::cell::RefCell;
@ -53,6 +54,32 @@ impl GenericParameter {
.collect() .collect()
} }
pub fn gather_types(
&self,
symbol_table: &SymbolTable,
types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> {
// self param
let generic_parameter_symbol = symbol_table
.get_generic_parameter_symbol_owned(self.scope_id.unwrap(), &self.declared_name)
.unwrap();
types_table.generic_parameter_types_mut().insert(
generic_parameter_symbol.clone(),
TypeInfo::GenericType(generic_parameter_symbol),
);
let mut diagnostics = Vec::new();
for type_use in &self.extends {
handle_diagnostics!(
type_use.gather_types(symbol_table, types_table),
diagnostics
);
}
diagnostics_result!(diagnostics)
}
pub fn type_check( pub fn type_check(
&mut self, &mut self,
symbol_table: &SymbolTable, symbol_table: &SymbolTable,

View File

@ -2,7 +2,6 @@ use crate::ast::diagnostic_factories::symbol_not_found;
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS; use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS;
use crate::source_range::SourceRange; use crate::source_range::SourceRange;
use crate::symbol::class_symbol::ClassSymbol;
use crate::symbol::type_symbol::TypeSymbol; use crate::symbol::type_symbol::TypeSymbol;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo; use crate::type_info::TypeInfo;
@ -57,55 +56,24 @@ impl TypeUse {
// check generic args // check generic args
for type_use in &self.generic_arguments { for type_use in &self.generic_arguments {
type_use.check_names(symbol_table); diagnostics.append(&mut type_use.check_names(symbol_table));
} }
diagnostics diagnostics
} }
pub fn gather_declared_names( pub fn gather_types(
&mut self, &self,
symbol_table: &mut SymbolTable,
) -> Result<(), Vec<Diagnostic>> {
self.scope_id = Some(symbol_table.current_scope_id());
let mut inner_diagnostics: Vec<Diagnostic> = vec![];
for generic_argument in &mut self.generic_arguments {
handle_diagnostics!(
generic_argument.gather_declared_names(symbol_table),
inner_diagnostics
);
}
diagnostics_result!(inner_diagnostics)
}
pub fn check_name_usages(
&mut self,
symbol_table: &SymbolTable, symbol_table: &SymbolTable,
class_context: Option<&Rc<ClassSymbol>>, types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> { ) -> Result<(), Vec<Diagnostic>> {
let mut diagnostics: Vec<Diagnostic> = vec![]; let mut diagnostics = Vec::new();
for type_use in &self.generic_arguments {
if symbol_table
.find_type_symbol(self.scope_id.unwrap(), &self.declared_name)
.is_none()
{
// this is wonky
let diagnostic = Diagnostic::new(
&format!("Unable to resolve symbol {}", self.declared_name),
self.declared_name_source_range.start(),
self.declared_name_source_range.end(),
)
.with_reporter(file!(), line!());
diagnostics.push(diagnostic);
}
for generic_argument in &mut self.generic_arguments {
handle_diagnostics!( handle_diagnostics!(
generic_argument.check_name_usages(symbol_table, class_context), type_use.gather_types(symbol_table, types_table),
diagnostics diagnostics
); );
} }
diagnostics_result!(diagnostics) diagnostics_result!(diagnostics)
} }
@ -157,12 +125,12 @@ impl TypeUse {
maybe_return_diagnostics!(diagnostics); maybe_return_diagnostics!(diagnostics);
// check that each arg is assignable to the param's extends // check that each arg is assignable to the param's extends
for i in 0..self.generic_arguments.len() { // for i in 0..self.generic_arguments.len() {
let generic_parameter_symbol = &generic_parameters[i]; // let generic_parameter_symbol = &generic_parameters[i];
if generic_parameter_symbol.extends().len() > 0 { // if generic_parameter_symbol.extends().len() > 0 {
unimplemented!("Generic extends not implemented yet.") // unimplemented!("Generic extends not implemented yet.")
} // }
} // }
} }
_ => { _ => {
// cannot extend a non-class type (except for Any) // cannot extend a non-class type (except for Any)
@ -199,7 +167,6 @@ mod tests {
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::parser::parse_compilation_unit; use crate::parser::parse_compilation_unit;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::types_table::TypesTable;
#[test] #[test]
fn type_check_generics() -> Result<(), Vec<Diagnostic>> { fn type_check_generics() -> Result<(), Vec<Diagnostic>> {
@ -214,11 +181,11 @@ mod tests {
)?; )?;
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
let mut types_table = TypesTable::new();
compilation_unit.init_scopes(&mut symbol_table); compilation_unit.init_scopes(&mut symbol_table);
compilation_unit.gather_symbols_into(&mut symbol_table)?; compilation_unit.gather_symbols_into(&mut symbol_table)?;
compilation_unit.check_names(&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.type_check(&mut symbol_table, &mut types_table)?;
Ok(()) Ok(())

View File

@ -1,5 +1,4 @@
use crate::source_range::SourceRange; use crate::source_range::SourceRange;
use crate::type_info::TypeInfo;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::rc::Rc; use std::rc::Rc;
@ -7,7 +6,6 @@ pub struct GenericParameterSymbol {
declared_name: Rc<str>, declared_name: Rc<str>,
declared_name_source_range: SourceRange, declared_name_source_range: SourceRange,
scope_id: usize, scope_id: usize,
extends: Option<Vec<TypeInfo>>,
} }
impl GenericParameterSymbol { impl GenericParameterSymbol {
@ -20,7 +18,6 @@ impl GenericParameterSymbol {
declared_name: declared_name.clone(), declared_name: declared_name.clone(),
declared_name_source_range: declared_name_source_range.clone(), declared_name_source_range: declared_name_source_range.clone(),
scope_id, scope_id,
extends: None,
} }
} }
@ -39,14 +36,6 @@ impl GenericParameterSymbol {
pub fn scope_id(&self) -> usize { pub fn scope_id(&self) -> usize {
self.scope_id self.scope_id
} }
pub fn set_extends(&mut self, extends: Vec<TypeInfo>) {
self.extends = Some(extends);
}
pub fn extends(&self) -> &[TypeInfo] {
self.extends.as_ref().unwrap()
}
} }
impl Eq for GenericParameterSymbol {} impl Eq for GenericParameterSymbol {}

View File

@ -289,6 +289,17 @@ impl SymbolTable {
} }
} }
pub fn get_generic_parameter_symbol_owned(
&self,
scope_id: usize,
name: &str,
) -> Option<Rc<GenericParameterSymbol>> {
match self.scope(scope_id) {
Scope::Class(class_scope) => class_scope.generic_parameter_symbols().get(name).cloned(),
_ => panic!("scope_id {} cannot contain generic types", scope_id),
}
}
pub fn get_field_symbol(&self, scope_id: usize, name: &str) -> Option<&FieldSymbol> { pub fn get_field_symbol(&self, scope_id: usize, name: &str) -> Option<&FieldSymbol> {
match self.scope(scope_id) { match self.scope(scope_id) {
Scope::ClassBody(class_body_scope) => { Scope::ClassBody(class_body_scope) => {

View File

@ -77,11 +77,11 @@ impl TypeInfo {
} }
} }
TypeInfo::GenericType(generic_parameter_symbol) => { TypeInfo::GenericType(generic_parameter_symbol) => {
if generic_parameter_symbol.extends().len() > 0 { // if generic_parameter_symbol.extends().len() > 0 {
unimplemented!( // unimplemented!(
"Assigning to generic parameter type with extends type uses not yet supported." // "Assigning to generic parameter type with extends type uses not yet supported."
); // );
} // }
true true
} }
TypeInfo::Void => { TypeInfo::Void => {

View File

@ -1,6 +1,7 @@
use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::class_symbol::ClassSymbol;
use crate::symbol::field_symbol::FieldSymbol; use crate::symbol::field_symbol::FieldSymbol;
use crate::symbol::function_symbol::FunctionSymbol; use crate::symbol::function_symbol::FunctionSymbol;
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
use crate::symbol::parameter_symbol::ParameterSymbol; use crate::symbol::parameter_symbol::ParameterSymbol;
use crate::symbol::variable_symbol::VariableSymbol; use crate::symbol::variable_symbol::VariableSymbol;
use crate::type_info::TypeInfo; use crate::type_info::TypeInfo;
@ -9,6 +10,7 @@ use std::rc::Rc;
pub struct TypesTable { pub struct TypesTable {
class_instance_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>, field_types: HashMap<Rc<FieldSymbol>, TypeInfo>,
parameter_types: HashMap<Rc<ParameterSymbol>, TypeInfo>, parameter_types: HashMap<Rc<ParameterSymbol>, TypeInfo>,
variable_types: HashMap<Rc<VariableSymbol>, TypeInfo>, variable_types: HashMap<Rc<VariableSymbol>, TypeInfo>,
@ -19,6 +21,7 @@ impl TypesTable {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
class_instance_types: HashMap::new(), class_instance_types: HashMap::new(),
generic_parameter_types: HashMap::new(),
field_types: HashMap::new(), field_types: HashMap::new(),
parameter_types: HashMap::new(), parameter_types: HashMap::new(),
variable_types: HashMap::new(), variable_types: HashMap::new(),
@ -34,6 +37,16 @@ impl TypesTable {
&mut self.class_instance_types &mut self.class_instance_types
} }
pub fn generic_parameter_types(&self) -> &HashMap<Rc<GenericParameterSymbol>, TypeInfo> {
&self.generic_parameter_types
}
pub fn generic_parameter_types_mut(
&mut self,
) -> &mut HashMap<Rc<GenericParameterSymbol>, TypeInfo> {
&mut self.generic_parameter_types
}
pub fn field_types(&self) -> &HashMap<Rc<FieldSymbol>, TypeInfo> { pub fn field_types(&self) -> &HashMap<Rc<FieldSymbol>, TypeInfo> {
&self.field_types &self.field_types
} }

View File

@ -9,7 +9,7 @@ mod e2e_tests {
use dvm_lib::vm::function::Function; use dvm_lib::vm::function::Function;
use dvm_lib::vm::operand::Operand; use dvm_lib::vm::operand::Operand;
use dvm_lib::vm::value::Value; use dvm_lib::vm::value::Value;
use dvm_lib::vm::{call, CallStack, DvmContext}; use dvm_lib::vm::{CallStack, DvmContext, call};
use std::rc::Rc; use std::rc::Rc;
const REGISTER_COUNT: usize = 8; const REGISTER_COUNT: usize = 8;