Work on star-use symbols.
This commit is contained in:
parent
5721bd1e83
commit
d653d26e14
@ -1,9 +1,4 @@
|
||||
use crate::ast::node::{
|
||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody,
|
||||
GenericParameters, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration, Parameters,
|
||||
PrimitiveType, ReturnType, TypeUse, TypedArray, UseStatement, UseStatementIdentifier,
|
||||
UseStatementPrefix,
|
||||
};
|
||||
use crate::ast::node::{CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody, GenericParameters, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration, Parameters, PrimitiveType, ReturnType, StarUseStatement, TypeUse, TypedArray, UseStatement, UseStatementIdentifier, UseStatementPrefix};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol;
|
||||
@ -13,9 +8,9 @@ use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::name_analysis::symbol::primitive_type_symbol::PrimitiveTypeSymbol;
|
||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::ConcreteUseSymbol;
|
||||
use crate::name_analysis::symbol_table::SymbolTable;
|
||||
use crate::name_analysis::util::{format_fqn, handle_insert_error, handle_lookup_error};
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
use crate::name_analysis::util::{format_fqn, handle_insert_error, handle_lookup_error, join_fqn_parts};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -60,7 +55,7 @@ fn na_p1_use_statement(
|
||||
na_p1_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
UseStatement::StarUseStatement(star_use_statement) => {
|
||||
todo!()
|
||||
na_p1_star_use_statement(star_use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,7 +95,7 @@ fn na_p1_concrete_use_statement(
|
||||
}
|
||||
|
||||
fn handle_concrete_use_statement_identifier(
|
||||
prefixes: &Vec<Rc<str>>,
|
||||
prefixes: &[Rc<str>],
|
||||
use_statement_identifier: &mut UseStatementIdentifier,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -134,6 +129,38 @@ fn handle_concrete_use_statement_identifier(
|
||||
}
|
||||
}
|
||||
|
||||
fn na_p1_star_use_statement(
|
||||
star_use_statement: &mut StarUseStatement,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let fqn_parts = star_use_statement
|
||||
.prefixes()
|
||||
.map(UseStatementPrefix::identifier)
|
||||
.map(Identifier::name)
|
||||
.map(|name| Rc::from(name))
|
||||
.collect::<Vec<Rc<str>>>();
|
||||
|
||||
let to_insert = StarUseSymbol::new(
|
||||
&fqn_parts,
|
||||
Some(SourceDefinition::from_star_use_statement(star_use_statement))
|
||||
);
|
||||
match symbol_table.insert_star_use_symbol(to_insert) {
|
||||
Ok(star_use_symbol) => {
|
||||
star_use_statement.set_symbol(star_use_symbol);
|
||||
}
|
||||
Err(symbol_insert_error) => {
|
||||
handle_insert_error(
|
||||
symbol_insert_error,
|
||||
&join_fqn_parts(&fqn_parts),
|
||||
star_use_statement.file_id(),
|
||||
star_use_statement.range(),
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn na_p1_module_level_declaration(
|
||||
module_level_declaration: &mut ModuleLevelDeclaration,
|
||||
symbol_table: &mut SymbolTable,
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
use crate::ast::node::{
|
||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Identifier, UseStatement,
|
||||
UseStatementIdentifier, UseStatementPrefix,
|
||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Identifier,
|
||||
StarUseStatement, UseStatement, UseStatementIdentifier, UseStatementPrefix,
|
||||
};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||
use crate::name_analysis::util::handle_lookup_error;
|
||||
use crate::name_analysis::util::{handle_lookup_error, join_fqn_parts};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn na_p2_compilation_unit(
|
||||
compilation_unit: &mut CompilationUnit,
|
||||
@ -29,7 +30,7 @@ fn na_p2_use_statement(
|
||||
na_p2_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
UseStatement::StarUseStatement(star_use_statement) => {
|
||||
todo!()
|
||||
na_p2_star_use_statement(star_use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,12 +40,12 @@ fn na_p2_concrete_use_statement(
|
||||
symbol_table: &SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let base_fqn_parts: Vec<String> = concrete_use_statement
|
||||
let base_fqn_parts = concrete_use_statement
|
||||
.prefixes()
|
||||
.map(UseStatementPrefix::identifier)
|
||||
.map(Identifier::name)
|
||||
.map(ToString::to_string)
|
||||
.collect();
|
||||
.map(Rc::from)
|
||||
.collect::<Vec<Rc<str>>>();
|
||||
|
||||
match concrete_use_statement.suffix_mut() {
|
||||
ConcreteUseStatementSuffix::UseStatementIdentifier(use_statement_identifier) => {
|
||||
@ -69,17 +70,14 @@ fn na_p2_concrete_use_statement(
|
||||
}
|
||||
|
||||
fn handle_concrete_use_statement_identifier(
|
||||
base_fqn_parts: &[String],
|
||||
base_fqn_parts: &[Rc<str>],
|
||||
use_statement_identifier: &mut UseStatementIdentifier,
|
||||
symbol_table: &SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let fqn_parts = {
|
||||
let mut all_parts: Vec<&str> = vec![];
|
||||
for part in base_fqn_parts {
|
||||
all_parts.push(part);
|
||||
}
|
||||
all_parts.push(use_statement_identifier.identifier().name());
|
||||
let mut all_parts = base_fqn_parts.to_vec();
|
||||
all_parts.push(Rc::from(use_statement_identifier.identifier().name()));
|
||||
all_parts
|
||||
};
|
||||
|
||||
@ -93,10 +91,32 @@ fn handle_concrete_use_statement_identifier(
|
||||
} else {
|
||||
handle_lookup_error(
|
||||
SymbolLookupError::NoDefinition,
|
||||
&fqn_parts.join("::"),
|
||||
&join_fqn_parts(&fqn_parts),
|
||||
use_statement_identifier.identifier().file_id(),
|
||||
use_statement_identifier.identifier().range(),
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn na_p2_star_use_statement(
|
||||
star_use_statement: &mut StarUseStatement,
|
||||
symbol_table: &SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let mut symbol_ref_mut = star_use_statement.symbol().unwrap().borrow_mut();
|
||||
match symbol_table.find_usable_symbols_by_base_fqn(symbol_ref_mut.fqn_parts()) {
|
||||
Ok(usable_symbols) => {
|
||||
symbol_ref_mut.set_resolved_symbols(usable_symbols);
|
||||
}
|
||||
Err(symbol_lookup_error) => {
|
||||
handle_lookup_error(
|
||||
symbol_lookup_error,
|
||||
&join_fqn_parts(symbol_ref_mut.fqn_parts()),
|
||||
star_use_statement.file_id(),
|
||||
star_use_statement.range(),
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::ast::node::{Identifier, Operator};
|
||||
use crate::ast::node::{Identifier, Operator, StarUseStatement};
|
||||
use std::range::Range;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -14,7 +14,7 @@ impl SourceDefinition {
|
||||
range: identifier.range(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn from_operator(operator: &Operator) -> Self {
|
||||
Self {
|
||||
file_id: operator.file_id(),
|
||||
@ -22,6 +22,13 @@ impl SourceDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_star_use_statement(star_use_statement: &StarUseStatement) -> Self {
|
||||
Self {
|
||||
file_id: star_use_statement.file_id(),
|
||||
range: star_use_statement.range(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_id(&self) -> usize {
|
||||
self.file_id
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ use crate::name_analysis::symbol::Symbol;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UsableSymbol {
|
||||
Interface(Rc<RefCell<InterfaceSymbol>>),
|
||||
Class(Rc<RefCell<ClassSymbol>>),
|
||||
|
||||
@ -76,6 +76,7 @@ impl Debug for ConcreteUseSymbol {
|
||||
pub struct StarUseSymbol {
|
||||
fqn_parts: Vec<Rc<str>>,
|
||||
source_definition: Option<SourceDefinition>,
|
||||
resolved_symbols: Vec<UsableSymbol>,
|
||||
}
|
||||
|
||||
impl StarUseSymbol {
|
||||
@ -83,12 +84,21 @@ impl StarUseSymbol {
|
||||
Self {
|
||||
fqn_parts: fqn_parts.to_vec(),
|
||||
source_definition,
|
||||
resolved_symbols: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fqn_parts(&self) -> &[Rc<str>] {
|
||||
&self.fqn_parts
|
||||
}
|
||||
|
||||
pub fn resolved_symbols(&self) -> &[UsableSymbol] {
|
||||
&self.resolved_symbols
|
||||
}
|
||||
|
||||
pub fn set_resolved_symbols(&mut self, symbols: Vec<UsableSymbol>) {
|
||||
self.resolved_symbols = symbols;
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol for StarUseSymbol {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol;
|
||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||
use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
|
||||
@ -12,7 +13,6 @@ use std::cell::RefCell;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol;
|
||||
|
||||
pub(self) mod fqn_context;
|
||||
mod scope;
|
||||
@ -25,6 +25,7 @@ pub enum SymbolInsertError {
|
||||
|
||||
pub enum SymbolLookupError {
|
||||
NoDefinition,
|
||||
NoSuchNamespace,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -95,7 +96,7 @@ impl SymbolTable {
|
||||
parts
|
||||
}
|
||||
|
||||
pub fn find_usable_symbol(&self, fqn_parts: &[&str]) -> Option<UsableSymbol> {
|
||||
pub fn find_usable_symbol(&self, fqn_parts: &[Rc<str>]) -> Option<UsableSymbol> {
|
||||
self.symbol_tree
|
||||
.find_interface(fqn_parts)
|
||||
.map(|interface_symbol| UsableSymbol::Interface(interface_symbol))
|
||||
@ -111,6 +112,13 @@ impl SymbolTable {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn find_usable_symbols_by_base_fqn(
|
||||
&self,
|
||||
fqn_parts: &[Rc<str>],
|
||||
) -> Result<Vec<UsableSymbol>, SymbolLookupError> {
|
||||
self.symbol_tree.find_all_by_base_fqn(fqn_parts)
|
||||
}
|
||||
|
||||
fn current_scope(&self) -> &Scope {
|
||||
&self.scopes[self.current_scope_id]
|
||||
}
|
||||
@ -179,15 +187,20 @@ impl SymbolTable {
|
||||
Ok(inserted)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn insert_generic_type_symbol(
|
||||
&mut self,
|
||||
generic_type_symbol: GenericTypeSymbol,
|
||||
) -> Result<Rc<RefCell<GenericTypeSymbol>>, SymbolInsertError> {
|
||||
if let Some(defined_symbol) = self.current_scope().find_type_symbol(generic_type_symbol.declared_name()) {
|
||||
if let Some(defined_symbol) = self
|
||||
.current_scope()
|
||||
.find_type_symbol(generic_type_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol.to_symbol()))
|
||||
} else {
|
||||
let inserted = self.current_scope_mut().insert_generic_type_symbol(generic_type_symbol);
|
||||
let inserted = self
|
||||
.current_scope_mut()
|
||||
.insert_generic_type_symbol(generic_type_symbol);
|
||||
Ok(inserted)
|
||||
}
|
||||
}
|
||||
@ -205,7 +218,7 @@ impl SymbolTable {
|
||||
}
|
||||
Err(SymbolLookupError::NoDefinition)
|
||||
}
|
||||
|
||||
|
||||
pub fn lookup_type_by_fqn(&self, fqn_parts: &[&str]) -> Result<TypeSymbol, SymbolLookupError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ use crate::name_analysis::symbol::class_symbol::ClassSymbol;
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
|
||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||
use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
|
||||
use crate::name_analysis::symbol_table::SymbolLookupError;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@ -24,35 +26,35 @@ impl SymbolTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_class(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<ClassSymbol>>> {
|
||||
pub fn find_class(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<ClassSymbol>>> {
|
||||
match fqn_parts.len() {
|
||||
0 => None,
|
||||
1 => self.classes.get(fqn_parts[0]).cloned(),
|
||||
1 => self.classes.get(&fqn_parts[0]).cloned(),
|
||||
_ => self
|
||||
.children
|
||||
.get(fqn_parts[0])
|
||||
.get(&fqn_parts[0])
|
||||
.and_then(|child_tree| child_tree.find_class(&fqn_parts[1..])),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_interface(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<InterfaceSymbol>>> {
|
||||
pub fn find_interface(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<InterfaceSymbol>>> {
|
||||
match fqn_parts.len() {
|
||||
0 => None,
|
||||
1 => self.interfaces.get(fqn_parts[0]).cloned(),
|
||||
1 => self.interfaces.get(&fqn_parts[0]).cloned(),
|
||||
_ => self
|
||||
.children
|
||||
.get(fqn_parts[0])
|
||||
.get(&fqn_parts[0])
|
||||
.and_then(|child_tree| child_tree.find_interface(&fqn_parts[1..])),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_function(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<FunctionSymbol>>> {
|
||||
pub fn find_function(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<FunctionSymbol>>> {
|
||||
match fqn_parts.len() {
|
||||
0 => None,
|
||||
1 => self.functions.get(fqn_parts[0]).cloned(),
|
||||
1 => self.functions.get(&fqn_parts[0]).cloned(),
|
||||
_ => self
|
||||
.children
|
||||
.get(fqn_parts[0])
|
||||
.get(&fqn_parts[0])
|
||||
.and_then(|child_tree| child_tree.find_function(&fqn_parts[1..])),
|
||||
}
|
||||
}
|
||||
@ -79,15 +81,19 @@ impl SymbolTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn register_function(&mut self, function_symbol: Rc<RefCell<FunctionSymbol>>) {
|
||||
let fqn_parts = function_symbol.borrow().fqn_parts_owned();
|
||||
self.recurse_register_function(function_symbol, &fqn_parts);
|
||||
self.recurse_register_function(function_symbol, &fqn_parts);
|
||||
}
|
||||
|
||||
fn recurse_register_function(&mut self, function_symbol: Rc<RefCell<FunctionSymbol>>, fqn_parts: &[Rc<str>]) {
|
||||
|
||||
fn recurse_register_function(
|
||||
&mut self,
|
||||
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
||||
fqn_parts: &[Rc<str>],
|
||||
) {
|
||||
if fqn_parts.len() == 0 {
|
||||
panic!("Unable to register function fqn with no parts.")
|
||||
panic!("Unable to register function fqn with no parts.");
|
||||
}
|
||||
if fqn_parts.len() == 1 {
|
||||
self.functions.insert(fqn_parts[0].clone(), function_symbol);
|
||||
@ -100,5 +106,33 @@ impl SymbolTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn find_all_by_base_fqn(
|
||||
&self,
|
||||
fqn_parts: &[Rc<str>],
|
||||
) -> Result<Vec<UsableSymbol>, SymbolLookupError> {
|
||||
match fqn_parts.len() {
|
||||
0 => {
|
||||
let mut all_symbols: Vec<UsableSymbol> = vec![];
|
||||
for interface_symbol in self.interfaces.values() {
|
||||
all_symbols.push(UsableSymbol::Interface(interface_symbol.clone()));
|
||||
}
|
||||
for class_symbol in self.classes.values() {
|
||||
all_symbols.push(UsableSymbol::Class(class_symbol.clone()));
|
||||
}
|
||||
for function_symbol in self.functions.values() {
|
||||
all_symbols.push(UsableSymbol::Function(function_symbol.clone()));
|
||||
}
|
||||
Ok(all_symbols)
|
||||
}
|
||||
_ => {
|
||||
if self.children.contains_key(fqn_parts[0].as_ref()) {
|
||||
let child = self.children.get(fqn_parts[0].as_ref()).unwrap();
|
||||
child.find_all_by_base_fqn(fqn_parts)
|
||||
} else {
|
||||
Err(SymbolLookupError::NoSuchNamespace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,11 +45,19 @@ pub fn handle_lookup_error(
|
||||
match err {
|
||||
SymbolLookupError::NoDefinition => {
|
||||
let diagnostic = Diagnostic::error()
|
||||
.with_message(format!("No such symbol '{}' in scope.", error_symbol_name,))
|
||||
.with_message(format!("No such symbol '{}' in scope.", error_symbol_name))
|
||||
.with_label(
|
||||
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
|
||||
);
|
||||
diagnostics.push(diagnostic);
|
||||
},
|
||||
SymbolLookupError::NoSuchNamespace => {
|
||||
let diagnostic = Diagnostic::error()
|
||||
.with_message(format!("No such namespace '{}' found", error_symbol_name))
|
||||
.with_label(
|
||||
Label::primary(error_file_id, error_range).with_message("Namespace used here.")
|
||||
);
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,6 +281,10 @@ StarUseStatement:
|
||||
- range:
|
||||
special:
|
||||
kind: range
|
||||
fields:
|
||||
- symbol:
|
||||
kind: StarUseSymbol
|
||||
wrap: rc_ref_cell
|
||||
UseStatementPrefix:
|
||||
struct:
|
||||
children:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user