From d8fe97b401ef98f16457ce5c3323386d1de83412 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Wed, 21 May 2025 08:54:21 -0500 Subject: [PATCH] Miscellaneous gather work and related. --- src/name_analysis/fqn_context.rs | 4 +- src/name_analysis/gather.rs | 398 +++++++++++++++++++++++++----- src/name_analysis/symbol.rs | 71 +++++- src/name_analysis/symbol_table.rs | 74 ++---- src/std_core/mod.rs | 2 +- 5 files changed, 420 insertions(+), 129 deletions(-) diff --git a/src/name_analysis/fqn_context.rs b/src/name_analysis/fqn_context.rs index c5f51f0..7589f3a 100644 --- a/src/name_analysis/fqn_context.rs +++ b/src/name_analysis/fqn_context.rs @@ -7,8 +7,8 @@ impl FqnContext { FqnContext { stack: Vec::new() } } - pub fn push(&mut self, name: String) { - self.stack.push(name); + pub fn push(&mut self, name: &str) { + self.stack.push(name.to_string()); } pub fn pop(&mut self) { diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index 23eb1f2..4134ee9 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -132,12 +132,8 @@ fn gather_function_type_use( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - gather_generic_parameters( - &mut function_type_use.generics, - symbol_table, - fqn_context, - diagnostics, - ); + symbol_table.push_scope("FunctionTypeUseScope"); + gather_generic_parameters(&mut function_type_use.generics, symbol_table, diagnostics); gather_parameters( &mut function_type_use.parameters, symbol_table, @@ -150,6 +146,7 @@ fn gather_function_type_use( fqn_context, diagnostics, ); + symbol_table.pop_scope(); } /* Generic Arguments */ @@ -170,10 +167,28 @@ fn gather_generic_arguments( 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") + for identifier in &mut generic_parameters.0 { + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Generic(GenericTypeSymbol::new( + &identifier.name(), + SourceDefinition::from_identifier(identifier), + ))); + match insert_result { + Ok(_) => {} + Err(insert_error) => { + handle_insert_error( + insert_error, + &identifier.name(), + identifier.file_id(), + identifier.range(), + "Type", + diagnostics, + ); + } + } + } } /* Implements List */ @@ -259,22 +274,12 @@ fn gather_return_type( fqn_context, diagnostics, ); - gather_references( - &mut return_type.references, - symbol_table, - fqn_context, - diagnostics, - ); + gather_references(&mut return_type.references, symbol_table); } /* References */ -fn gather_references( - references: &mut References, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { +fn gather_references(references: &mut References, symbol_table: &mut SymbolTable) { for identifier in &mut references.0 { gather_identifier(identifier, symbol_table); } @@ -289,7 +294,7 @@ pub(super) fn gather_compilation_unit( ) { let mut fqn_context = FqnContext::new(); if let Some(namespace) = &compilation_unit.namespace { - fqn_context.push(namespace.name().to_string()); + fqn_context.push(&namespace.name()); } symbol_table.push_scope(&format!("FileScope({})", compilation_unit.file_name)); @@ -384,6 +389,14 @@ fn gather_module_level_declaration( Module(module_declaration) => { gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } Class(class_declaration) => { gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) } @@ -398,7 +411,6 @@ fn gather_module_level_declaration( diagnostics, ); } - _ => todo!(), } } @@ -408,7 +420,39 @@ fn gather_interface_level_declaration( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + use InterfaceLevelDeclaration::*; + match declaration { + Module(module_declaration) => { + gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); + } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Class(class_declaration) => { + gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) + } + Function(interface_function_declaration) => { + gather_interface_function_declaration( + interface_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + OperatorFunction(interface_operator_function_declaration) => { + gather_interface_operator_function_declaration( + interface_operator_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + } } fn gather_class_level_declaration( @@ -417,7 +461,53 @@ fn gather_class_level_declaration( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + use ClassLevelDeclaration::*; + match declaration { + Module(module_declaration) => { + gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); + } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Class(class_declaration) => { + gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics); + } + Function(function_definition) => { + gather_function_definition(function_definition, symbol_table, fqn_context, diagnostics); + } + OperatorFunction(operator_function_definition) => { + gather_operator_function_definition( + operator_function_definition, + symbol_table, + fqn_context, + diagnostics, + ); + } + PlatformFunction(platform_function_declaration) => { + gather_platform_function_definition( + platform_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Property(property_declaration) => { + gather_property_declaration( + property_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Field(field_declaration) => { + gather_field_declaration(field_declaration, symbol_table, fqn_context, diagnostics); + } + } } /* Main Declarations */ @@ -429,10 +519,11 @@ fn gather_module_declaration( diagnostics: &mut Vec, ) { // 1. Add mod identifier symbol - // 2. Update fqn context + // 2. Push identifier on fqn_context // 3. Push scope // 4. Process declarations // 5. Pop scope + // 6. Pop fqn_context let module_name = declaration.identifier.name(); @@ -443,24 +534,78 @@ fn gather_module_declaration( Some(&declaration.identifier), )); - if let Err(err) = insert_result { - handle_insert_error( - err, + match insert_result { + Ok(_) => { + fqn_context.push(&module_name); + symbol_table.push_scope(&format!("ModuleScope({})", module_name)); + + for inner_declaration in &mut declaration.declarations { + gather_module_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => handle_insert_error( + insert_error, &module_name, declaration.identifier.file_id(), declaration.identifier.range(), - "module/type", + "Module", diagnostics, - ) + ), } +} - fqn_context.push(module_name.to_string()); +fn gather_interface_declaration( + declaration: &mut InterfaceDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let interface_name = declaration.identifier.name(); - symbol_table.push_scope(&format!("ModuleScope({})", module_name)); - for inner_declaration in &mut declaration.declarations { - gather_module_level_declaration(inner_declaration, symbol_table, fqn_context, diagnostics); + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( + &fqn_context.resolve(&interface_name), + &interface_name, + declaration.is_public, + Some(&declaration.identifier), + ))); + + match insert_result { + Ok(_) => { + fqn_context.push(&interface_name); + symbol_table.push_scope(&format!("InterfaceScope({})", interface_name)); + + for inner_declaration in &mut declaration.declarations { + gather_interface_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &interface_name, + declaration.identifier.file_id(), + declaration.identifier.range(), + "Interface", + diagnostics, + ); + } } - symbol_table.pop_scope() } fn gather_class_declaration( @@ -469,27 +614,58 @@ fn gather_class_declaration( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - let declared_name = class_declaration.identifier.name(); - let resolved_name = fqn_context.resolve(&declared_name); + let class_name = class_declaration.identifier.name(); - let insert_result = symbol_table.insert_type_symbol(TypeSymbol::new( - &resolved_name, - &declared_name, - class_declaration.is_public, - Some(&class_declaration.identifier), - )); - if let Err(err) = insert_result { - handle_insert_error( - err, - &declared_name, - class_declaration.identifier.file_id(), - class_declaration.identifier.range(), - "interface/class", - diagnostics, - ); + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( + &fqn_context.resolve(&class_name), + &class_name, + class_declaration.is_public, + Some(&class_declaration.identifier), + ))); + + match insert_result { + Ok(_) => { + // Do this first so we can't implement generic parameters! + gather_implements_list( + &mut class_declaration.implements, + symbol_table, + fqn_context, + diagnostics, + ); + + fqn_context.push(&class_name); + symbol_table.push_scope(&format!("ClassScope({})", class_name)); + + gather_generic_parameters(&mut class_declaration.generics, symbol_table, diagnostics); + + if let Some(class_constructor) = &mut class_declaration.class_constructor { + gather_class_constructor(class_constructor, symbol_table, fqn_context, diagnostics); + } + + for inner_declaration in &mut class_declaration.declarations { + gather_class_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &class_name, + class_declaration.identifier.file_id(), + class_declaration.identifier.range(), + "interface/class", + diagnostics, + ); + } } - - // todo: scopes, generics, etc. } /* Function declarations and components */ @@ -646,7 +822,57 @@ fn gather_interface_function_declaration( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + let name = declaration.identifier.name(); + let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( + &fqn_context.resolve(&name), + &name, + true, + false, + Some(&declaration.identifier), + )); + + match insert_result { + Ok(function_symbol) => { + symbol_table.push_scope(&format!("FunctionParameterScope({})", &name)); + + gather_generic_parameters(&mut declaration.generics, symbol_table, diagnostics); + + let parameters = gather_parameters( + &mut declaration.parameters, + symbol_table, + fqn_context, + diagnostics, + ); + if let Some(parameter_symbols) = parameters { + function_symbol + .borrow_mut() + .set_parameters(parameter_symbols); + } + + gather_return_type( + &mut declaration.return_type, + symbol_table, + fqn_context, + diagnostics, + ); + + if let Some(body) = &mut declaration.body { + gather_function_body(body, symbol_table, fqn_context, diagnostics); + } + + symbol_table.pop_scope(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &name, + declaration.identifier.file_id(), + declaration.identifier.range(), + "Interface Function", + diagnostics, + ); + } + } } fn gather_interface_operator_function_declaration( @@ -666,6 +892,7 @@ fn gather_function_body( ) { use crate::ast::FunctionBody::*; match function_body { + Equals(expression) => gather_expression(expression, symbol_table, diagnostics), Block(block) => gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics), _ => todo!(), } @@ -819,7 +1046,13 @@ fn gather_if_statement( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + gather_expression(&mut if_statement.condition, symbol_table, diagnostics); + gather_block_statement( + &mut if_statement.then_block, + symbol_table, + fqn_context, + diagnostics, + ); } fn gather_if_else_statement( @@ -828,7 +1061,18 @@ fn gather_if_else_statement( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + gather_if_statement( + &mut if_else_statement.if_statement, + symbol_table, + fqn_context, + diagnostics, + ); + for if_statement in &mut if_else_statement.else_ifs.0 { + gather_if_statement(if_statement, symbol_table, fqn_context, diagnostics); + } + if let Some(else_block) = &mut if_else_statement.else_block { + gather_block_statement(&mut else_block.0, symbol_table, fqn_context, diagnostics); + } } fn gather_while_statement( @@ -837,7 +1081,13 @@ fn gather_while_statement( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + gather_expression(&mut while_statement.condition, symbol_table, diagnostics); + gather_block_statement( + &mut while_statement.body, + symbol_table, + fqn_context, + diagnostics, + ); } fn gather_for_statement( @@ -846,7 +1096,37 @@ fn gather_for_statement( fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { - todo!() + gather_expression(&mut for_statement.iterator, symbol_table, diagnostics); + symbol_table.push_scope("ForStatementScope"); + let variable_identifier = &mut for_statement.variable; + let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( + &variable_identifier.name(), + false, + Some(variable_identifier), + )); + + match insert_result { + Ok(_) => { + gather_block_statement_inner( + &mut for_statement.body, + symbol_table, + fqn_context, + diagnostics, + ); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &variable_identifier.name(), + variable_identifier.file_id(), + variable_identifier.range(), + "variable", + diagnostics, + ); + } + } + + symbol_table.pop_scope(); } /* Expressions */ diff --git a/src/name_analysis/symbol.rs b/src/name_analysis/symbol.rs index 300794b..03a53fe 100644 --- a/src/name_analysis/symbol.rs +++ b/src/name_analysis/symbol.rs @@ -1,9 +1,10 @@ +use crate::ast::named::Named; use crate::ast::{Identifier, UseStatement}; use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter}; +use std::ops::Deref; use std::range::Range; use std::rc::Rc; -use crate::ast::named::Named; #[derive(Clone, Debug)] pub struct SourceDefinition { @@ -66,7 +67,10 @@ impl Symbol { match self { Symbol::UseStatement(s) => s.borrow().definition(), Symbol::Module(s) => s.definition(), - Symbol::Type(s) => s.definition(), + Symbol::Type(s) => match s.deref() { + TypeSymbol::Concrete(cts) => cts.definition(), + TypeSymbol::Generic(gts) => gts.definition(), + }, Symbol::Function(s) => s.borrow().definition(), Symbol::Parameter(s) => s.definition(), Symbol::Variable(s) => s.definition(), @@ -180,21 +184,36 @@ impl Debug for ModuleSymbol { /* TypeSymbol */ -pub struct TypeSymbol { +#[derive(Debug)] +pub enum TypeSymbol { + Concrete(ConcreteTypeSymbol), + Generic(GenericTypeSymbol), +} + +impl TypeSymbol { + pub fn declared_name(&self) -> &str { + match self { + TypeSymbol::Concrete(t) => t.declared_name(), + TypeSymbol::Generic(t) => t.declared_name(), + } + } +} + +pub struct ConcreteTypeSymbol { fqn: String, declared_name: String, is_public: bool, definition: Option, } -impl TypeSymbol { +impl ConcreteTypeSymbol { pub fn new( fqn: &str, declared_name: &str, is_public: bool, identifier: Option<&Identifier>, ) -> Self { - TypeSymbol { + ConcreteTypeSymbol { fqn: fqn.to_string(), declared_name: declared_name.to_string(), is_public, @@ -211,7 +230,7 @@ impl TypeSymbol { } } -impl SymbolInner for TypeSymbol { +impl SymbolInner for ConcreteTypeSymbol { fn declared_name(&self) -> &str { &self.declared_name } @@ -221,7 +240,7 @@ impl SymbolInner for TypeSymbol { } } -impl Debug for TypeSymbol { +impl Debug for ConcreteTypeSymbol { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("TypeSymbol") .field("fqn", &self.fqn) @@ -231,6 +250,38 @@ impl Debug for TypeSymbol { } } +pub struct GenericTypeSymbol { + declared_name: String, + source_definition: SourceDefinition, +} + +impl GenericTypeSymbol { + pub fn new(declared_name: &str, source_definition: SourceDefinition) -> Self { + GenericTypeSymbol { + declared_name: declared_name.to_string(), + source_definition, + } + } +} + +impl SymbolInner for GenericTypeSymbol { + fn declared_name(&self) -> &str { + self.declared_name.as_str() + } + + fn definition(&self) -> Option { + Some(self.source_definition.clone()) + } +} + +impl Debug for GenericTypeSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("GenericTypeSymbol") + .field("declared_name", &self.declared_name) + .finish() + } +} + /* Function */ pub struct FunctionSymbol { @@ -240,7 +291,7 @@ pub struct FunctionSymbol { is_platform: bool, definition: Option, parameters: Vec>, - return_type: Option>, + return_type: Option>, } impl FunctionSymbol { @@ -277,7 +328,7 @@ impl FunctionSymbol { } } - pub fn with_return_type(self, return_type: TypeSymbol) -> Self { + pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self { Self { fqn: self.fqn, declared_name: self.declared_name, @@ -297,7 +348,7 @@ impl FunctionSymbol { self.parameters = parameters; } - pub fn set_return_type(&mut self, return_type: Rc) { + pub fn set_return_type(&mut self, return_type: Rc) { self.return_type = Some(return_type); } } diff --git a/src/name_analysis/symbol_table.rs b/src/name_analysis/symbol_table.rs index dfd96c5..8419cc6 100644 --- a/src/name_analysis/symbol_table.rs +++ b/src/name_analysis/symbol_table.rs @@ -1,12 +1,10 @@ -use crate::name_analysis::symbol::{ - FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, - UseStatementSymbol, VariableSymbol, -}; +use crate::name_analysis::symbol::*; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Display; +use std::ops::Deref; use std::rc::Rc; /* Scope */ @@ -36,37 +34,6 @@ impl Scope { } } - fn get_any_symbol(&self, name: &str) -> Option { - self.variable_symbols - .get(name) - .map(|s| Symbol::Variable(s.clone())) - .or_else(|| { - self.parameter_symbols - .get(name) - .map(|s| Symbol::Parameter(s.clone())) - }) - .or_else(|| { - self.function_symbols - .get(name) - .map(|s| Symbol::Function(s.clone())) - }) - .or_else(|| { - self.type_symbols - .get(name) - .map(|ts| Symbol::Type(ts.clone())) - }) - .or_else(|| { - self.module_symbols - .get(name) - .map(|ms| Symbol::Module(ms.clone())) - }) - .or_else(|| { - self.use_statement_symbols - .get(name) - .map(|us| Symbol::UseStatement(us.clone())) - }) - } - fn get_module_symbol_by_declared_name(&self, name: &str) -> Option> { for module_symbol in self.module_symbols.values() { if module_symbol.declared_name() == name { @@ -96,7 +63,13 @@ impl Scope { } fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option> { - self.type_symbols.values().find(|s| s.fqn() == fqn).cloned() + self.type_symbols + .values() + .find(|s| match s.deref().deref() { + TypeSymbol::Concrete(cts) => cts.fqn() == fqn, + _ => false, + }) + .cloned() } fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option { @@ -106,8 +79,13 @@ impl Scope { } } for type_symbol in self.type_symbols.values() { - if type_symbol.fqn() == fqn { - return Some(Symbol::Type(type_symbol.clone())); + match type_symbol.deref() { + TypeSymbol::Concrete(concrete_type_symbol) => { + if concrete_type_symbol.fqn() == fqn { + return Some(Symbol::Type(type_symbol.clone())); + } + } + _ => continue, } } None @@ -173,9 +151,7 @@ impl Scope { .find(|fs| fs.borrow().fqn() == fqn) .map(|f| Symbol::Function(f.clone())) .or_else(|| { - self.type_symbols - .values() - .find(|ts| ts.fqn() == fqn) + self.get_type_symbol_by_fqn(fqn) .map(|ts| Symbol::Type(ts.clone())) }) } @@ -342,22 +318,6 @@ 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 { - if let Some(symbol) = scope.get_any_symbol(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_declared_name( &self, declared_name: &str, diff --git a/src/std_core/mod.rs b/src/std_core/mod.rs index 733e853..15228d6 100644 --- a/src/std_core/mod.rs +++ b/src/std_core/mod.rs @@ -1,4 +1,4 @@ -use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol, TypeSymbol}; +use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol}; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {