1114 lines
35 KiB
Rust
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);
|
|
}
|
|
}
|