Much work on use-statements and symbols.
This commit is contained in:
parent
8cd5e588a0
commit
4f74136d97
@ -794,6 +794,7 @@ fn build_field_declaration(file_id: usize, field_pair: Pair<Rule>) -> FieldDecla
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement {
|
fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement {
|
||||||
|
let as_span = use_statement_pair.as_span();
|
||||||
let mut inner = use_statement_pair.into_inner();
|
let mut inner = use_statement_pair.into_inner();
|
||||||
let inner_length = inner.len();
|
let inner_length = inner.len();
|
||||||
|
|
||||||
@ -834,10 +835,15 @@ fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UseStatement {
|
UseStatement::new(
|
||||||
identifiers,
|
identifiers,
|
||||||
last: last.unwrap(),
|
last.unwrap(),
|
||||||
}
|
file_id,
|
||||||
|
Range {
|
||||||
|
start: as_span.start(),
|
||||||
|
end: as_span.end(),
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_block_statement(file_id: usize, block_statement_pair: Pair<Rule>) -> BlockStatement {
|
fn build_block_statement(file_id: usize, block_statement_pair: Pair<Rule>) -> BlockStatement {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
use crate::ast::named::Named;
|
||||||
use crate::name_analysis::symbol::Symbol;
|
use crate::name_analysis::symbol::Symbol;
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::range::Range;
|
use std::range::Range;
|
||||||
|
|
||||||
pub mod build;
|
pub mod build;
|
||||||
@ -455,6 +457,97 @@ pub struct FieldDeclaration {
|
|||||||
pub struct UseStatement {
|
pub struct UseStatement {
|
||||||
pub identifiers: Vec<Identifier>,
|
pub identifiers: Vec<Identifier>,
|
||||||
pub last: UseStatementLast,
|
pub last: UseStatementLast,
|
||||||
|
pub file_id: usize,
|
||||||
|
pub range: Range<usize>,
|
||||||
|
scope_id: Option<usize>,
|
||||||
|
symbol: Option<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// First is declared_name, second is fully_qualified_name
|
||||||
|
pub type UseStatementName = (String, String);
|
||||||
|
|
||||||
|
impl UseStatement {
|
||||||
|
pub fn new(
|
||||||
|
identifiers: Vec<Identifier>,
|
||||||
|
last: UseStatementLast,
|
||||||
|
file_id: usize,
|
||||||
|
range: Range<usize>,
|
||||||
|
) -> Self {
|
||||||
|
UseStatement {
|
||||||
|
identifiers,
|
||||||
|
last,
|
||||||
|
file_id,
|
||||||
|
range,
|
||||||
|
scope_id: None,
|
||||||
|
symbol: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 names(&self) -> Vec<UseStatementName> {
|
||||||
|
let base_name = self.base_name();
|
||||||
|
use UseStatementLast::*;
|
||||||
|
match &self.last {
|
||||||
|
Identifier(identifier) => vec![(
|
||||||
|
identifier.name().to_string(),
|
||||||
|
base_name.to_string() + "::" + &identifier.name(),
|
||||||
|
)],
|
||||||
|
Identifiers(identifiers) => {
|
||||||
|
let mut names = Vec::new();
|
||||||
|
for identifier in identifiers {
|
||||||
|
names.push((
|
||||||
|
identifier.name().to_string(),
|
||||||
|
base_name.to_string() + "::" + &identifier.name(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
names
|
||||||
|
}
|
||||||
|
Star => panic!("Cannot call names() on a star UseStatement"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_star(&self) -> bool {
|
||||||
|
match &self.last {
|
||||||
|
UseStatementLast::Star => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_scope_id(&mut self, scope_id: usize) {
|
||||||
|
self.scope_id = Some(scope_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scope_id(&self) -> Option<usize> {
|
||||||
|
self.scope_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_symbol(&mut self, symbol: Symbol) {
|
||||||
|
self.symbol = Some(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(&self) -> &Option<Symbol> {
|
||||||
|
&self.symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use crate::ast::named::Named;
|
use crate::ast::named::Named;
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::name_analysis::fqn_context::FqnContext;
|
use crate::name_analysis::fqn_context::FqnContext;
|
||||||
use crate::name_analysis::symbol::{
|
use crate::name_analysis::symbol::*;
|
||||||
ClassSymbol, FunctionSymbol, ModuleSymbol, SourceDefinition, Symbol, VariableSymbol,
|
use crate::name_analysis::symbol_table::{ScopeLevel, SymbolInsertError, SymbolTable};
|
||||||
};
|
|
||||||
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
|
||||||
use crate::name_analysis::DiagnosticsContainer;
|
use crate::name_analysis::DiagnosticsContainer;
|
||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
use std::range::Range;
|
use std::range::Range;
|
||||||
@ -121,7 +119,74 @@ fn gather_generic_arguments(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn gather_module_level_declaration(
|
pub(super) fn gather_compilation_unit(
|
||||||
|
compilation_unit: &mut CompilationUnit,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
|
) {
|
||||||
|
let mut fqn_context = FqnContext::new();
|
||||||
|
if let Some(namespace) = &compilation_unit.namespace {
|
||||||
|
fqn_context.push(namespace.name().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table.push_scope(
|
||||||
|
&format!("FileScope({})", compilation_unit.file_name),
|
||||||
|
ScopeLevel::ModuleOrInterfaceOrClass,
|
||||||
|
);
|
||||||
|
for use_statement in &mut compilation_unit.use_statements {
|
||||||
|
gather_use_statement(use_statement, symbol_table, &mut fqn_context, diagnostics)
|
||||||
|
}
|
||||||
|
for declaration in &mut compilation_unit.declarations {
|
||||||
|
gather_module_level_declaration(declaration, symbol_table, &mut fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
assert_eq!(symbol_table.current_scope_id(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_use_statement(
|
||||||
|
use_statement: &mut UseStatement,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
|
) {
|
||||||
|
if use_statement.is_star() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
for (declared_name, fully_qualified_name) in use_statement.names() {
|
||||||
|
let insert_result = symbol_table.insert(
|
||||||
|
&declared_name,
|
||||||
|
Symbol::UseStatement(UseStatementSymbol::new(
|
||||||
|
&fully_qualified_name,
|
||||||
|
&declared_name,
|
||||||
|
SourceDefinition::from_use_statement(use_statement),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(err) = insert_result {
|
||||||
|
handle_insert_error(
|
||||||
|
err,
|
||||||
|
&declared_name,
|
||||||
|
use_statement.file_id,
|
||||||
|
use_statement.range,
|
||||||
|
"Use statement",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
match &mut use_statement.last {
|
||||||
|
UseStatementLast::Identifier(identifier) => {
|
||||||
|
identifier.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
}
|
||||||
|
UseStatementLast::Identifiers(identifiers) => {
|
||||||
|
for identifier in identifiers {
|
||||||
|
identifier.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use_statement.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_module_level_declaration(
|
||||||
declaration: &mut ModuleLevelDeclaration,
|
declaration: &mut ModuleLevelDeclaration,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
fqn_context: &mut FqnContext,
|
fqn_context: &mut FqnContext,
|
||||||
@ -187,7 +252,10 @@ fn gather_module_declaration(
|
|||||||
|
|
||||||
fqn_context.push(module_name.to_string());
|
fqn_context.push(module_name.to_string());
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("Module '{}' Scope", module_name));
|
symbol_table.push_scope(
|
||||||
|
&format!("Module '{}' Scope", module_name),
|
||||||
|
ScopeLevel::ModuleOrInterfaceOrClass,
|
||||||
|
);
|
||||||
for inner_declaration in &mut declaration.declarations {
|
for inner_declaration in &mut declaration.declarations {
|
||||||
gather_module_level_declaration(inner_declaration, symbol_table, fqn_context, diagnostics);
|
gather_module_level_declaration(inner_declaration, symbol_table, fqn_context, diagnostics);
|
||||||
}
|
}
|
||||||
@ -261,7 +329,10 @@ fn gather_function_definition(
|
|||||||
.identifier
|
.identifier
|
||||||
.set_scope_id(symbol_table.current_scope_id());
|
.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("FunctionScope({})", resolved_name));
|
symbol_table.push_scope(
|
||||||
|
&format!("FunctionScope({})", resolved_name),
|
||||||
|
ScopeLevel::Function,
|
||||||
|
);
|
||||||
gather_parameters(
|
gather_parameters(
|
||||||
&mut function.parameters,
|
&mut function.parameters,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
@ -309,7 +380,10 @@ fn gather_platform_function_definition(
|
|||||||
.identifier
|
.identifier
|
||||||
.set_scope_id(symbol_table.current_scope_id());
|
.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("FunctionScope({})", declared_name_as_string));
|
symbol_table.push_scope(
|
||||||
|
&format!("FunctionScope({})", declared_name_as_string),
|
||||||
|
ScopeLevel::Function,
|
||||||
|
);
|
||||||
gather_parameters(
|
gather_parameters(
|
||||||
&mut platform_function_declaration.parameters,
|
&mut platform_function_declaration.parameters,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
@ -389,7 +463,7 @@ fn gather_block_statement(
|
|||||||
fqn_context: &mut FqnContext,
|
fqn_context: &mut FqnContext,
|
||||||
diagnostics: &mut DiagnosticsContainer,
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
symbol_table.push_scope("BlockStatementScope");
|
symbol_table.push_scope("BlockStatementScope", ScopeLevel::Function);
|
||||||
gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics);
|
gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics);
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use crate::ast::named::Named;
|
use crate::ast::named::Named;
|
||||||
use crate::ast::CompilationUnit;
|
use crate::ast::CompilationUnit;
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::fqn_context::FqnContext;
|
use crate::name_analysis::gather::gather_compilation_unit;
|
||||||
use crate::name_analysis::gather::gather_module_level_declaration;
|
use crate::name_analysis::resolve::resolve_compilation_unit;
|
||||||
use crate::name_analysis::resolve::resolve_module_level_declaration;
|
|
||||||
use crate::name_analysis::symbol_table::SymbolTable;
|
use crate::name_analysis::symbol_table::SymbolTable;
|
||||||
|
|
||||||
mod fqn_context;
|
mod fqn_context;
|
||||||
@ -42,29 +41,12 @@ pub fn analyze_names(
|
|||||||
|
|
||||||
// gather symbols
|
// gather symbols
|
||||||
for compilation_unit in compilation_units.iter_mut() {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
let mut fqn_context = FqnContext::new();
|
gather_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||||
if let Some(namespace) = &compilation_unit.namespace {
|
|
||||||
fqn_context.push(namespace.name().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("FileScope({})", compilation_unit.file_name));
|
|
||||||
for declaration in &mut compilation_unit.declarations {
|
|
||||||
gather_module_level_declaration(
|
|
||||||
declaration,
|
|
||||||
symbol_table,
|
|
||||||
&mut fqn_context,
|
|
||||||
&mut diagnostics,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
symbol_table.pop_scope();
|
|
||||||
assert_eq!(symbol_table.current_scope_id(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
for compilation_unit in compilation_units.iter_mut() {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
for declaration in &mut compilation_unit.declarations {
|
resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||||
resolve_module_level_declaration(declaration, symbol_table, &mut diagnostics);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.into()
|
diagnostics.into()
|
||||||
@ -82,7 +64,7 @@ mod tests {
|
|||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn assert_no_diagnostics(sources: HashMap<&str, &str>) {
|
fn assert_no_diagnostics(sources: HashMap<&str, &str>) -> SymbolTable {
|
||||||
let mut files = SimpleFiles::new();
|
let mut files = SimpleFiles::new();
|
||||||
let mut compilation_units = vec![];
|
let mut compilation_units = vec![];
|
||||||
|
|
||||||
@ -115,6 +97,12 @@ mod tests {
|
|||||||
eprintln!("{}", symbol_table);
|
eprintln!("{}", symbol_table);
|
||||||
panic!("Diagnostics was not empty!");
|
panic!("Diagnostics was not empty!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for compilation_unit in &compilation_units {
|
||||||
|
dbg!(compilation_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -127,7 +115,7 @@ mod tests {
|
|||||||
}"},
|
}"},
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
assert_no_diagnostics(sources)
|
assert_no_diagnostics(sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::ast::named::Named;
|
use crate::ast::named::Named;
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::name_analysis::symbol_table::SymbolTable;
|
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||||
use crate::name_analysis::DiagnosticsContainer;
|
use crate::name_analysis::DiagnosticsContainer;
|
||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
|
|
||||||
@ -37,15 +37,15 @@ fn resolve_fully_qualified_name(
|
|||||||
fn resolve_type_use(
|
fn resolve_type_use(
|
||||||
type_use: &mut TypeUse,
|
type_use: &mut TypeUse,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
match type_use {
|
match type_use {
|
||||||
TypeUse::Void => {},
|
TypeUse::Void => {}
|
||||||
TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
|
TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
|
||||||
resolve_interface_or_class_type_use(
|
resolve_interface_or_class_type_use(
|
||||||
interface_or_class_type_use,
|
interface_or_class_type_use,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
diagnostics
|
diagnostics,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TypeUse::Tuple(tuple_type_use) => {
|
TypeUse::Tuple(tuple_type_use) => {
|
||||||
@ -60,73 +60,65 @@ fn resolve_type_use(
|
|||||||
fn resolve_interface_or_class_type_use(
|
fn resolve_interface_or_class_type_use(
|
||||||
interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
|
interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_fully_qualified_name(
|
resolve_fully_qualified_name(
|
||||||
&mut interface_or_class_type_use.fqn,
|
&mut interface_or_class_type_use.fqn,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
diagnostics
|
diagnostics,
|
||||||
);
|
);
|
||||||
resolve_generic_arguments(
|
resolve_generic_arguments(
|
||||||
&mut interface_or_class_type_use.generics,
|
&mut interface_or_class_type_use.generics,
|
||||||
symbol_table,
|
symbol_table,
|
||||||
diagnostics
|
diagnostics,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_tuple_type_use(
|
fn resolve_tuple_type_use(
|
||||||
tuple_type_use: &mut TupleTypeUse,
|
tuple_type_use: &mut TupleTypeUse,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_tuple_arguments(
|
resolve_tuple_arguments(&mut tuple_type_use.arguments, symbol_table, diagnostics);
|
||||||
&mut tuple_type_use.arguments,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_function_type_use(
|
fn resolve_function_type_use(
|
||||||
function_type_use: &mut FunctionTypeUse,
|
function_type_use: &mut FunctionTypeUse,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_parameters(&mut function_type_use.parameters, symbol_table, diagnostics);
|
resolve_parameters(&mut function_type_use.parameters, symbol_table, diagnostics);
|
||||||
resolve_return_type(&mut function_type_use.return_type, symbol_table, diagnostics);
|
resolve_return_type(
|
||||||
|
&mut function_type_use.return_type,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_generic_arguments(
|
fn resolve_generic_arguments(
|
||||||
generic_arguments: &mut GenericArguments,
|
generic_arguments: &mut GenericArguments,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
for generic_argument in &mut generic_arguments.0 {
|
for generic_argument in &mut generic_arguments.0 {
|
||||||
resolve_type_use(
|
resolve_type_use(generic_argument, symbol_table, diagnostics);
|
||||||
generic_argument,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_tuple_arguments(
|
fn resolve_tuple_arguments(
|
||||||
tuple_type_use: &mut TupleArguments,
|
tuple_type_use: &mut TupleArguments,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
for type_use in &mut tuple_type_use.0 {
|
for type_use in &mut tuple_type_use.0 {
|
||||||
resolve_type_use(
|
resolve_type_use(type_use, symbol_table, diagnostics);
|
||||||
type_use,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_implements_list(
|
fn resolve_implements_list(
|
||||||
implements_list: &mut ImplementsList,
|
implements_list: &mut ImplementsList,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -134,7 +126,7 @@ fn resolve_implements_list(
|
|||||||
fn resolve_parameters(
|
fn resolve_parameters(
|
||||||
parameters: &mut Parameters,
|
parameters: &mut Parameters,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
for parameter in &mut parameters.0 {
|
for parameter in &mut parameters.0 {
|
||||||
resolve_type_use(&mut parameter.type_use, symbol_table, diagnostics);
|
resolve_type_use(&mut parameter.type_use, symbol_table, diagnostics);
|
||||||
@ -144,30 +136,70 @@ fn resolve_parameters(
|
|||||||
fn resolve_return_type(
|
fn resolve_return_type(
|
||||||
return_type: &mut ReturnType,
|
return_type: &mut ReturnType,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_type_use(
|
resolve_type_use(&mut return_type.declared_type, symbol_table, diagnostics);
|
||||||
&mut return_type.declared_type,
|
resolve_references(&mut return_type.references, symbol_table, diagnostics);
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
resolve_references(
|
|
||||||
&mut return_type.references,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_references(
|
fn resolve_references(
|
||||||
references: &mut References,
|
references: &mut References,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
for reference in &mut references.0 {
|
for reference in &mut references.0 {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_use_statement(
|
||||||
|
use_statement: &mut UseStatement,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
|
) {
|
||||||
|
if use_statement.is_star() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
for (_, fully_qualified_name) in use_statement.names() {
|
||||||
|
let lookup_result = symbol_table.lookup_usable(
|
||||||
|
&fully_qualified_name,
|
||||||
|
use_statement
|
||||||
|
.scope_id()
|
||||||
|
.expect("UseStatement.scope_id was not set."),
|
||||||
|
);
|
||||||
|
match lookup_result {
|
||||||
|
Ok(referenced_symbol) => {
|
||||||
|
use_statement.set_symbol(referenced_symbol.clone());
|
||||||
|
}
|
||||||
|
Err(err) => match err {
|
||||||
|
SymbolLookupError::NoDefinition => {
|
||||||
|
diagnostics.add(
|
||||||
|
Diagnostic::error()
|
||||||
|
.with_message(&format!(
|
||||||
|
"No definition found for symbol '{}'",
|
||||||
|
fully_qualified_name
|
||||||
|
))
|
||||||
|
.with_label(Label::primary(use_statement.file_id, use_statement.range)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn resolve_compilation_unit(
|
||||||
|
compilation_unit: &mut CompilationUnit,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
|
) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn resolve_module_level_declaration(
|
pub(super) fn resolve_module_level_declaration(
|
||||||
declaration: &mut ModuleLevelDeclaration,
|
declaration: &mut ModuleLevelDeclaration,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
@ -178,13 +210,11 @@ pub(super) fn resolve_module_level_declaration(
|
|||||||
Function(function_definition) => {
|
Function(function_definition) => {
|
||||||
resolve_function_definition(function_definition, symbol_table, diagnostics)
|
resolve_function_definition(function_definition, symbol_table, diagnostics)
|
||||||
}
|
}
|
||||||
PlatformFunction(platform_function_declaration) => {
|
PlatformFunction(platform_function_declaration) => resolve_platform_function_declaration(
|
||||||
resolve_platform_function_declaration(
|
platform_function_declaration,
|
||||||
platform_function_declaration,
|
symbol_table,
|
||||||
symbol_table,
|
diagnostics,
|
||||||
diagnostics,
|
),
|
||||||
)
|
|
||||||
}
|
|
||||||
Class(class_declaration) => {
|
Class(class_declaration) => {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
@ -197,18 +227,34 @@ fn resolve_function_definition(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer,
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_parameters(&mut function_definition.parameters, symbol_table, diagnostics);
|
resolve_parameters(
|
||||||
resolve_return_type(&mut function_definition.return_type, symbol_table, diagnostics);
|
&mut function_definition.parameters,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
resolve_return_type(
|
||||||
|
&mut function_definition.return_type,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
resolve_function_body(&mut function_definition.body, symbol_table, diagnostics);
|
resolve_function_body(&mut function_definition.body, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_platform_function_declaration(
|
fn resolve_platform_function_declaration(
|
||||||
platform_function_declaration: &mut PlatformFunctionDeclaration,
|
platform_function_declaration: &mut PlatformFunctionDeclaration,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_parameters(&mut platform_function_declaration.parameters, symbol_table, diagnostics);
|
resolve_parameters(
|
||||||
resolve_return_type(&mut platform_function_declaration.return_type, symbol_table, diagnostics);
|
&mut platform_function_declaration.parameters,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
resolve_return_type(
|
||||||
|
&mut platform_function_declaration.return_type,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_function_body(
|
fn resolve_function_body(
|
||||||
@ -298,32 +344,16 @@ fn resolve_expression(
|
|||||||
resolve_binary_expression(binary_expression, symbol_table, diagnostics);
|
resolve_binary_expression(binary_expression, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
UnaryPrefix(prefix_expression) => {
|
UnaryPrefix(prefix_expression) => {
|
||||||
resolve_prefix_expression(
|
resolve_prefix_expression(prefix_expression, symbol_table, diagnostics);
|
||||||
prefix_expression,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
UnarySuffix(suffix_expression) => {
|
UnarySuffix(suffix_expression) => {
|
||||||
resolve_suffix_expression(
|
resolve_suffix_expression(suffix_expression, symbol_table, diagnostics);
|
||||||
suffix_expression,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Call(call_expression) => {
|
Call(call_expression) => {
|
||||||
resolve_call_expression(
|
resolve_call_expression(call_expression, symbol_table, diagnostics)
|
||||||
call_expression,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ObjectAccess(object_access) => {
|
ObjectAccess(object_access) => {
|
||||||
resolve_object_access(
|
resolve_object_access(object_access, symbol_table, diagnostics);
|
||||||
object_access,
|
|
||||||
symbol_table,
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics),
|
FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics),
|
||||||
Literal(literal) => {
|
Literal(literal) => {
|
||||||
@ -338,17 +368,25 @@ fn resolve_expression(
|
|||||||
fn resolve_ternary_expression(
|
fn resolve_ternary_expression(
|
||||||
ternary_expression: &mut TernaryExpression,
|
ternary_expression: &mut TernaryExpression,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut ternary_expression.condition, symbol_table, diagnostics);
|
resolve_expression(&mut ternary_expression.condition, symbol_table, diagnostics);
|
||||||
resolve_expression(&mut ternary_expression.true_expression, symbol_table, diagnostics);
|
resolve_expression(
|
||||||
resolve_expression(&mut ternary_expression.false_expression, symbol_table, diagnostics);
|
&mut ternary_expression.true_expression,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
resolve_expression(
|
||||||
|
&mut ternary_expression.false_expression,
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_binary_expression(
|
fn resolve_binary_expression(
|
||||||
binary_expression: &mut BinaryExpression,
|
binary_expression: &mut BinaryExpression,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut binary_expression.left, symbol_table, diagnostics);
|
resolve_expression(&mut binary_expression.left, symbol_table, diagnostics);
|
||||||
resolve_expression(&mut binary_expression.right, symbol_table, diagnostics);
|
resolve_expression(&mut binary_expression.right, symbol_table, diagnostics);
|
||||||
@ -357,7 +395,7 @@ fn resolve_binary_expression(
|
|||||||
fn resolve_prefix_expression(
|
fn resolve_prefix_expression(
|
||||||
prefix_expression: &mut PrefixExpression,
|
prefix_expression: &mut PrefixExpression,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut prefix_expression.expression, symbol_table, diagnostics);
|
resolve_expression(&mut prefix_expression.expression, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
@ -365,7 +403,7 @@ fn resolve_prefix_expression(
|
|||||||
fn resolve_suffix_expression(
|
fn resolve_suffix_expression(
|
||||||
suffix_expression: &mut SuffixExpression,
|
suffix_expression: &mut SuffixExpression,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut suffix_expression.expression, symbol_table, diagnostics);
|
resolve_expression(&mut suffix_expression.expression, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
@ -373,7 +411,7 @@ fn resolve_suffix_expression(
|
|||||||
fn resolve_call_expression(
|
fn resolve_call_expression(
|
||||||
call_expression: &mut CallExpression,
|
call_expression: &mut CallExpression,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut call_expression.callee, symbol_table, diagnostics);
|
resolve_expression(&mut call_expression.callee, symbol_table, diagnostics);
|
||||||
if let Some(turbo_fish) = &mut call_expression.turbo_fish {
|
if let Some(turbo_fish) = &mut call_expression.turbo_fish {
|
||||||
@ -385,7 +423,7 @@ fn resolve_call_expression(
|
|||||||
fn resolve_turbo_fish(
|
fn resolve_turbo_fish(
|
||||||
turbo_fish: &mut TurboFish,
|
turbo_fish: &mut TurboFish,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -393,7 +431,7 @@ fn resolve_turbo_fish(
|
|||||||
fn resolve_call_arguments(
|
fn resolve_call_arguments(
|
||||||
call_arguments: &mut CallArguments,
|
call_arguments: &mut CallArguments,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
for argument in &mut call_arguments.0 {
|
for argument in &mut call_arguments.0 {
|
||||||
resolve_call_argument(argument, symbol_table, diagnostics);
|
resolve_call_argument(argument, symbol_table, diagnostics);
|
||||||
@ -403,7 +441,7 @@ fn resolve_call_arguments(
|
|||||||
fn resolve_call_argument(
|
fn resolve_call_argument(
|
||||||
call_argument: &mut CallArgument,
|
call_argument: &mut CallArgument,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
resolve_expression(&mut call_argument.0, symbol_table, diagnostics);
|
resolve_expression(&mut call_argument.0, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
@ -411,7 +449,7 @@ fn resolve_call_argument(
|
|||||||
fn resolve_closure(
|
fn resolve_closure(
|
||||||
closure: &mut Closure,
|
closure: &mut Closure,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -419,7 +457,7 @@ fn resolve_closure(
|
|||||||
fn resolve_object_access(
|
fn resolve_object_access(
|
||||||
object_access: &mut ObjectAccess,
|
object_access: &mut ObjectAccess,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -427,7 +465,7 @@ fn resolve_object_access(
|
|||||||
fn resolve_literal(
|
fn resolve_literal(
|
||||||
literal: &mut Literal,
|
literal: &mut Literal,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
match literal {
|
match literal {
|
||||||
Literal::DString(d_string) => resolve_d_string(d_string, symbol_table, diagnostics),
|
Literal::DString(d_string) => resolve_d_string(d_string, symbol_table, diagnostics),
|
||||||
@ -439,7 +477,7 @@ fn resolve_literal(
|
|||||||
fn resolve_d_string(
|
fn resolve_d_string(
|
||||||
d_string: &mut DString,
|
d_string: &mut DString,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut DiagnosticsContainer
|
diagnostics: &mut DiagnosticsContainer,
|
||||||
) {
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::ast::Identifier;
|
use crate::ast::{Identifier, UseStatement};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::range::Range;
|
use std::range::Range;
|
||||||
|
|
||||||
@ -16,6 +16,13 @@ impl SourceDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
|
||||||
|
SourceDefinition {
|
||||||
|
file_id: use_statement.file_id,
|
||||||
|
range: use_statement.range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn file_id(&self) -> usize {
|
pub fn file_id(&self) -> usize {
|
||||||
self.file_id
|
self.file_id
|
||||||
}
|
}
|
||||||
@ -31,6 +38,7 @@ pub enum Symbol {
|
|||||||
Variable(VariableSymbol),
|
Variable(VariableSymbol),
|
||||||
Module(ModuleSymbol),
|
Module(ModuleSymbol),
|
||||||
Class(ClassSymbol),
|
Class(ClassSymbol),
|
||||||
|
UseStatement(UseStatementSymbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol {
|
impl Symbol {
|
||||||
@ -40,6 +48,7 @@ impl Symbol {
|
|||||||
Symbol::Variable(s) => s.name.as_str(),
|
Symbol::Variable(s) => s.name.as_str(),
|
||||||
Symbol::Module(s) => s.declared_name.as_str(),
|
Symbol::Module(s) => s.declared_name.as_str(),
|
||||||
Symbol::Class(s) => s.declared_name.as_str(),
|
Symbol::Class(s) => s.declared_name.as_str(),
|
||||||
|
Symbol::UseStatement(s) => s.declared_name.as_str(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +58,7 @@ impl Symbol {
|
|||||||
Symbol::Module(s) => s.definition(),
|
Symbol::Module(s) => s.definition(),
|
||||||
Symbol::Variable(s) => s.definition(),
|
Symbol::Variable(s) => s.definition(),
|
||||||
Symbol::Class(s) => s.definition(),
|
Symbol::Class(s) => s.definition(),
|
||||||
|
Symbol::UseStatement(s) => s.definition(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,6 +71,7 @@ impl Display for Symbol {
|
|||||||
Variable(variable_symbol) => write!(f, "{}", variable_symbol),
|
Variable(variable_symbol) => write!(f, "{}", variable_symbol),
|
||||||
Module(module_symbol) => write!(f, "{}", module_symbol),
|
Module(module_symbol) => write!(f, "{}", module_symbol),
|
||||||
Class(class_symbol) => write!(f, "{}", class_symbol),
|
Class(class_symbol) => write!(f, "{}", class_symbol),
|
||||||
|
UseStatement(use_statement_symbol) => write!(f, "{}", use_statement_symbol),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +203,7 @@ impl ClassSymbol {
|
|||||||
definition: SourceDefinition::from_identifier(identifier),
|
definition: SourceDefinition::from_identifier(identifier),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn definition(&self) -> &SourceDefinition {
|
pub fn definition(&self) -> &SourceDefinition {
|
||||||
&self.definition
|
&self.definition
|
||||||
}
|
}
|
||||||
@ -207,3 +218,44 @@ impl Display for ClassSymbol {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct UseStatementSymbol {
|
||||||
|
pub fqn: String,
|
||||||
|
pub declared_name: String,
|
||||||
|
definition: SourceDefinition,
|
||||||
|
referenced_symbol: Option<Box<Symbol>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UseStatementSymbol {
|
||||||
|
pub fn new(fqn: &str, declared_name: &str, definition: SourceDefinition) -> Self {
|
||||||
|
UseStatementSymbol {
|
||||||
|
fqn: fqn.to_string(),
|
||||||
|
declared_name: declared_name.to_string(),
|
||||||
|
definition,
|
||||||
|
referenced_symbol: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn definition(&self) -> &SourceDefinition {
|
||||||
|
&self.definition
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_referenced_symbol(&mut self, referenced_symbol: Symbol) {
|
||||||
|
self.referenced_symbol = Some(Box::new(referenced_symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn referenced_symbol(&self) -> Option<Box<Symbol>> {
|
||||||
|
self.referenced_symbol.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for UseStatementSymbol {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"UseStatementSymbol(fqn = {}, declared_name = {})",
|
||||||
|
self.fqn, self.declared_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,25 +1,88 @@
|
|||||||
use crate::name_analysis::symbol::Symbol;
|
use crate::name_analysis::symbol::Symbol;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
||||||
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum ScopeLevel {
|
||||||
|
Global,
|
||||||
|
ModuleOrInterfaceOrClass,
|
||||||
|
Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
|
level: ScopeLevel,
|
||||||
parent: Option<usize>,
|
parent: Option<usize>,
|
||||||
function_and_variable_symbols: HashMap<String, Symbol>,
|
use_statement_symbols: HashMap<String, Symbol>,
|
||||||
type_and_module_symbols: HashMap<String, Symbol>,
|
module_symbols: HashMap<String, Symbol>,
|
||||||
|
type_symbols: HashMap<String, Symbol>,
|
||||||
|
function_symbols: HashMap<String, Symbol>,
|
||||||
|
variable_symbols: HashMap<String, Symbol>,
|
||||||
debug_name: String,
|
debug_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
pub fn new(parent: Option<usize>, debug_name: String) -> Scope {
|
pub fn new(parent: Option<usize>, debug_name: String, level: ScopeLevel) -> Scope {
|
||||||
Scope {
|
Scope {
|
||||||
|
level,
|
||||||
parent,
|
parent,
|
||||||
function_and_variable_symbols: HashMap::new(),
|
use_statement_symbols: HashMap::new(),
|
||||||
type_and_module_symbols: HashMap::new(),
|
module_symbols: HashMap::new(),
|
||||||
|
type_symbols: HashMap::new(),
|
||||||
|
function_symbols: HashMap::new(),
|
||||||
|
variable_symbols: HashMap::new(),
|
||||||
debug_name,
|
debug_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn level(&self) -> ScopeLevel {
|
||||||
|
self.level.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_any_symbol(&self, name: &str) -> Option<&Symbol> {
|
||||||
|
self.variable_symbols
|
||||||
|
.get(name)
|
||||||
|
.or_else(|| self.function_symbols.get(name))
|
||||||
|
.or_else(|| self.type_symbols.get(name))
|
||||||
|
.or_else(|| self.module_symbols.get(name))
|
||||||
|
.or_else(|| self.use_statement_symbols.get(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_usable_symbol(&self, fqn: &str) -> Option<&Symbol> {
|
||||||
|
for function_symbol in self.function_symbols.values() {
|
||||||
|
match function_symbol {
|
||||||
|
Symbol::Function(s) => {
|
||||||
|
if s.fqn == fqn {
|
||||||
|
return Some(function_symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Cannot have non-function in function_symbols."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for type_symbol in self.type_symbols.values() {
|
||||||
|
match type_symbol {
|
||||||
|
Symbol::Class(s) => {
|
||||||
|
if s.fqn == fqn {
|
||||||
|
return Some(type_symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Cannot have non-class in type_symbols."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbols(&self) -> Vec<&Symbol> {
|
||||||
|
let mut symbols: Vec<&Symbol> = Vec::new();
|
||||||
|
symbols.extend(self.use_statement_symbols.values());
|
||||||
|
symbols.extend(self.module_symbols.values());
|
||||||
|
symbols.extend(self.type_symbols.values());
|
||||||
|
symbols.extend(self.function_symbols.values());
|
||||||
|
symbols.extend(self.variable_symbols.values());
|
||||||
|
symbols
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SymbolInsertError {
|
pub enum SymbolInsertError {
|
||||||
@ -27,9 +90,10 @@ pub enum SymbolInsertError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum SymbolLookupError {
|
pub enum SymbolLookupError {
|
||||||
NoDefinition
|
NoDefinition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SymbolTable {
|
pub struct SymbolTable {
|
||||||
scopes: Vec<Scope>,
|
scopes: Vec<Scope>,
|
||||||
current_scope_id: usize,
|
current_scope_id: usize,
|
||||||
@ -39,7 +103,11 @@ pub struct SymbolTable {
|
|||||||
impl SymbolTable {
|
impl SymbolTable {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut t = SymbolTable {
|
let mut t = SymbolTable {
|
||||||
scopes: vec![Scope::new(None, String::from("GlobalScope"))],
|
scopes: vec![Scope::new(
|
||||||
|
None,
|
||||||
|
String::from("GlobalScope"),
|
||||||
|
ScopeLevel::Global,
|
||||||
|
)],
|
||||||
current_scope_id: 0,
|
current_scope_id: 0,
|
||||||
};
|
};
|
||||||
t
|
t
|
||||||
@ -49,10 +117,17 @@ impl SymbolTable {
|
|||||||
self.current_scope_id
|
self.current_scope_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_scope(&mut self, debug_name: &str) {
|
pub fn scopes(&self) -> &Vec<Scope> {
|
||||||
|
&self.scopes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_scope(&mut self, debug_name: &str, level: ScopeLevel) {
|
||||||
let id = self.scopes.len();
|
let id = self.scopes.len();
|
||||||
self.scopes
|
self.scopes.push(Scope::new(
|
||||||
.push(Scope::new(Some(self.current_scope_id), debug_name.to_string()));
|
Some(self.current_scope_id),
|
||||||
|
debug_name.to_string(),
|
||||||
|
level,
|
||||||
|
));
|
||||||
self.current_scope_id = id;
|
self.current_scope_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,32 +143,53 @@ impl SymbolTable {
|
|||||||
self.insert_function_or_variable(name, symbol)
|
self.insert_function_or_variable(name, symbol)
|
||||||
}
|
}
|
||||||
Symbol::Module(_) | Symbol::Class(_) => self.insert_module_or_type(name, symbol),
|
Symbol::Module(_) | Symbol::Class(_) => self.insert_module_or_type(name, symbol),
|
||||||
|
Symbol::UseStatement(_) => self.insert_use_statement_symbol(name, symbol),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_function_or_variable(&mut self, name: &str, symbol: Symbol) -> Result<(), SymbolInsertError> {
|
fn insert_function_or_variable(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
symbol: Symbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
if let Some(defined_symbol) = self.scopes[self.current_scope_id]
|
if let Some(defined_symbol) = self.scopes[self.current_scope_id]
|
||||||
.function_and_variable_symbols
|
.function_symbols
|
||||||
.get(name)
|
.get(name)
|
||||||
{
|
{
|
||||||
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||||
} else {
|
} else {
|
||||||
self.scopes[self.current_scope_id]
|
self.scopes[self.current_scope_id]
|
||||||
.function_and_variable_symbols
|
.function_symbols
|
||||||
.insert(name.to_string(), symbol);
|
.insert(name.to_string(), symbol);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_module_or_type(&mut self, name: &str, symbol: Symbol) -> Result<(), SymbolInsertError> {
|
fn insert_module_or_type(
|
||||||
if let Some(defined_symbol) = self.scopes[self.current_scope_id]
|
&mut self,
|
||||||
.type_and_module_symbols
|
name: &str,
|
||||||
.get(name)
|
symbol: Symbol,
|
||||||
{
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) = self.scopes[self.current_scope_id].type_symbols.get(name) {
|
||||||
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||||
} else {
|
} else {
|
||||||
self.scopes[self.current_scope_id]
|
self.scopes[self.current_scope_id]
|
||||||
.type_and_module_symbols
|
.type_symbols
|
||||||
|
.insert(name.to_string(), symbol);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_use_statement_symbol(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
symbol: Symbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
if let Some(defined_symbol) = self.scopes[self.current_scope_id].get_any_symbol(name) {
|
||||||
|
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||||
|
} else {
|
||||||
|
self.scopes[self.current_scope_id]
|
||||||
|
.use_statement_symbols
|
||||||
.insert(name.to_string(), symbol);
|
.insert(name.to_string(), symbol);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -102,7 +198,7 @@ impl SymbolTable {
|
|||||||
pub fn lookup(&self, name: &str, scope_id: usize) -> Result<&Symbol, SymbolLookupError> {
|
pub fn lookup(&self, name: &str, scope_id: usize) -> Result<&Symbol, SymbolLookupError> {
|
||||||
let mut scope_opt = Some(&self.scopes[scope_id]);
|
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||||
while let Some(scope) = scope_opt {
|
while let Some(scope) = scope_opt {
|
||||||
if let Some(symbol) = scope.function_and_variable_symbols.get(name) {
|
if let Some(symbol) = scope.get_any_symbol(name) {
|
||||||
return Ok(symbol);
|
return Ok(symbol);
|
||||||
}
|
}
|
||||||
scope_opt = if let Some(parent_id) = scope.parent {
|
scope_opt = if let Some(parent_id) = scope.parent {
|
||||||
@ -113,6 +209,22 @@ impl SymbolTable {
|
|||||||
}
|
}
|
||||||
Err(NoDefinition)
|
Err(NoDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lookup_usable(
|
||||||
|
&self,
|
||||||
|
fully_qualified_name: &str,
|
||||||
|
scope_id: usize,
|
||||||
|
) -> Result<&Symbol, SymbolLookupError> {
|
||||||
|
for scope in &self.scopes {
|
||||||
|
if scope.level == ScopeLevel::Function {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(symbol) = scope.get_usable_symbol(fully_qualified_name) {
|
||||||
|
return Ok(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(NoDefinition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for SymbolTable {
|
impl Display for SymbolTable {
|
||||||
@ -120,10 +232,19 @@ impl Display for SymbolTable {
|
|||||||
writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?;
|
writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?;
|
||||||
for (i, scope) in self.scopes.iter().enumerate() {
|
for (i, scope) in self.scopes.iter().enumerate() {
|
||||||
writeln!(f, "Scope {} {}", i, scope.debug_name)?;
|
writeln!(f, "Scope {} {}", i, scope.debug_name)?;
|
||||||
for (name, symbol) in &scope.type_and_module_symbols {
|
for (name, symbol) in &scope.use_statement_symbols {
|
||||||
writeln!(f, " {}({})", name, symbol)?;
|
writeln!(f, " {}({})", name, symbol)?;
|
||||||
}
|
}
|
||||||
for (name, symbol) in &scope.function_and_variable_symbols {
|
for (name, symbol) in &scope.module_symbols {
|
||||||
|
writeln!(f, " {}({})", name, symbol)?;
|
||||||
|
}
|
||||||
|
for (name, symbol) in &scope.type_symbols {
|
||||||
|
writeln!(f, " {}({})", name, symbol)?;
|
||||||
|
}
|
||||||
|
for (name, symbol) in &scope.function_symbols {
|
||||||
|
writeln!(f, " {}({})", name, symbol)?;
|
||||||
|
}
|
||||||
|
for (name, symbol) in &scope.variable_symbols {
|
||||||
writeln!(f, " {}({})", name, symbol)?;
|
writeln!(f, " {}({})", name, symbol)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user