From 4c68d0dc28110d54a23b9473f387a9e70c549519 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Tue, 20 May 2025 10:56:47 -0500 Subject: [PATCH] Flesh out gather and resolve, add todos, refactor a bit. --- sketching/may_2025/use.dm | 2 - src/ast/mod.rs | 204 +++++++-------- src/ast/named.rs | 59 +++++ src/name_analysis/gather.rs | 412 ++++++++++++++++++++++-------- src/name_analysis/mod.rs | 30 ++- src/name_analysis/resolve.rs | 389 ++++++++++++++++++++++------ src/name_analysis/symbol.rs | 9 +- src/name_analysis/symbol_table.rs | 139 ++++++++++ 8 files changed, 927 insertions(+), 317 deletions(-) diff --git a/sketching/may_2025/use.dm b/sketching/may_2025/use.dm index bcaefc3..19be4b7 100644 --- a/sketching/may_2025/use.dm +++ b/sketching/may_2025/use.dm @@ -1,3 +1 @@ -use std::core::println; -use std::core::*; use std::core::{print, println}; diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 84c7be1..19c7044 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -10,7 +10,8 @@ pub mod build; pub mod named; pub mod pretty_print; pub mod unparse; -// Operators + +/* Operators */ #[derive(Debug)] pub enum Operator { @@ -56,19 +57,13 @@ pub enum SuffixUnaryOperator { /* Names */ -#[derive(Debug, Clone)] -pub enum SavedSymbol { - Declaration(Symbol), - Linking(Symbol), -} - #[derive(Debug)] pub struct Identifier { - pub name: String, - pub file_id: usize, - pub range: Range, + name: String, + file_id: usize, + range: Range, scope_id: Option, - saved_symbol: Option, + saved_symbol: Option, } impl Identifier { @@ -81,31 +76,15 @@ impl Identifier { saved_symbol: None, } } - - pub fn set_scope_id(&mut self, id: usize) { - self.scope_id = Some(id); - } - - pub fn scope_id(&self) -> Option { - self.scope_id - } - - pub fn set_saved_symbol(&mut self, saved_symbol: SavedSymbol) { - self.saved_symbol = Some(saved_symbol); - } - - pub fn saved_symbol(&self) -> Option { - self.saved_symbol.clone() - } } #[derive(Debug)] pub struct FullyQualifiedName { - pub identifiers: Vec, - pub file_id: usize, - pub range: Range, + identifiers: Vec, + file_id: usize, + range: Range, scope_id: Option, - symbol: Option, + saved_symbol: Option, } impl FullyQualifiedName { @@ -115,24 +94,25 @@ impl FullyQualifiedName { range, file_id, scope_id: None, - symbol: None, + saved_symbol: None, } } - pub fn set_scope_id(&mut self, scope_id: usize) { - self.scope_id = Some(scope_id); + pub fn last(&self) -> &Identifier { + &self.identifiers[self.identifiers.len() - 1] } - pub fn scope_id(&self) -> Option { - self.scope_id + pub fn last_mut(&mut self) -> &mut Identifier { + let last_index = self.identifiers.len() - 1; + &mut self.identifiers[last_index] } - - pub fn set_symbol(&mut self, symbol: Symbol) { - self.symbol = Some(symbol); + + pub fn len(&self) -> usize { + self.identifiers.len() } - - pub fn symbol(&self) -> &Option { - &self.symbol + + pub fn is_single_identifier(&self) -> bool { + self.identifiers.len() == 1 } } @@ -185,7 +165,7 @@ pub struct FunctionTypeUse { pub return_type: ReturnType, } -// Generic arguments +/* Generic arguments */ #[derive(Debug)] pub struct GenericArguments(pub Vec); @@ -319,7 +299,68 @@ pub struct CompilationUnit { pub declarations: Vec, } -// Declarations allowed in each level +/* Use Statement */ + +#[derive(Debug)] +pub struct UseStatement { + pub identifiers: Vec, + pub last: UseStatementLast, + pub file_id: usize, + pub range: Range, +} + +impl UseStatement { + pub fn new( + identifiers: Vec, + last: UseStatementLast, + file_id: usize, + range: Range, + ) -> Self { + UseStatement { + identifiers, + last, + file_id, + range, + } + } + + pub fn base_name(&self) -> Cow<'_, str> { + use UseStatementLast::*; + if self.identifiers.is_empty() { + match &self.last { + Identifier(_) => Cow::from(""), + Star | Identifiers(_) => panic!(), // should never get here because of grammar + } + } else if self.identifiers.len() == 1 { + self.identifiers[0].name() + } else { + let mut acc = String::new(); + for (i, identifier) in self.identifiers.iter().enumerate() { + acc.push_str(&identifier.name()); + if i != self.identifiers.len() - 1 { + acc.push_str("::"); + } + } + Cow::from(acc) + } + } + + pub fn is_star(&self) -> bool { + match &self.last { + UseStatementLast::Star => true, + _ => false, + } + } +} + +#[derive(Debug)] +pub enum UseStatementLast { + Identifier(Rc>), + Identifiers(Vec>>), + Star, +} + +/* Declarations allowed in each level */ #[derive(Debug)] pub enum ModuleLevelDeclaration { @@ -351,7 +392,7 @@ pub enum ClassLevelDeclaration { Field(FieldDeclaration), } -// Declarations +/* Main Declarations */ #[derive(Debug)] pub struct ModuleDeclaration { @@ -379,7 +420,7 @@ pub struct ClassDeclaration { pub declarations: Vec, } -// Function declarations and components +/* Function declarations and components */ #[derive(Debug)] pub struct FunctionDefinition { @@ -449,7 +490,7 @@ pub enum FunctionBody { Alias(Identifier), } -// Class components +/* Class components */ #[derive(Debug)] pub struct ClassConstructor(pub Vec); @@ -474,72 +515,7 @@ pub struct FieldDeclaration { pub declared_type: TypeUse, } -// Statements - -#[derive(Debug)] -pub struct UseStatement { - pub identifiers: Vec, - pub last: UseStatementLast, - pub file_id: usize, - pub range: Range, -} - -pub struct UseStatementImport<'a> { - pub declared_name: String, - pub fqn: String, - pub identifier: &'a mut Identifier, -} - -impl UseStatement { - pub fn new( - identifiers: Vec, - last: UseStatementLast, - file_id: usize, - range: Range, - ) -> Self { - UseStatement { - identifiers, - last, - file_id, - range, - } - } - - pub fn base_name(&self) -> Cow<'_, str> { - use UseStatementLast::*; - if self.identifiers.is_empty() { - match &self.last { - Identifier(_) => Cow::from(""), - Star | Identifiers(_) => panic!(), // should never get here because of grammar - } - } else if self.identifiers.len() == 1 { - self.identifiers[0].name() - } else { - let mut acc = String::new(); - for (i, identifier) in self.identifiers.iter().enumerate() { - acc.push_str(&identifier.name()); - if i != self.identifiers.len() - 1 { - acc.push_str("::"); - } - } - Cow::from(acc) - } - } - - pub fn is_star(&self) -> bool { - match &self.last { - UseStatementLast::Star => true, - _ => false, - } - } -} - -#[derive(Debug)] -pub enum UseStatementLast { - Identifier(Rc>), - Identifiers(Vec>>), - Star, -} +/* Statements */ #[derive(Debug)] pub struct BlockStatement { @@ -612,7 +588,7 @@ pub struct ForStatement { pub body: BlockStatement, } -// Expressions +/* Expressions */ #[derive(Debug)] pub enum Expression { diff --git a/src/ast/named.rs b/src/ast/named.rs index d319126..4c31873 100644 --- a/src/ast/named.rs +++ b/src/ast/named.rs @@ -1,14 +1,49 @@ use crate::ast::{FullyQualifiedName, Identifier}; +use crate::name_analysis::symbol::Symbol; use std::borrow::Cow; +use std::range::Range; pub trait Named { fn name(&self) -> Cow<'_, str>; + + fn file_id(&self) -> usize; + fn range(&self) -> Range; + + fn set_scope_id(&mut self, scope_id: usize); + fn scope_id(&self) -> Option; + + fn set_saved_symbol(&mut self, symbol: Symbol); + fn saved_symbol(&self) -> Option; } impl Named for Identifier { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.name) } + + fn file_id(&self) -> usize { + self.file_id + } + + fn range(&self) -> Range { + self.range + } + + fn set_scope_id(&mut self, id: usize) { + self.scope_id = Some(id); + } + + fn scope_id(&self) -> Option { + self.scope_id + } + + fn set_saved_symbol(&mut self, saved_symbol: Symbol) { + self.saved_symbol = Some(saved_symbol); + } + + fn saved_symbol(&self) -> Option { + self.saved_symbol.clone() + } } impl Named for FullyQualifiedName { @@ -26,4 +61,28 @@ impl Named for FullyQualifiedName { Cow::Owned(acc) } } + + fn file_id(&self) -> usize { + self.file_id + } + + fn range(&self) -> Range { + self.range + } + + fn set_scope_id(&mut self, id: usize) { + self.scope_id = Some(id); + } + + fn scope_id(&self) -> Option { + self.scope_id + } + + fn set_saved_symbol(&mut self, symbol: Symbol) { + self.saved_symbol = Some(symbol); + } + + fn saved_symbol(&self) -> Option { + self.saved_symbol.clone() + } } diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index 3222d5f..23eb1f2 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -42,6 +42,8 @@ fn handle_insert_error( } } +/* Names */ + fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) { identifier.set_scope_id(symbol_table.current_scope_id()); } @@ -50,9 +52,11 @@ fn gather_fully_qualified_name( fully_qualified_name: &mut FullyQualifiedName, symbol_table: &mut SymbolTable, ) { - fully_qualified_name.set_scope_id(symbol_table.current_scope_id()); + gather_identifier(fully_qualified_name.last_mut(), symbol_table); } +/* Type Use */ + fn gather_type_use( type_use: &mut TypeUse, symbol_table: &mut SymbolTable, @@ -61,19 +65,7 @@ fn gather_type_use( ) { match type_use { TypeUse::Primitive(primitive_type_use) => { - match primitive_type_use { - PrimitiveTypeUse::Array(generic_arguments_opt) => { - if let Some(generic_arguments) = generic_arguments_opt { - gather_generic_arguments( - generic_arguments, - symbol_table, - fqn_context, - diagnostics, - ); - } - } - _ => {} - } + gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics) } TypeUse::InterfaceOrClass(interface_or_class_type_use) => { gather_interface_or_class_type_use( @@ -92,6 +84,22 @@ fn gather_type_use( } } +fn gather_primitive_type_use( + primitive_type_use: &mut PrimitiveTypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + match primitive_type_use { + PrimitiveTypeUse::Array(generic_arguments_opt) => { + if let Some(generic_arguments) = generic_arguments_opt { + gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics); + } + } + _ => {} + } +} + fn gather_interface_or_class_type_use( interface_or_class_type_use: &mut InterfaceOrClassTypeUse, symbol_table: &mut SymbolTable, @@ -124,9 +132,28 @@ fn gather_function_type_use( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + gather_generic_parameters( + &mut function_type_use.generics, + symbol_table, + fqn_context, + diagnostics, + ); + gather_parameters( + &mut function_type_use.parameters, + symbol_table, + fqn_context, + diagnostics, + ); + gather_return_type( + &mut function_type_use.return_type, + symbol_table, + fqn_context, + diagnostics, + ); } +/* Generic Arguments */ + fn gather_generic_arguments( generic_arguments: &mut GenericArguments, symbol_table: &mut SymbolTable, @@ -138,6 +165,123 @@ fn gather_generic_arguments( } } +/* Generic Parameters */ + +fn gather_generic_parameters( + generic_parameters: &mut GenericParameters, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!("Add each Identifier as a type to the current scope; make sure caller's push/pop before/after") +} + +/* Implements List */ + +fn gather_implements_list( + implements_list: &mut ImplementsList, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for type_use in &mut implements_list.0 { + gather_type_use(type_use, symbol_table, fqn_context, diagnostics); + } +} + +/* Function Parameters */ + +fn gather_parameters( + parameters: &mut Parameters, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) -> Option>> { + parameters + .0 + .iter_mut() + .map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics)) + .collect() +} + +fn gather_parameter( + parameter: &mut Parameter, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) -> Option> { + let parameter_name = parameter.identifier.name(); + + let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( + ¶meter_name, + Some(¶meter.identifier), + )); + + match insert_result { + Ok(parameter_symbol) => { + parameter + .identifier + .set_scope_id(symbol_table.current_scope_id()); + + gather_type_use( + &mut parameter.type_use, + symbol_table, + fqn_context, + diagnostics, + ); + Some(parameter_symbol) + } + Err(err) => { + handle_insert_error( + err, + ¶meter_name, + parameter.identifier.file_id(), + parameter.identifier.range(), + "function/variable", + diagnostics, + ); + None + } + } +} + +/* Return Type */ + +fn gather_return_type( + return_type: &mut ReturnType, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_type_use( + &mut return_type.declared_type, + symbol_table, + fqn_context, + diagnostics, + ); + gather_references( + &mut return_type.references, + symbol_table, + fqn_context, + diagnostics, + ); +} + +/* References */ + +fn gather_references( + references: &mut References, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for identifier in &mut references.0 { + gather_identifier(identifier, symbol_table); + } +} + +/* Compilation Unit/Top-level construct */ + pub(super) fn gather_compilation_unit( compilation_unit: &mut CompilationUnit, symbol_table: &mut SymbolTable, @@ -159,6 +303,8 @@ pub(super) fn gather_compilation_unit( assert_eq!(symbol_table.current_scope_id(), 0); } +/* Use Statement */ + fn handle_use_statement_import( symbol_table: &mut SymbolTable, base_name: &str, @@ -181,16 +327,15 @@ fn handle_use_statement_import( gather_identifier(mutable_borrowed_identifier.deref_mut(), symbol_table); - mutable_borrowed_identifier.set_saved_symbol(SavedSymbol::Linking( - Symbol::UseStatement(use_statement_symbol), - )); + mutable_borrowed_identifier + .set_saved_symbol(Symbol::UseStatement(use_statement_symbol)); } Err(err) => { handle_insert_error( err, &declared_name, - borrowed_identifier.file_id, - borrowed_identifier.range, + borrowed_identifier.file_id(), + borrowed_identifier.range(), "Use statement", diagnostics, ); @@ -226,6 +371,8 @@ fn gather_use_statement( } } +/* Declarations allowed in each level */ + fn gather_module_level_declaration( declaration: &mut ModuleLevelDeclaration, symbol_table: &mut SymbolTable, @@ -255,6 +402,26 @@ fn gather_module_level_declaration( } } +fn gather_interface_level_declaration( + declaration: &mut InterfaceLevelDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_class_level_declaration( + declaration: &mut ClassLevelDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Main Declarations */ + fn gather_module_declaration( declaration: &mut ModuleDeclaration, symbol_table: &mut SymbolTable, @@ -280,8 +447,8 @@ fn gather_module_declaration( handle_insert_error( err, &module_name, - declaration.identifier.file_id, - declaration.identifier.range, + declaration.identifier.file_id(), + declaration.identifier.range(), "module/type", diagnostics, ) @@ -315,8 +482,8 @@ fn gather_class_declaration( handle_insert_error( err, &declared_name, - class_declaration.identifier.file_id, - class_declaration.identifier.range, + class_declaration.identifier.file_id(), + class_declaration.identifier.range(), "interface/class", diagnostics, ); @@ -325,6 +492,8 @@ fn gather_class_declaration( // todo: scopes, generics, etc. } +/* Function declarations and components */ + fn gather_function_definition( function: &mut FunctionDefinition, symbol_table: &mut SymbolTable, @@ -384,8 +553,8 @@ fn gather_function_definition( handle_insert_error( err, &declared_name, - function.identifier.file_id, - function.identifier.range, + function.identifier.file_id(), + function.identifier.range(), "function/variable", diagnostics, ); @@ -393,6 +562,15 @@ fn gather_function_definition( } } +fn gather_operator_function_definition( + operator_function_definition: &mut OperatorFunctionDefinition, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + fn gather_platform_function_definition( platform_function_declaration: &mut PlatformFunctionDeclaration, symbol_table: &mut SymbolTable, @@ -453,8 +631,8 @@ fn gather_platform_function_definition( handle_insert_error( err, &declared_name, - platform_function_declaration.identifier.file_id, - platform_function_declaration.identifier.range, + platform_function_declaration.identifier.file_id(), + platform_function_declaration.identifier.range(), "(Platform-) Function", diagnostics, ); @@ -462,89 +640,22 @@ fn gather_platform_function_definition( } } -fn gather_parameters( - parameters: &mut Parameters, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) -> Option>> { - parameters - .0 - .iter_mut() - .map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics)) - .collect() -} - -fn gather_parameter( - parameter: &mut Parameter, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) -> Option> { - let parameter_name = parameter.identifier.name(); - - let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( - ¶meter_name, - Some(¶meter.identifier), - )); - - match insert_result { - Ok(parameter_symbol) => { - parameter - .identifier - .set_scope_id(symbol_table.current_scope_id()); - - gather_type_use( - &mut parameter.type_use, - symbol_table, - fqn_context, - diagnostics, - ); - Some(parameter_symbol) - } - Err(err) => { - handle_insert_error( - err, - ¶meter_name, - parameter.identifier.file_id, - parameter.identifier.range, - "function/variable", - diagnostics, - ); - None - } - } -} - -fn gather_return_type( - return_type: &mut ReturnType, +fn gather_interface_function_declaration( + declaration: &mut InterfaceFunctionDeclaration, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - gather_type_use( - &mut return_type.declared_type, - symbol_table, - fqn_context, - diagnostics, - ); - gather_references( - &mut return_type.references, - symbol_table, - fqn_context, - diagnostics, - ); + todo!() } -fn gather_references( - references: &mut References, +fn gather_interface_operator_function_declaration( + declaration: &mut InterfaceOperatorFunctionDeclaration, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - for identifier in &mut references.0 { - gather_identifier(identifier, symbol_table); - } + todo!() } fn gather_function_body( @@ -560,6 +671,37 @@ fn gather_function_body( } } +/* Class Components */ + +fn gather_class_constructor( + class_constructor: &mut ClassConstructor, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_property_declaration( + property_declaration: &mut PropertyDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_field_declaration( + field_declaration: &mut FieldDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Statements */ + fn gather_block_statement( block: &mut BlockStatement, symbol_table: &mut SymbolTable, @@ -626,8 +768,8 @@ fn gather_variable_declaration( handle_insert_error( err, &variable_name, - variable_declaration.identifier.file_id, - variable_declaration.identifier.range, + variable_declaration.identifier.file_id(), + variable_declaration.identifier.range(), "function/variable", diagnostics, ) @@ -660,6 +802,55 @@ fn gather_call_statement( gather_expression(&mut call_statement.0, symbol_table, diagnostics); } +fn gather_return_statement( + return_statement: &mut ReturnStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + if let Some(expression) = &mut return_statement.0 { + gather_expression(expression, symbol_table, diagnostics); + } +} + +fn gather_if_statement( + if_statement: &mut IfStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_if_else_statement( + if_else_statement: &mut IfElseStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_while_statement( + while_statement: &mut WhileStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_for_statement( + for_statement: &mut ForStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Expressions */ + fn gather_expression( expression: &mut Expression, symbol_table: &mut SymbolTable, @@ -782,6 +973,7 @@ fn gather_object_access( gather_expression(index_expression, symbol_table, diagnostics); } ObjectNavigation::Identifier(identifier) => { + // TODO: use a special gather for names belonging to a struct gather_identifier(identifier, symbol_table); } } @@ -794,8 +986,18 @@ fn gather_literal( diagnostics: &mut Vec, ) { match literal { - Literal::DString(d_string) => todo!(), - Literal::BacktickString(backtick_string) => todo!(), + Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics), + Literal::BacktickString(backtick_string) => { + gather_d_string(backtick_string, symbol_table, diagnostics) + } _ => {} } } + +fn gather_d_string( + d_string: &mut DString, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index ab6392d..b669a5e 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -88,8 +88,6 @@ mod tests { let diagnostics = analyze_names(&mut compilation_units, symbol_table); - assert_eq!(n_diagnostics, diagnostics.len()); - if !diagnostics.is_empty() { let writer = StandardStream::stderr(ColorChoice::Always); let config = term::Config::default(); @@ -101,6 +99,8 @@ mod tests { eprintln!("{}", symbol_table); } + assert_eq!(n_diagnostics, diagnostics.len()); + for compilation_unit in &compilation_units { dbg!(compilation_unit); } @@ -174,13 +174,25 @@ mod tests { } #[test] - fn symbol_shadows_import() { - let sources: HashMap<&str, &str> = HashMap::from([( - "main.dm", - indoc! {" - platform fn println(msg: Any) -> Void; - "}, - )]); + fn use_class_from_other_file() { + let sources: HashMap<&str, &str> = HashMap::from([ + ( + "main.dm", + indoc! {" + use greeter::Greeter; + + fn test(greeter: Greeter) {} + "}, + ), + ( + "greeter.dm", + indoc! {" + ns greeter; + + class Greeter {} + "}, + ), + ]); let mut symbol_table = SymbolTable::new(); add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); assert_no_diagnostics(sources, &mut symbol_table); diff --git a/src/name_analysis/resolve.rs b/src/name_analysis/resolve.rs index 4373f6a..05f0fe8 100644 --- a/src/name_analysis/resolve.rs +++ b/src/name_analysis/resolve.rs @@ -1,41 +1,14 @@ use crate::ast::named::Named; use crate::ast::*; use crate::diagnostic::DmDiagnostic; -use crate::name_analysis::symbol_table::SymbolTable; +use crate::name_analysis::symbol::Symbol; +use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use std::cell::RefCell; use std::range::Range; use std::rc::Rc; -fn resolve_fully_qualified_name( - fully_qualified_name: &mut FullyQualifiedName, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let lookup_result = symbol_table.lookup( - fully_qualified_name.name().as_ref(), - fully_qualified_name.scope_id().expect(&format!( - "FullyQualifiedName has no scope_id set: {:?}", - fully_qualified_name - )), - ); - match lookup_result { - Ok(symbol) => { - fully_qualified_name.set_symbol(symbol.clone()); - } - Err(e) => diagnostics.push( - Diagnostic::error() - .with_message(format!( - "No symbol with name '{}' found in current scope.", - fully_qualified_name.name() - )) - .with_label(Label::primary( - fully_qualified_name.file_id, - fully_qualified_name.range, - )), - ), - } -} +/* Type Use */ fn resolve_type_use( type_use: &mut TypeUse, @@ -44,18 +17,7 @@ fn resolve_type_use( ) { match type_use { TypeUse::Primitive(primitive_type_use) => { - match primitive_type_use { - PrimitiveTypeUse::Array(generic_arguments_opt) => { - if let Some(generic_arguments) = generic_arguments_opt { - resolve_generic_arguments( - generic_arguments, - symbol_table, - diagnostics, - ); - } - } - _ => {} - } + resolve_primitive_type_use(primitive_type_use, symbol_table, diagnostics) } TypeUse::InterfaceOrClass(interface_or_class_type_use) => { resolve_interface_or_class_type_use( @@ -73,16 +35,56 @@ fn resolve_type_use( } } +fn resolve_primitive_type_use( + primitive_type_use: &mut PrimitiveTypeUse, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + match primitive_type_use { + PrimitiveTypeUse::Array(generic_arguments_opt) => { + if let Some(generic_arguments) = generic_arguments_opt { + resolve_generic_arguments(generic_arguments, symbol_table, diagnostics); + } + } + _ => {} + } +} + fn resolve_interface_or_class_type_use( interface_or_class_type_use: &mut InterfaceOrClassTypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { - resolve_fully_qualified_name( - &mut interface_or_class_type_use.fqn, - symbol_table, - diagnostics, - ); + // 1. handle main name + let fqn = &mut interface_or_class_type_use.fqn; + let lookup_result = if fqn.is_single_identifier() { + let identifier = fqn.last(); + symbol_table.lookup_type_by_declared_name( + &identifier.name(), + identifier + .scope_id() + .expect("Identifier's scope id not set."), + ) + } else { + todo!("Fully-qualified-name type uses sensitive to imports and so on") + }; + match lookup_result { + Ok(type_symbol) => { + fqn.last_mut().set_saved_symbol(Symbol::Type(type_symbol)); + } + Err(_) => { + diagnostics.push( + Diagnostic::error() + .with_message(&format!( + "No type symbol '{}' found in current scope.", + fqn.name() + )) + .with_label(Label::primary(fqn.file_id(), fqn.range())), + ); + } + } + + // 2. generics resolve_generic_arguments( &mut interface_or_class_type_use.generics, symbol_table, @@ -111,6 +113,8 @@ fn resolve_function_type_use( ); } +/* Generic arguments */ + fn resolve_generic_arguments( generic_arguments: &mut GenericArguments, symbol_table: &mut SymbolTable, @@ -121,6 +125,10 @@ fn resolve_generic_arguments( } } +/* Generic parameters: todo: no resolution needed? */ + +/* Tuple arguments */ + fn resolve_tuple_arguments( tuple_type_use: &mut TupleArguments, symbol_table: &mut SymbolTable, @@ -131,6 +139,8 @@ fn resolve_tuple_arguments( } } +/* Implements list */ + fn resolve_implements_list( implements_list: &mut ImplementsList, symbol_table: &mut SymbolTable, @@ -139,6 +149,8 @@ fn resolve_implements_list( todo!() } +/* Function parameters */ + fn resolve_parameters( parameters: &mut Parameters, symbol_table: &mut SymbolTable, @@ -149,6 +161,8 @@ fn resolve_parameters( } } +/* Return Type */ + fn resolve_return_type( return_type: &mut ReturnType, symbol_table: &mut SymbolTable, @@ -158,6 +172,8 @@ fn resolve_return_type( resolve_references(&mut return_type.references, symbol_table, diagnostics); } +/* References */ + fn resolve_references( references: &mut References, symbol_table: &mut SymbolTable, @@ -168,8 +184,25 @@ fn resolve_references( } } +/* Compilation Unit/Top-level construct */ + +pub(super) fn resolve_compilation_unit( + compilation_unit: &mut CompilationUnit, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + for use_statement in &mut compilation_unit.use_statements { + resolve_use_statement(use_statement, symbol_table, diagnostics); + } + for declaration in &mut compilation_unit.declarations { + resolve_module_level_declaration(declaration, symbol_table, diagnostics); + } +} + +/* Use Statement */ + fn handle_use_statement_identifier( - identifier: &Rc>, + identifier: Rc>, base_name: &str, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, @@ -183,18 +216,15 @@ fn handle_use_statement_identifier( symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap()); match lookup_result { - Ok(referenced_symbol) => match borrowed_identifier.saved_symbol() { - Some(saved_symbol) => match saved_symbol { - SavedSymbol::Linking(symbol) => { - let use_statement_symbol = symbol.unwrap_use_statement_symbol(); - use_statement_symbol - .borrow_mut() - .set_referenced_symbol(referenced_symbol); - } - _ => panic!("Expected to find SavedSymbol::Linking."), - }, - None => panic!("Expected to find saved_symbol"), - }, + Ok(referenced_symbol) => { + let saved_symbol = borrowed_identifier + .saved_symbol() + .expect("Identifier's saved_symbol is not set."); + let use_statement_symbol = saved_symbol.unwrap_use_statement_symbol(); + use_statement_symbol + .borrow_mut() + .set_referenced_symbol(referenced_symbol); + } Err(_) => { diagnostics.push( Diagnostic::error() @@ -215,7 +245,7 @@ fn resolve_use_statement( match &use_statement.last { UseStatementLast::Identifier(identifier) => { handle_use_statement_identifier( - identifier, + identifier.clone(), &base_name, symbol_table, diagnostics, @@ -226,33 +256,22 @@ fn resolve_use_statement( UseStatementLast::Identifiers(identifiers) => { for identifier in identifiers { handle_use_statement_identifier( - identifier, + identifier.clone(), &base_name, symbol_table, diagnostics, use_statement.file_id, - identifier.borrow().range, + identifier.borrow().range(), ) } } - UseStatementLast::Star => todo!(), + UseStatementLast::Star => todo!("star imports"), } } -pub(super) fn resolve_compilation_unit( - compilation_unit: &mut CompilationUnit, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - for use_statement in &mut compilation_unit.use_statements { - resolve_use_statement(use_statement, symbol_table, diagnostics); - } - for declaration in &mut compilation_unit.declarations { - resolve_module_level_declaration(declaration, symbol_table, diagnostics); - } -} +/* Declarations allowed in each level */ -pub(super) fn resolve_module_level_declaration( +fn resolve_module_level_declaration( declaration: &mut ModuleLevelDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, @@ -274,6 +293,65 @@ pub(super) fn resolve_module_level_declaration( } } +fn resolve_interface_level_declaration( + declaration: &mut InterfaceLevelDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_class_level_declaration( + declaration: &mut ClassLevelDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Main Declarations */ + +fn resolve_module_declaration( + module_declaration: &mut ModuleDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + for declaration in &mut module_declaration.declarations { + resolve_module_level_declaration(declaration, symbol_table, diagnostics); + } +} + +fn resolve_interface_declaration( + interface_declaration: &mut InterfaceDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + resolve_implements_list( + &mut interface_declaration.implements, + symbol_table, + diagnostics, + ); + for declaration in &mut interface_declaration.declarations { + resolve_interface_level_declaration(declaration, symbol_table, diagnostics); + } +} + +fn resolve_class_declaration( + class_declaration: &mut ClassDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + if let Some(class_constructor) = &mut class_declaration.class_constructor { + resolve_class_constructor(class_constructor, symbol_table, diagnostics); + } + resolve_implements_list(&mut class_declaration.implements, symbol_table, diagnostics); + for declaration in &mut class_declaration.declarations { + resolve_class_level_declaration(declaration, symbol_table, diagnostics); + } +} + +/* Function declarations and components */ + fn resolve_function_definition( function_definition: &mut FunctionDefinition, symbol_table: &mut SymbolTable, @@ -292,6 +370,14 @@ fn resolve_function_definition( resolve_function_body(&mut function_definition.body, symbol_table, diagnostics); } +fn resolve_operator_function_definition( + operator_function_definition: &mut OperatorFunctionDefinition, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + fn resolve_platform_function_declaration( platform_function_declaration: &mut PlatformFunctionDeclaration, symbol_table: &mut SymbolTable, @@ -309,6 +395,22 @@ fn resolve_platform_function_declaration( ); } +fn resolve_interface_function_declaration( + interface_function_declaration: &mut InterfaceFunctionDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_interface_operator_function_declaration( + interface_operator_function_declaration: &mut InterfaceOperatorFunctionDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + fn resolve_function_body( function_body: &mut FunctionBody, symbol_table: &mut SymbolTable, @@ -316,12 +418,49 @@ fn resolve_function_body( ) { use crate::ast::FunctionBody::*; match function_body { - Block(block) => resolve_block(block, symbol_table, diagnostics), - _ => todo!(), + Equals(expression) => resolve_expression(expression, symbol_table, diagnostics), + Block(block) => resolve_block_statement(block, symbol_table, diagnostics), + Alias(identifier) => resolve_function_alias(identifier, symbol_table, diagnostics), } } -fn resolve_block( +fn resolve_function_alias( + identifier: &mut Identifier, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Class components */ + +fn resolve_class_constructor( + class_constructor: &mut ClassConstructor, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_property_declaration( + property_declaration: &mut PropertyDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_field_declaration( + field_declaration: &mut FieldDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Statements */ + +fn resolve_block_statement( block_statement: &mut BlockStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, @@ -341,7 +480,7 @@ fn resolve_statement( ) { use crate::ast::Statement::*; match statement { - BlockStatement(block) => resolve_block(block, symbol_table, diagnostics), + BlockStatement(block) => resolve_block_statement(block, symbol_table, diagnostics), VariableDeclarationStatement(variable_declaration) => { resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) } @@ -382,6 +521,42 @@ fn resolve_call_statement( resolve_expression(&mut call_statement.0, symbol_table, diagnostics) } +fn resolve_return_statement( + return_statement: &mut ReturnStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + if let Some(expression) = &mut return_statement.0 { + resolve_expression(expression, symbol_table, diagnostics); + } +} + +fn resolve_if_statement( + if_statement: &mut IfStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_while_statement( + while_statement: &mut WhileStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn resolve_for_statement( + for_statement: &mut ForStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Expressions */ + fn resolve_expression( expression: &mut Expression, symbol_table: &mut SymbolTable, @@ -407,7 +582,13 @@ fn resolve_expression( ObjectAccess(object_access) => { resolve_object_access(object_access, symbol_table, diagnostics); } - FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics), + FullyQualifiedName(fqn) => { + if fqn.is_single_identifier() { + resolve_identifier_expression(fqn.last_mut(), symbol_table, diagnostics); + } else { + resolve_fqn_expression(fqn, symbol_table, diagnostics); + } + } Literal(literal) => { resolve_literal(literal, symbol_table, diagnostics); } @@ -417,6 +598,48 @@ fn resolve_expression( } } +fn handle_named_lookup_result( + lookup_result: Result, + named: &mut impl Named, + diagnostics: &mut Vec, +) { + match lookup_result { + Ok(referenced_symbol) => { + named.set_saved_symbol(referenced_symbol); + } + Err(_) => { + diagnostics.push( + DmDiagnostic::error() + .with_message(&format!( + "Unable to find expressible symbol {} in current scope.", + named.name() + )) + .with_label(Label::primary(named.file_id(), named.range())), + ); + } + } +} + +fn resolve_identifier_expression( + identifier: &mut Identifier, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let lookup_result = symbol_table + .lookup_expressible_by_declared_name(&identifier.name(), identifier.scope_id().unwrap()); + handle_named_lookup_result(lookup_result, identifier, diagnostics); +} + +fn resolve_fqn_expression( + fqn: &mut FullyQualifiedName, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let lookup_result = + symbol_table.lookup_expressible_by_fqn(&fqn.name(), fqn.last().scope_id().unwrap()); + handle_named_lookup_result(lookup_result, fqn, diagnostics); +} + fn resolve_ternary_expression( ternary_expression: &mut TernaryExpression, symbol_table: &mut SymbolTable, @@ -477,7 +700,7 @@ fn resolve_turbo_fish( symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { - todo!() + resolve_generic_arguments(&mut turbo_fish.0, symbol_table, diagnostics); } fn resolve_call_arguments( diff --git a/src/name_analysis/symbol.rs b/src/name_analysis/symbol.rs index a5bbd7e..300794b 100644 --- a/src/name_analysis/symbol.rs +++ b/src/name_analysis/symbol.rs @@ -3,6 +3,7 @@ use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter}; use std::range::Range; use std::rc::Rc; +use crate::ast::named::Named; #[derive(Clone, Debug)] pub struct SourceDefinition { @@ -13,16 +14,16 @@ pub struct SourceDefinition { impl SourceDefinition { pub fn from_identifier(identifier: &Identifier) -> Self { SourceDefinition { - file_id: identifier.file_id, - range: identifier.range, + file_id: identifier.file_id(), + range: identifier.range(), } } pub fn from_identifier_rc(identifier: Rc>) -> Self { let borrowed = identifier.borrow(); SourceDefinition { - file_id: borrowed.file_id, - range: borrowed.range, + file_id: borrowed.file_id(), + range: borrowed.range(), } } diff --git a/src/name_analysis/symbol_table.rs b/src/name_analysis/symbol_table.rs index dc54513..dfd96c5 100644 --- a/src/name_analysis/symbol_table.rs +++ b/src/name_analysis/symbol_table.rs @@ -76,6 +76,29 @@ impl Scope { None } + fn get_type_symbol_by_declared_name(&self, declared_name: &str) -> Option> { + if let Some(type_symbol) = self.type_symbols.get(declared_name) { + Some(type_symbol.clone()) + } else { + for use_statement_symbol in self.use_statement_symbols.values() { + let borrowed = use_statement_symbol.borrow(); + if borrowed.declared_name() == declared_name { + if let Some(referenced_symbol) = borrowed.referenced_symbol() { + match *referenced_symbol { + Symbol::Type(type_symbol) => return Some(type_symbol.clone()), + _ => continue, + } + } + } + } + None + } + } + + fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option> { + self.type_symbols.values().find(|s| s.fqn() == fqn).cloned() + } + fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option { for function_symbol in self.function_symbols.values() { if function_symbol.borrow().fqn() == fqn { @@ -117,6 +140,45 @@ impl Scope { } None } + + fn get_expressible_by_declared_name(&self, declared_name: &str) -> Option { + self.variable_symbols + .get(declared_name) + .map(|s| Symbol::Variable(s.clone())) + .or_else(|| { + self.parameter_symbols + .get(declared_name) + .map(|p| Symbol::Parameter(p.clone())) + }) + .or_else(|| { + self.function_symbols + .get(declared_name) + .map(|f| Symbol::Function(f.clone())) + }) + .or_else(|| { + self.type_symbols + .get(declared_name) + .map(|t| Symbol::Type(t.clone())) + }) + .or_else(|| { + self.use_statement_symbols + .get(declared_name) + .map(|us| Symbol::UseStatement(us.clone())) + }) + } + + fn get_expressible_by_fqn(&self, fqn: &str) -> Option { + self.function_symbols + .values() + .find(|fs| fs.borrow().fqn() == fqn) + .map(|f| Symbol::Function(f.clone())) + .or_else(|| { + self.type_symbols + .values() + .find(|ts| ts.fqn() == fqn) + .map(|ts| Symbol::Type(ts.clone())) + }) + } } /* Symbol table */ @@ -280,6 +342,7 @@ impl SymbolTable { } } + #[deprecated(note = "Use more specific lookup methods.")] pub fn lookup(&self, name: &str, scope_id: usize) -> Result { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { @@ -295,6 +358,44 @@ impl SymbolTable { Err(NoDefinition) } + pub fn lookup_type_by_declared_name( + &self, + declared_name: &str, + scope_id: usize, + ) -> Result, SymbolLookupError> { + let mut scope_opt = Some(&self.scopes[scope_id]); + while let Some(scope) = scope_opt { + if let Some(symbol) = scope.get_type_symbol_by_declared_name(declared_name) { + return Ok(symbol); + } + scope_opt = if let Some(parent_id) = scope.parent { + Some(&self.scopes[parent_id]) + } else { + None + } + } + Err(NoDefinition) + } + + pub fn lookup_type_by_fqn( + &self, + fqn: &str, + scope_id: usize, + ) -> Result, SymbolLookupError> { + let mut scope_opt = Some(&self.scopes[scope_id]); + while let Some(scope) = scope_opt { + if let Some(symbol) = scope.get_type_symbol_by_fqn(fqn) { + return Ok(symbol); + } + scope_opt = if let Some(parent_id) = scope.parent { + Some(&self.scopes[parent_id]) + } else { + None + } + } + Err(NoDefinition) + } + pub fn lookup_usable_by_fqn( &self, fully_qualified_name: &str, @@ -307,6 +408,44 @@ impl SymbolTable { } Err(NoDefinition) } + + pub fn lookup_expressible_by_declared_name( + &self, + declared_name: &str, + scope_id: usize, + ) -> Result { + let mut scope_opt = Some(&self.scopes[scope_id]); + while let Some(scope) = scope_opt { + if let Some(symbol) = scope.get_expressible_by_declared_name(declared_name) { + return Ok(symbol); + } + scope_opt = if let Some(parent_id) = scope.parent { + Some(&self.scopes[parent_id]) + } else { + None + } + } + Err(NoDefinition) + } + + pub fn lookup_expressible_by_fqn( + &self, + fqn: &str, + scope_id: usize, + ) -> Result { + let mut scope_opt = Some(&self.scopes[scope_id]); + while let Some(scope) = scope_opt { + if let Some(symbol) = scope.get_expressible_by_fqn(fqn) { + return Ok(symbol); + } + scope_opt = if let Some(parent_id) = scope.parent { + Some(&self.scopes[parent_id]) + } else { + None + } + } + Err(NoDefinition) + } } impl Display for SymbolTable {