deimos-lang/src/name_analysis/gather_2.rs.bak

1114 lines
35 KiB
Rust

/// The gather phase must exclusively gather all named items that can be used elsewhere.
use crate::ast::ast_node::{AstNode, AstNodeRefMut};
use crate::ast::node::{
Class, Closure, ClosureParameter, CompilationUnit, ForStatement, Function, FunctionBody,
GenericParameters, Identifier, IfClause, Interface, InterfaceDefaultFunction,
InterfaceDefaultOperatorFunction, InterfaceFunction, InterfaceOperatorFunction, Member, Module,
Namespace, OperatorFunction, Parameter, PlatformFunction, PlatformOperatorFunction,
TernaryExpression, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse,
WhileStatement,
};
use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::fqn_context::FqnContext;
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::type_symbol::{
ConcreteTypeSymbol, ConcreteTypeSymbolKind, GenericTypeSymbol, TypeSymbol,
};
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolLookupError, SymbolTable};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::range::Range;
fn handle_insert_error(
err: SymbolInsertError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolInsertError::SymbolAlreadyDefined(s) => {
let mut diagnostic = Diagnostic::error()
.with_message(format!(
"{} symbol '{}' already defined in the current scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range)
.with_message("Symbol duplicated here."),
);
if let Some(source_definition) = s.definition() {
diagnostic = diagnostic.with_label(
Label::secondary(source_definition.file_id(), source_definition.range())
.with_message("Symbol defined here."),
);
}
diagnostics.push(diagnostic);
}
}
}
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);
}
}
}
fn gather_node_children<'a>(
node: &'a mut dyn AstNode<'a>,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
node.for_each_child_mut(&mut |child| {
gather_node(child, symbol_table, fqn_context, diagnostics);
});
}
fn gather_node<'a>(
node: &'a mut dyn AstNode<'a>,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let node_ref = node.as_node_ref_mut();
match node_ref {
AstNodeRefMut::GenericParameters(generic_parameters) => {
gather_generic_parameters(generic_parameters, symbol_table, diagnostics);
}
AstNodeRefMut::Parameter(parameter) => {
gather_parameter(parameter, symbol_table, diagnostics);
}
AstNodeRefMut::Namespace(namespace) => {
gather_namespace(namespace, fqn_context);
}
AstNodeRefMut::UseStatement(use_statement) => {
gather_use_statement(use_statement, symbol_table, diagnostics);
}
AstNodeRefMut::Module(module) => {
gather_module(module, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::Interface(interface) => {
gather_interface(interface, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::Class(class) => {
gather_class(class, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::Function(function) => {
gather_function(function, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::OperatorFunction(operator_function) => {
gather_operator_function(operator_function, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::PlatformFunction(platform_function) => {
gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::PlatformOperatorFunction(platform_operator_function) => {
gather_platform_operator_function(
platform_operator_function,
symbol_table,
fqn_context,
diagnostics,
);
}
AstNodeRefMut::InterfaceFunction(interface_function) => {
gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::InterfaceDefaultFunction(interface_default_function) => {
gather_interface_default_function(
interface_default_function,
symbol_table,
fqn_context,
diagnostics,
);
}
AstNodeRefMut::InterfaceOperatorFunction(interface_operator_function) => {
gather_interface_operator_function(
interface_operator_function,
symbol_table,
fqn_context,
diagnostics,
);
}
AstNodeRefMut::InterfaceDefaultOperatorFunction(interface_default_operator_function) => {
gather_interface_default_operator_function(
interface_default_operator_function,
symbol_table,
fqn_context,
diagnostics,
);
}
AstNodeRefMut::FunctionBody(function_body) => {
gather_function_body(function_body, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::Member(member) => {
gather_member(member, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::VariableDeclaration(variable_declaration) => {
gather_variable_declaration(
variable_declaration,
symbol_table,
fqn_context,
diagnostics,
);
}
AstNodeRefMut::IfClause(if_clause) => {
gather_if_clause(if_clause, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::IfElseIf(if_else_if) => {
gather_node_children(if_else_if, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::WhileStatement(while_statement) => {
gather_while_statement(while_statement, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::ForStatement(for_statement) => {
gather_for_statement(for_statement, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::VariableUse(variable_use) => {
gather_variable_use(variable_use, symbol_table, diagnostics);
}
AstNodeRefMut::TernaryExpression(ternary_expression) => {
gather_ternary_expression(ternary_expression, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::Closure(closure) => {
gather_closure(closure, symbol_table, fqn_context, diagnostics);
}
AstNodeRefMut::ClosureParameter(closure_parameter) => {
gather_closure_parameter(closure_parameter, symbol_table, fqn_context, diagnostics);
}
_ => todo!(),
}
}
fn gather_generic_parameters<'a>(
generic_parameters: &'a GenericParameters,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for identifier in generic_parameters.identifier_list().identifiers() {
let type_symbol = TypeSymbol::Generic(GenericTypeSymbol::new(
identifier.name(),
Some(SourceDefinition::from_identifier(identifier)),
));
if let Err(insert_error) = symbol_table.insert_type_symbol(type_symbol) {
handle_insert_error(
insert_error,
identifier.name(),
identifier.file_id(),
identifier.range(),
"Type",
diagnostics,
);
}
}
}
fn gather_parameter<'a>(
parameter: &'a mut Parameter,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let parameter_symbol = ParameterSymbol::new(
parameter.identifier().name(),
Some(SourceDefinition::from_identifier(parameter.identifier())),
);
if let Err(insert_error) = symbol_table.insert_parameter_symbol(parameter_symbol) {
handle_insert_error(
insert_error,
parameter.identifier().name(),
parameter.identifier().file_id(),
parameter.identifier().range(),
"Parameter",
diagnostics,
);
}
}
pub fn gather_compilation_unit<'a>(
compilation_unit: &'a mut CompilationUnit,
file_name: &str,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let mut fqn_context = FqnContext::new();
symbol_table.push_scope(&format!("FileScope {}", file_name));
gather_node(
compilation_unit,
symbol_table,
&mut fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_namespace(namespace: &Namespace, fqn_context: &mut FqnContext) {
for identifier in namespace.fqn().identifiers() {
fqn_context.push(identifier.name());
}
}
fn gather_use_statement(
use_statement: &UseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let base_fqn = use_statement
.prefixes()
.map(|prefix| prefix.identifier().name())
.collect::<Vec<_>>()
.join("::");
match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => {
gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics);
}
UseStatementSuffix::Star => {
let symbol = StarUseSymbol::new(
&base_fqn,
Some(SourceDefinition::from_use_statement(use_statement)),
);
let insert_result = symbol_table.insert_star_use_symbol(symbol);
if let Err(error) = insert_result {
handle_insert_error(
error,
&base_fqn,
use_statement.file_id(),
use_statement.range(),
"Use Statement",
diagnostics,
);
}
}
UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() {
gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics);
}
}
}
}
fn gather_concrete_use_symbol(
base_fqn: &str,
identifier: &Identifier,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let symbol = ConcreteUseSymbol::new(
base_fqn,
identifier.name(),
Some(SourceDefinition::from_identifier(identifier)),
);
if let Err(insert_error) = symbol_table.insert_concrete_use_symbol(symbol) {
handle_insert_error(
insert_error,
&base_fqn,
identifier.file_id(),
identifier.range(),
"Use Statement",
diagnostics,
);
}
}
fn gather_module<'a>(
module: &'a mut Module,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let module_symbol = ModuleSymbol::new(
&fqn_context.resolve(module.identifier().name()),
module.identifier().name(),
module.is_public(),
Some(SourceDefinition::from_identifier(module.identifier())),
);
if let Err(symbol_insert_error) = symbol_table.insert_module_symbol(module_symbol) {
handle_insert_error(
symbol_insert_error,
module.identifier().name(),
module.identifier().file_id(),
module.identifier().range(),
"Module",
diagnostics,
);
}
fqn_context.push(module.identifier().name());
symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name()));
for declaration in module.declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
fqn_context.pop();
}
fn gather_interface<'a>(
interface: &'a mut Interface,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let type_symbol = ConcreteTypeSymbol::new(
&fqn_context.resolve(interface.identifier().name()),
interface.identifier().name(),
interface.is_public(),
ConcreteTypeSymbolKind::Interface,
Some(SourceDefinition::from_identifier(interface.identifier())),
);
if let Err(symbol_insert_error) =
symbol_table.insert_type_symbol(TypeSymbol::Concrete(type_symbol))
{
handle_insert_error(
symbol_insert_error,
interface.identifier().name(),
interface.identifier().file_id(),
interface.identifier().range(),
"Interface",
diagnostics,
);
}
fqn_context.push(interface.identifier().name());
symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name()));
for declaration in interface.declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
fqn_context.pop();
}
fn gather_class<'a>(
class: &'a mut Class,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let class_symbol = ConcreteTypeSymbol::new(
&fqn_context.resolve(class.identifier().name()),
class.identifier().name(),
class.is_public(),
ConcreteTypeSymbolKind::Class,
Some(SourceDefinition::from_identifier(class.identifier())),
);
if let Err(symbol_insert_error) =
symbol_table.insert_type_symbol(TypeSymbol::Concrete(class_symbol))
{
handle_insert_error(
symbol_insert_error,
class.identifier().name(),
class.identifier().file_id(),
class.identifier().range(),
"Class",
diagnostics,
);
}
fqn_context.push(class.identifier().name());
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
gather_node(
class.class_constructor_mut(),
symbol_table,
fqn_context,
diagnostics,
);
for declaration in class.class_level_declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
fqn_context.pop();
}
fn gather_function<'a>(
function: &'a mut Function,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(function.identifier().name()),
function.identifier().name(),
function.is_public(),
false,
Some(SourceDefinition::from_identifier(function.identifier())),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
function.identifier().name(),
function.identifier().file_id(),
function.identifier().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
gather_node(
function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
function.function_body_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_operator_function<'a>(
operator_function: &'a mut OperatorFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(&operator_function.operator().inner().name()),
operator_function.operator().inner().name(),
operator_function.is_public(),
false,
Some(SourceDefinition::from_operator(
operator_function.operator(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
operator_function.operator().inner().name(),
operator_function.operator().file_id(),
operator_function.operator().range(),
"Operator",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"FunctionScope {}",
operator_function.operator().inner().name()
));
gather_node(
operator_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
operator_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
operator_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
operator_function.function_body_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_platform_function<'a>(
platform_function: &'a mut PlatformFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(platform_function.identifier().name()),
platform_function.identifier().name(),
platform_function.is_public(),
true,
Some(SourceDefinition::from_identifier(
platform_function.identifier(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
platform_function.identifier().name(),
platform_function.identifier().file_id(),
platform_function.identifier().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"PlatformFunctionScope {}",
platform_function.identifier().name()
));
gather_node(
platform_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
platform_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
platform_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_platform_operator_function<'a>(
platform_operator_function: &'a mut PlatformOperatorFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(platform_operator_function.operator().inner().name()),
platform_operator_function.operator().inner().name(),
platform_operator_function.is_public(),
true,
Some(SourceDefinition::from_operator(
platform_operator_function.operator(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
platform_operator_function.operator().inner().name(),
platform_operator_function.operator().file_id(),
platform_operator_function.operator().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"PlatformOperatorFunctionScope {}",
platform_operator_function.operator().inner().name()
));
gather_node(
platform_operator_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
platform_operator_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
platform_operator_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_interface_function<'a>(
interface_function: &'a mut InterfaceFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(interface_function.identifier().name()),
interface_function.identifier().name(),
true,
false,
Some(SourceDefinition::from_identifier(
interface_function.identifier(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
interface_function.identifier().name(),
interface_function.identifier().file_id(),
interface_function.identifier().range(),
"Type",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"InterfaceFunctionScope {}",
interface_function.identifier().name()
));
gather_node(
interface_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_interface_default_function<'a>(
interface_default_function: &'a mut InterfaceDefaultFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(interface_default_function.identifier().name()),
interface_default_function.identifier().name(),
true,
false,
Some(SourceDefinition::from_identifier(
interface_default_function.identifier(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
interface_default_function.identifier().name(),
interface_default_function.identifier().file_id(),
interface_default_function.identifier().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"InterfaceDefaultFunctionScope {}",
interface_default_function.identifier().name()
));
gather_node(
interface_default_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_function.function_body_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_interface_operator_function<'a>(
interface_operator_function: &'a mut InterfaceOperatorFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(interface_operator_function.operator().inner().name()),
interface_operator_function.operator().inner().name(),
true,
false,
Some(SourceDefinition::from_operator(
interface_operator_function.operator(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
interface_operator_function.operator().inner().name(),
interface_operator_function.operator().file_id(),
interface_operator_function.operator().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"InterfaceOperatorFunctionScope {}",
interface_operator_function.operator().inner().name()
));
gather_node(
interface_operator_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_operator_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_operator_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_interface_default_operator_function<'a>(
interface_default_operator_function: &'a mut InterfaceDefaultOperatorFunction,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
&fqn_context.resolve(
interface_default_operator_function
.operator()
.inner()
.name(),
),
interface_default_operator_function
.operator()
.inner()
.name(),
true,
false,
Some(SourceDefinition::from_operator(
interface_default_operator_function.operator(),
)),
);
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
handle_insert_error(
insert_error,
interface_default_operator_function
.operator()
.inner()
.name(),
interface_default_operator_function.operator().file_id(),
interface_default_operator_function.operator().range(),
"Function",
diagnostics,
);
}
symbol_table.push_scope(&format!(
"InterfaceDefaultOperatorFunctionScope {}",
interface_default_operator_function
.operator()
.inner()
.name()
));
gather_node(
interface_default_operator_function.generics_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_operator_function.parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_operator_function.return_type_mut(),
symbol_table,
fqn_context,
diagnostics,
);
gather_node(
interface_default_operator_function.function_body_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.pop_scope();
}
fn gather_function_body<'a>(
function_body: &'a mut FunctionBody,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.push_scope("FunctionBodyScope");
gather_node_children(function_body, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope();
}
fn gather_member<'a>(
member: &'a mut Member,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let member_symbol = ClassMemberSymbol::new(
member.is_public(),
member.is_mut(),
member.identifier().name(),
Some(SourceDefinition::from_identifier(member.identifier())),
);
if let Err(insert_error) = symbol_table.insert_class_member_symbol(member_symbol) {
handle_insert_error(
insert_error,
member.identifier().name(),
member.identifier().file_id(),
member.identifier().range(),
"Class Member",
diagnostics,
);
}
gather_node(
member.type_use_mut(),
symbol_table,
fqn_context,
diagnostics,
);
}
fn gather_variable_declaration<'a>(
variable_declaration: &'a mut VariableDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let variable_symbol = VariableSymbol::new(
variable_declaration.identifier().name(),
variable_declaration.is_mut(),
Some(SourceDefinition::from_identifier(
variable_declaration.identifier(),
)),
);
if let Err(insert_error) = symbol_table.insert_variable_symbol(variable_symbol) {
handle_insert_error(
insert_error,
variable_declaration.identifier().name(),
variable_declaration.identifier().file_id(),
variable_declaration.identifier().range(),
"Variable",
diagnostics,
);
}
if let Some(expression) = variable_declaration.expression_mut() {
gather_node(expression, symbol_table, fqn_context, diagnostics);
}
}
fn gather_if_clause<'a>(
if_clause: &'a mut IfClause,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.push_scope("IfClauseScope");
gather_node(
if_clause.expression_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.push_scope("IfClauseStatementsScope");
for statement in if_clause.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
symbol_table.pop_scope();
}
fn gather_while_statement<'a>(
while_statement: &'a mut WhileStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.push_scope("WhileStatementScope");
gather_node(
while_statement.expression_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.push_scope("WhileStatementStatementsScope");
for statement in while_statement.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
symbol_table.pop_scope();
}
fn gather_for_statement<'a>(
for_statement: &'a mut ForStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
gather_node(
for_statement.expression_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.push_scope("ForStatementScope");
let identifier_symbol = VariableSymbol::new(
for_statement.identifier().name(),
false,
Some(SourceDefinition::from_identifier(
for_statement.identifier(),
)),
);
if let Err(insert_error) = symbol_table.insert_variable_symbol(identifier_symbol) {
handle_insert_error(
insert_error,
for_statement.identifier().name(),
for_statement.identifier().file_id(),
for_statement.identifier().range(),
"Variable",
diagnostics,
);
}
symbol_table.push_scope("ForStatementStatementsScope");
for statement in for_statement.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
symbol_table.pop_scope();
}
fn gather_variable_use<'a>(
variable_use: &'a VariableUse,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Err(lookup_error) = symbol_table.lookup_addressable_by_identifier(
variable_use.identifier().name(),
symbol_table.current_scope_id(),
) {
handle_lookup_error(
lookup_error,
variable_use.identifier().name(),
variable_use.identifier().file_id(),
variable_use.identifier().range(),
"Variable",
diagnostics,
)
}
}
fn gather_ternary_expression<'a>(
ternary_expression: &'a mut TernaryExpression,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.push_scope("TernaryExpressionScope");
gather_node_children(ternary_expression, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope();
}
fn gather_closure<'a>(
closure: &'a mut Closure,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.push_scope("ClosureScope");
gather_node(
closure.closure_parameters_mut(),
symbol_table,
fqn_context,
diagnostics,
);
symbol_table.push_scope("ClosureStatementsScope");
for statement in closure.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
symbol_table.pop_scope();
}
fn gather_closure_parameter<'a>(
closure_parameter: &'a mut ClosureParameter,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let parameter_symbol = ParameterSymbol::new(
closure_parameter.identifier().name(),
Some(SourceDefinition::from_identifier(
closure_parameter.identifier(),
)),
);
if let Err(insert_err) = symbol_table.insert_parameter_symbol(parameter_symbol) {
handle_insert_error(
insert_err,
closure_parameter.identifier().name(),
closure_parameter.identifier().file_id(),
closure_parameter.identifier().range(),
"Parameter",
diagnostics,
);
}
if let Some(type_use) = closure_parameter.type_use_mut() {
gather_node(type_use, symbol_table, fqn_context, diagnostics);
}
}