99 lines
3.3 KiB
Rust
99 lines
3.3 KiB
Rust
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
|
|
use crate::diagnostic::DmDiagnostic;
|
|
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
|
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
|
use crate::name_analysis::util::use_statement_base_fqn;
|
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
|
use std::range::Range;
|
|
|
|
fn handle_lookup_error(
|
|
err: SymbolLookupError,
|
|
error_symbol_name: &str,
|
|
error_file_id: usize,
|
|
error_range: Range<usize>,
|
|
symbol_types: &str,
|
|
diagnostics: &mut Vec<DmDiagnostic>,
|
|
) {
|
|
match err {
|
|
SymbolLookupError::NoDefinition => {
|
|
let diagnostic = Diagnostic::error()
|
|
.with_message(format!(
|
|
"No such {} symbol '{}' in scope.",
|
|
symbol_types, error_symbol_name,
|
|
))
|
|
.with_label(
|
|
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
|
|
);
|
|
diagnostics.push(diagnostic);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn nap2_compilation_unit(
|
|
compilation_unit: &mut CompilationUnit,
|
|
symbol_table: &SymbolTable,
|
|
diagnostics: &mut Vec<DmDiagnostic>,
|
|
) {
|
|
// TODO: check namespace for proper file name
|
|
for use_statement in compilation_unit.use_statements_mut() {
|
|
nap2_use_statement(use_statement, symbol_table, diagnostics);
|
|
}
|
|
|
|
// TODO: declarations
|
|
}
|
|
|
|
fn nap2_use_statement(
|
|
use_statement: &mut UseStatement,
|
|
symbol_table: &SymbolTable,
|
|
diagnostics: &mut Vec<DmDiagnostic>,
|
|
) {
|
|
let base_fqn = use_statement_base_fqn(use_statement);
|
|
|
|
let mut handle_concrete_use_symbol = |identifier: &Identifier| {
|
|
let fqn = format!("{}::{}", base_fqn, identifier.name());
|
|
match symbol_table.resolve_concrete_usable_by_fqn(&fqn) {
|
|
Ok(resolved_symbol) => match *use_statement.use_symbol().unwrap().borrow() {
|
|
UseSymbol::Concrete(ref concrete_use_symbol) => {
|
|
concrete_use_symbol
|
|
.borrow_mut()
|
|
.set_resolved_symbol(resolved_symbol);
|
|
}
|
|
_ => panic!("Unexpected symbol type"),
|
|
},
|
|
Err(lookup_error) => {
|
|
handle_lookup_error(
|
|
lookup_error,
|
|
&fqn,
|
|
use_statement.file_id(),
|
|
use_statement.range(),
|
|
"Usable Symbol",
|
|
diagnostics,
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
match use_statement.suffix() {
|
|
UseStatementSuffix::Identifier(identifier) => {
|
|
handle_concrete_use_symbol(identifier);
|
|
}
|
|
UseStatementSuffix::Star => {
|
|
if let Err(error) = symbol_table.resolve_usable_star(&base_fqn) {
|
|
handle_lookup_error(
|
|
error,
|
|
&base_fqn,
|
|
use_statement.file_id(),
|
|
use_statement.range(),
|
|
"Star Usable Symbol",
|
|
diagnostics,
|
|
);
|
|
}
|
|
}
|
|
UseStatementSuffix::UseList(use_list) => {
|
|
for identifier in use_list.identifiers() {
|
|
handle_concrete_use_symbol(identifier);
|
|
}
|
|
}
|
|
}
|
|
}
|