diff --git a/dmc-lib/src/ast/class.rs b/dmc-lib/src/ast/class.rs index 7d93ff6..b2381d1 100644 --- a/dmc-lib/src/ast/class.rs +++ b/dmc-lib/src/ast/class.rs @@ -205,6 +205,14 @@ impl Class { 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 for field in &self.fields { handle_diagnostics!(field.gather_types(symbol_table, types_table), diagnostics); diff --git a/dmc-lib/src/ast/generic_parameter.rs b/dmc-lib/src/ast/generic_parameter.rs index 354c507..06764ea 100644 --- a/dmc-lib/src/ast/generic_parameter.rs +++ b/dmc-lib/src/ast/generic_parameter.rs @@ -3,6 +3,7 @@ use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; use crate::symbol::generic_parameter_symbol::GenericParameterSymbol; use crate::symbol_table::SymbolTable; +use crate::type_info::TypeInfo; use crate::types_table::TypesTable; use crate::{diagnostics_result, handle_diagnostics}; use std::cell::RefCell; @@ -53,6 +54,32 @@ impl GenericParameter { .collect() } + pub fn gather_types( + &self, + symbol_table: &SymbolTable, + types_table: &mut TypesTable, + ) -> Result<(), Vec> { + // 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( &mut self, symbol_table: &SymbolTable, diff --git a/dmc-lib/src/ast/type_use.rs b/dmc-lib/src/ast/type_use.rs index 2c4727b..91d6454 100644 --- a/dmc-lib/src/ast/type_use.rs +++ b/dmc-lib/src/ast/type_use.rs @@ -2,7 +2,6 @@ use crate::ast::diagnostic_factories::symbol_not_found; use crate::diagnostic::Diagnostic; use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS; use crate::source_range::SourceRange; -use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::type_symbol::TypeSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; @@ -57,55 +56,24 @@ impl TypeUse { // check generic args for type_use in &self.generic_arguments { - type_use.check_names(symbol_table); + diagnostics.append(&mut type_use.check_names(symbol_table)); } diagnostics } - pub fn gather_declared_names( - &mut self, - symbol_table: &mut SymbolTable, - ) -> Result<(), Vec> { - self.scope_id = Some(symbol_table.current_scope_id()); - let mut inner_diagnostics: Vec = 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, + pub fn gather_types( + &self, symbol_table: &SymbolTable, - class_context: Option<&Rc>, + types_table: &mut TypesTable, ) -> Result<(), Vec> { - let mut diagnostics: Vec = vec![]; - - 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 { + let mut diagnostics = Vec::new(); + for type_use in &self.generic_arguments { handle_diagnostics!( - generic_argument.check_name_usages(symbol_table, class_context), + type_use.gather_types(symbol_table, types_table), diagnostics ); } - diagnostics_result!(diagnostics) } @@ -157,12 +125,12 @@ impl TypeUse { maybe_return_diagnostics!(diagnostics); // check that each arg is assignable to the param's extends - for i in 0..self.generic_arguments.len() { - let generic_parameter_symbol = &generic_parameters[i]; - if generic_parameter_symbol.extends().len() > 0 { - unimplemented!("Generic extends not implemented yet.") - } - } + // for i in 0..self.generic_arguments.len() { + // let generic_parameter_symbol = &generic_parameters[i]; + // if generic_parameter_symbol.extends().len() > 0 { + // unimplemented!("Generic extends not implemented yet.") + // } + // } } _ => { // cannot extend a non-class type (except for Any) @@ -199,7 +167,6 @@ 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> { @@ -214,11 +181,11 @@ 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)?; Ok(()) diff --git a/dmc-lib/src/symbol/generic_parameter_symbol.rs b/dmc-lib/src/symbol/generic_parameter_symbol.rs index 83aa7d6..eb3cbea 100644 --- a/dmc-lib/src/symbol/generic_parameter_symbol.rs +++ b/dmc-lib/src/symbol/generic_parameter_symbol.rs @@ -1,5 +1,4 @@ use crate::source_range::SourceRange; -use crate::type_info::TypeInfo; use std::hash::{Hash, Hasher}; use std::rc::Rc; @@ -7,7 +6,6 @@ pub struct GenericParameterSymbol { declared_name: Rc, declared_name_source_range: SourceRange, scope_id: usize, - extends: Option>, } impl GenericParameterSymbol { @@ -20,7 +18,6 @@ impl GenericParameterSymbol { declared_name: declared_name.clone(), declared_name_source_range: declared_name_source_range.clone(), scope_id, - extends: None, } } @@ -39,14 +36,6 @@ impl GenericParameterSymbol { pub fn scope_id(&self) -> usize { self.scope_id } - - pub fn set_extends(&mut self, extends: Vec) { - self.extends = Some(extends); - } - - pub fn extends(&self) -> &[TypeInfo] { - self.extends.as_ref().unwrap() - } } impl Eq for GenericParameterSymbol {} diff --git a/dmc-lib/src/symbol_table/mod.rs b/dmc-lib/src/symbol_table/mod.rs index 3a15b5b..711ff48 100644 --- a/dmc-lib/src/symbol_table/mod.rs +++ b/dmc-lib/src/symbol_table/mod.rs @@ -289,6 +289,17 @@ impl SymbolTable { } } + pub fn get_generic_parameter_symbol_owned( + &self, + scope_id: usize, + name: &str, + ) -> Option> { + 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> { match self.scope(scope_id) { Scope::ClassBody(class_body_scope) => { diff --git a/dmc-lib/src/type_info.rs b/dmc-lib/src/type_info.rs index de28bfe..f30c0aa 100644 --- a/dmc-lib/src/type_info.rs +++ b/dmc-lib/src/type_info.rs @@ -77,11 +77,11 @@ impl TypeInfo { } } TypeInfo::GenericType(generic_parameter_symbol) => { - if generic_parameter_symbol.extends().len() > 0 { - unimplemented!( - "Assigning to generic parameter type with extends type uses not yet supported." - ); - } + // if generic_parameter_symbol.extends().len() > 0 { + // unimplemented!( + // "Assigning to generic parameter type with extends type uses not yet supported." + // ); + // } true } TypeInfo::Void => { diff --git a/dmc-lib/src/types_table.rs b/dmc-lib/src/types_table.rs index 6b8afef..2feb822 100644 --- a/dmc-lib/src/types_table.rs +++ b/dmc-lib/src/types_table.rs @@ -1,6 +1,7 @@ use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::field_symbol::FieldSymbol; use crate::symbol::function_symbol::FunctionSymbol; +use crate::symbol::generic_parameter_symbol::GenericParameterSymbol; use crate::symbol::parameter_symbol::ParameterSymbol; use crate::symbol::variable_symbol::VariableSymbol; use crate::type_info::TypeInfo; @@ -9,6 +10,7 @@ use std::rc::Rc; pub struct TypesTable { class_instance_types: HashMap, TypeInfo>, + generic_parameter_types: HashMap, TypeInfo>, field_types: HashMap, TypeInfo>, parameter_types: HashMap, TypeInfo>, variable_types: HashMap, TypeInfo>, @@ -19,6 +21,7 @@ impl TypesTable { pub fn new() -> Self { Self { class_instance_types: HashMap::new(), + generic_parameter_types: HashMap::new(), field_types: HashMap::new(), parameter_types: HashMap::new(), variable_types: HashMap::new(), @@ -34,6 +37,16 @@ impl TypesTable { &mut self.class_instance_types } + pub fn generic_parameter_types(&self) -> &HashMap, TypeInfo> { + &self.generic_parameter_types + } + + pub fn generic_parameter_types_mut( + &mut self, + ) -> &mut HashMap, TypeInfo> { + &mut self.generic_parameter_types + } + pub fn field_types(&self) -> &HashMap, TypeInfo> { &self.field_types } diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index 9e27b22..526ea53 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -9,7 +9,7 @@ mod e2e_tests { use dvm_lib::vm::function::Function; use dvm_lib::vm::operand::Operand; use dvm_lib::vm::value::Value; - use dvm_lib::vm::{call, CallStack, DvmContext}; + use dvm_lib::vm::{CallStack, DvmContext, call}; use std::rc::Rc; const REGISTER_COUNT: usize = 8;