Various new ideas for name analysis.

This commit is contained in:
Jesse Brault 2025-10-20 18:31:54 -05:00
parent d32580a1d4
commit af8f0b5dac
14 changed files with 577 additions and 199 deletions

View File

@ -1,5 +1,5 @@
use convert_case::{Case, Casing};
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec}; use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
use convert_case::{Case, Casing};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
@ -10,20 +10,19 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
.map(|rule| { .map(|rule| {
let rule_ident = format_ident!("{}", rule.rule()); let rule_ident = format_ident!("{}", rule.rule());
match rule.child() { match rule.child() {
Some(child) => { Some(child) => match child.kind() {
match child.kind() { EnumRuleChildKind::Node(node_child) => {
EnumRuleChildKind::Node(node_child) => { let child_ident =
let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake)); format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
quote! { quote! {
#type_ident::#rule_ident(#child_ident) => vec![ #type_ident::#rule_ident(#child_ident) => vec![
#child_ident #child_ident
] ]
}
}
_ => quote! {
#type_ident::#rule_ident(_) => vec![]
} }
} }
_ => quote! {
#type_ident::#rule_ident(_) => vec![]
},
}, },
None => { None => {
quote! { quote! {
@ -33,7 +32,35 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut_match_arms = enum_spec
.rules()
.map(|rule| {
let rule_ident = format_ident!("{}", rule.rule());
match rule.child() {
Some(child) => match child.kind() {
EnumRuleChildKind::Node(node_child) => {
let child_ident =
format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
quote! {
#type_ident::#rule_ident(#child_ident) => {
f(#child_ident as &'a mut dyn AstNode<'a>)
}
}
}
_ => quote! {
#type_ident::#rule_ident(_) => {}
},
},
None => {
quote! {
#type_ident::#rule_ident => {}
}
}
}
})
.collect::<Vec<_>>();
quote! { quote! {
impl<'a> AstNode<'a> for #type_ident { impl<'a> AstNode<'a> for #type_ident {
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
@ -42,9 +69,19 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
} }
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
match self {
#(#mut_match_arms,)*
}
}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -10,9 +10,15 @@ pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
vec![] vec![]
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -10,9 +10,15 @@ pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream
vec![] vec![]
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -1,63 +1,47 @@
mod enum_ast_node; mod enum_ast_node;
mod leaf_enum_ast_node; mod leaf_enum_ast_node;
mod struct_ast_node;
mod leaf_struct_ast_node; mod leaf_struct_ast_node;
mod polymorphic_type_ast_node;
mod polymorphic_enum_loop_ast_node; mod polymorphic_enum_loop_ast_node;
mod polymorphic_type_ast_node;
mod struct_ast_node;
use crate::spec::BuildSpec;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl; use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl; use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl; use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl; use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl; use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl; use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
use crate::spec::BuildSpec;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> { pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
match build_spec { match build_spec {
BuildSpec::Enum(enum_spec) => { BuildSpec::Enum(enum_spec) => Some(make_enum_ast_node_impl(enum_spec)),
Some(make_enum_ast_node_impl(enum_spec)) BuildSpec::LeafEnum(leaf_enum) => Some(make_leaf_enum_ast_node_impl(leaf_enum)),
} BuildSpec::Struct(struct_spec) => Some(make_struct_ast_node_impl(struct_spec)),
BuildSpec::LeafEnum(leaf_enum) => { BuildSpec::LeafStruct(leaf_struct) => Some(make_leaf_struct_ast_node_impl(leaf_struct)),
Some(make_leaf_enum_ast_node_impl(leaf_enum))
}
BuildSpec::Struct(struct_spec) => {
Some(make_struct_ast_node_impl(struct_spec))
}
BuildSpec::LeafStruct(leaf_struct) => {
Some(make_leaf_struct_ast_node_impl(leaf_struct))
}
BuildSpec::Production(_) => None, BuildSpec::Production(_) => None,
BuildSpec::NodeProduction(_) => None, BuildSpec::NodeProduction(_) => None,
BuildSpec::PolymorphicType(polymorphic_type) => { BuildSpec::PolymorphicType(polymorphic_type) => {
Some(make_polymorphic_type_ast_node_impl(polymorphic_type)) Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
} }
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => { BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some(
Some(make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop)) make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
} ),
BuildSpec::PolymorphicPassThrough(_) => None, BuildSpec::PolymorphicPassThrough(_) => None,
} }
} }
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> { fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
match build_spec { match build_spec {
BuildSpec::Struct(struct_spec) => { BuildSpec::Struct(struct_spec) => Some(format_ident!("{}", struct_spec.build())),
Some(format_ident!("{}", struct_spec.build())) BuildSpec::LeafStruct(leaf_struct) => Some(format_ident!("{}", leaf_struct.build())),
} BuildSpec::Enum(enum_spec) => Some(format_ident!("{}", enum_spec.build())),
BuildSpec::LeafStruct(leaf_struct) => { BuildSpec::LeafEnum(leaf_enum) => Some(format_ident!("{}", leaf_enum.build())),
Some(format_ident!("{}", leaf_struct.build()))
}
BuildSpec::Enum(enum_spec) => {
Some(format_ident!("{}", enum_spec.build()))
}
BuildSpec::LeafEnum(leaf_enum) => {
Some(format_ident!("{}", leaf_enum.build()))
}
BuildSpec::PolymorphicType(polymorphic_type) => { BuildSpec::PolymorphicType(polymorphic_type) => {
Some(format_ident!("{}", polymorphic_type.name())) Some(format_ident!("{}", polymorphic_type.name()))
}, }
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => { BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
Some(format_ident!("{}", polymorphic_enum_loop.name())) Some(format_ident!("{}", polymorphic_enum_loop.name()))
} }
@ -65,40 +49,36 @@ pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
BuildSpec::Production(_) => None, BuildSpec::Production(_) => None,
BuildSpec::NodeProduction(_) => None, BuildSpec::NodeProduction(_) => None,
} }
.map(|type_ident| { }
quote! {
#type_ident(&'a #type_ident) pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
} make_type_ident(build_spec).map(|type_ident| {
}) quote! {
#type_ident(&'a #type_ident)
}
})
}
pub fn make_ast_enum_mut_member(build_spec: &BuildSpec) -> Option<TokenStream> {
make_type_ident(build_spec).map(|type_ident| {
quote! {
#type_ident(&'a mut #type_ident)
}
})
} }
pub fn make_ast_node_ref_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> { pub fn make_ast_node_ref_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> {
match build_spec { make_type_ident(build_spec).map(|type_ident| {
BuildSpec::Enum(enum_spec) => { quote! {
Some(format_ident!("{}", enum_spec.build())) AstNodeRef::#type_ident(inner) => *inner
} }
BuildSpec::LeafEnum(leaf_enum) => { })
Some(format_ident!("{}", leaf_enum.build())) }
pub fn make_ast_node_ref_mut_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> {
make_type_ident(build_spec).map(|type_ident| {
quote! {
AstNodeRefMut::#type_ident(inner) => *inner
} }
BuildSpec::Struct(struct_spec) => { })
Some(format_ident!("{}", struct_spec.build()))
}
BuildSpec::LeafStruct(leaf_struct) => {
Some(format_ident!("{}", leaf_struct.build()))
}
BuildSpec::Production(_) => None,
BuildSpec::NodeProduction(_) => None,
BuildSpec::PolymorphicType(polymorphic_type) => {
Some(format_ident!("{}", polymorphic_type.name()))
}
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
Some(format_ident!("{}", polymorphic_enum_loop.name()))
}
BuildSpec::PolymorphicPassThrough(_) => None
}
.map(|type_ident| {
quote! {
AstNodeRef::#type_ident(inner) => *inner
}
})
} }

View File

@ -41,9 +41,17 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
children children
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
todo!()
}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -16,6 +16,19 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let match_arms_mut = spec
.variants()
.map(|variant| {
let variant_ident = format_ident!("{}", variant.name());
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
quote! {
#type_ident::#variant_ident(#child_ident) => {
f(#child_ident as &'a mut dyn AstNode)
}
}
})
.collect::<Vec<_>>();
quote! { quote! {
impl<'a> AstNode<'a> for #type_ident { impl<'a> AstNode<'a> for #type_ident {
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> {
@ -24,9 +37,19 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
} }
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
match self {
#(#match_arms_mut,)*
}
}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -2,19 +2,27 @@ use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChi
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { fn make_child_adders(spec: &StructSpec, is_mut: bool) -> Vec<TokenStream> {
let type_ident = format_ident!("{}", spec.build()); let as_clause = if is_mut {
let child_adders = spec quote! { as &mut dyn AstNode }
.children() } else {
quote! { as &dyn AstNode }
};
spec.children()
.map(|child| match child { .map(|child| match child {
StructChild::SkipChild(_) => None, StructChild::SkipChild(_) => None,
StructChild::VecChild(vec_child) => match vec_child.build() { StructChild::VecChild(vec_child) => match vec_child.build() {
VecChildBuild::String(_) => None, VecChildBuild::String(_) => None,
VecChildBuild::Node(_) => { VecChildBuild::Node(_) => {
let child_ident = format_ident!("{}", vec_child.name()); let child_ident = if is_mut {
format_ident!("{}_mut", vec_child.name())
} else {
format_ident!("{}", vec_child.name())
};
let children_stream = quote! { let children_stream = quote! {
for child in self.#child_ident() { for child in self.#child_ident() {
children.push(child as &dyn AstNode); children.push(child #as_clause);
} }
}; };
Some(children_stream) Some(children_stream)
@ -22,16 +30,21 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
}, },
StructChild::MemberChild(member_child) => match member_child.build() { StructChild::MemberChild(member_child) => match member_child.build() {
MemberChildBuild::Node(_) => { MemberChildBuild::Node(_) => {
let child_ident = format_ident!("{}", member_child.name()); let child_ident = if is_mut {
format_ident!("{}_mut", member_child.name())
} else {
format_ident!("{}", member_child.name())
};
if member_child.optional() { if member_child.optional() {
Some(quote! { Some(quote! {
if let Some(#child_ident) = self.#child_ident() { if let Some(#child_ident) = self.#child_ident() {
children.push(#child_ident as &dyn AstNode); children.push(#child_ident #as_clause);
} }
}) })
} else { } else {
Some(quote! { Some(quote! {
children.push(self.#child_ident() as &dyn AstNode) children.push(self.#child_ident() #as_clause)
}) })
} }
} }
@ -41,7 +54,13 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
}) })
.filter(Option::is_some) .filter(Option::is_some)
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>()
}
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
let type_ident = format_ident!("{}", spec.build());
let child_adders = make_child_adders(spec, false);
let child_adders_mut = make_child_adders(spec, true);
quote! { quote! {
impl<'a> AstNode<'a> for #type_ident { impl<'a> AstNode<'a> for #type_ident {
@ -51,9 +70,17 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
children children
} }
fn for_each_child_mut(&'a mut self, mut f: &mut dyn FnMut(&'a mut dyn AstNode<'a>)) {
todo!()
}
fn as_node_ref(&'a self) -> AstNodeRef<'a> { fn as_node_ref(&'a self) -> AstNodeRef<'a> {
AstNodeRef::#type_ident(&self) AstNodeRef::#type_ident(&self)
} }
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
AstNodeRefMut::#type_ident(self)
}
} }
} }
} }

View File

@ -6,7 +6,10 @@ mod spec;
mod type_gen; mod type_gen;
mod walk; mod walk;
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl, make_ast_node_ref_unwrapper}; use crate::ast_node::{
make_ast_enum_member, make_ast_enum_mut_member, make_ast_node_impl,
make_ast_node_ref_mut_unwrapper, make_ast_node_ref_unwrapper,
};
use crate::build_fn::make_build_fn; use crate::build_fn::make_build_fn;
use crate::deserialize::deserialize_yaml_spec; use crate::deserialize::deserialize_yaml_spec;
use crate::pretty_print::make_pretty_print_impl; use crate::pretty_print::make_pretty_print_impl;
@ -165,6 +168,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let ast_enum_mut_members = build_specs
.iter()
.map(|build_spec| make_ast_enum_mut_member(build_spec))
.filter(Option::is_some)
.map(Option::unwrap)
.collect::<Vec<_>>();
let inner_unwrappers = build_specs let inner_unwrappers = build_specs
.iter() .iter()
.map(|build_spec| make_ast_node_ref_unwrapper(build_spec)) .map(|build_spec| make_ast_node_ref_unwrapper(build_spec))
@ -172,6 +182,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let inner_mut_unwrappers = build_specs
.iter()
.map(|build_spec| make_ast_node_ref_mut_unwrapper(build_spec))
.filter(Option::is_some)
.map(Option::unwrap)
.collect::<Vec<_>>();
let combined = quote! { let combined = quote! {
use crate::ast::node::*; use crate::ast::node::*;
@ -187,10 +204,26 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
} }
} }
pub enum AstNodeRefMut<'a> {
#(#ast_enum_mut_members,)*
}
impl<'a> AstNodeRefMut<'a> {
pub fn inner(&mut self) -> &mut dyn AstNode<'a> {
match self {
#(#inner_mut_unwrappers,)*
}
}
}
pub trait AstNode<'a> { pub trait AstNode<'a> {
fn children(&'a self) -> Vec<&'a dyn AstNode<'a>>; fn children(&'a self) -> Vec<&'a dyn AstNode<'a>>;
fn for_each_child_mut(&'a mut self, f: &mut dyn FnMut(&'a mut dyn AstNode<'a>));
fn as_node_ref(&'a self) -> AstNodeRef<'a>; fn as_node_ref(&'a self) -> AstNodeRef<'a>;
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a>;
} }
#(#impls)* #(#impls)*

View File

@ -0,0 +1,147 @@
use crate::ast::node::{CompilationUnit, UseStatement, UseStatementSuffix};
use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::fqn_context::FqnContext;
use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
use crate::name_analysis::util::use_statement_base_fqn;
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);
}
}
}
macro_rules! insert_symbol {
($insert_method:ident, $symbol:expr, $symbol_table:ident, $name:expr, $node:ident, $symbol_kinds:literal, $diagnostics:ident) => {
if let Err(insert_error) = $symbol_table.$insert_method($symbol) {
handle_insert_error(
insert_error,
$name,
$node.file_id(),
$node.range(),
$symbol_kinds,
$diagnostics,
)
}
};
}
macro_rules! insert_concrete_use_symbol {
($symbol:expr, $symbol_table:ident, $symbol_name:expr, $source_node:ident, $symbol_kinds:literal, $diagnostics:ident) => {
insert_symbol!(
insert_concrete_use_symbol,
$symbol,
$symbol_table,
$symbol_name,
$source_node,
$symbol_kinds,
$diagnostics
)
};
}
pub fn np1_compilation_unit(
file_name: &str,
compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let mut fqn_context = FqnContext::new();
symbol_table.push_scope(&format!("FileScope {}", file_name));
if let Some(namespace) = compilation_unit.namespace() {
for identifier in namespace.fqn().identifiers() {
fqn_context.push(identifier.name());
}
}
for use_statement in compilation_unit.use_statements_mut() {
np1_use_statement(use_statement, symbol_table, diagnostics);
}
symbol_table.pop_scope();
}
fn np1_use_statement(
use_statement: &mut UseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let base_fqn = use_statement_base_fqn(use_statement);
match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => {
insert_concrete_use_symbol!(
ConcreteUseSymbol::new(
&base_fqn,
identifier.name(),
Some(SourceDefinition::from_identifier(identifier))
),
symbol_table,
&base_fqn,
identifier,
"Use Statement",
diagnostics
)
}
UseStatementSuffix::Star => {
insert_symbol!(
insert_star_use_symbol,
StarUseSymbol::new(
&base_fqn,
Some(SourceDefinition::from_use_statement(use_statement))
),
symbol_table,
&base_fqn,
use_statement,
"Use Statement",
diagnostics
);
}
UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() {
insert_concrete_use_symbol!(
ConcreteUseSymbol::new(
&base_fqn,
identifier.name(),
Some(SourceDefinition::from_identifier(identifier))
),
symbol_table,
&base_fqn,
identifier,
"Use Statement",
diagnostics
);
}
}
}
}

View File

@ -1,5 +1,5 @@
/// The gather phase must exclusively gather all named items that can be used elsewhere. /// The gather phase must exclusively gather all named items that can be used elsewhere.
use crate::ast::ast_node::{AstNode, AstNodeRef}; use crate::ast::ast_node::{AstNode, AstNodeRef, AstNodeRefMut};
use crate::ast::node::{ use crate::ast::node::{
Class, Closure, ClosureParameter, CompilationUnit, ForStatement, Function, FunctionBody, Class, Closure, ClosureParameter, CompilationUnit, ForStatement, Function, FunctionBody,
GenericParameters, Identifier, IfClause, Interface, InterfaceDefaultFunction, GenericParameters, Identifier, IfClause, Interface, InterfaceDefaultFunction,
@ -81,54 +81,55 @@ fn handle_lookup_error(
} }
fn gather_node_children<'a>( fn gather_node_children<'a>(
node: &'a dyn AstNode<'a>, node: &'a mut dyn AstNode<'a>,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
for child in node.children() { node.for_each_child_mut(&mut |child| {
gather_node(child, symbol_table, fqn_context, diagnostics); gather_node(child, symbol_table, fqn_context, diagnostics);
} });
} }
fn gather_node<'a>( fn gather_node<'a>(
node: &'a dyn AstNode<'a>, node: &'a mut dyn AstNode<'a>,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match node.as_node_ref() { let node_ref = node.as_node_ref_mut();
AstNodeRef::GenericParameters(generic_parameters) => { match node_ref {
AstNodeRefMut::GenericParameters(generic_parameters) => {
gather_generic_parameters(generic_parameters, symbol_table, diagnostics); gather_generic_parameters(generic_parameters, symbol_table, diagnostics);
} }
AstNodeRef::Parameter(parameter) => { AstNodeRefMut::Parameter(parameter) => {
gather_parameter(parameter, symbol_table, diagnostics); gather_parameter(parameter, symbol_table, diagnostics);
} }
AstNodeRef::Namespace(namespace) => { AstNodeRefMut::Namespace(namespace) => {
gather_namespace(namespace, fqn_context); gather_namespace(namespace, fqn_context);
} }
AstNodeRef::UseStatement(use_statement) => { AstNodeRefMut::UseStatement(use_statement) => {
gather_use_statement(use_statement, symbol_table, diagnostics); gather_use_statement(use_statement, symbol_table, diagnostics);
} }
AstNodeRef::Module(module) => { AstNodeRefMut::Module(module) => {
gather_module(module, symbol_table, fqn_context, diagnostics); gather_module(module, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::Interface(interface) => { AstNodeRefMut::Interface(interface) => {
gather_interface(interface, symbol_table, fqn_context, diagnostics); gather_interface(interface, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::Class(class) => { AstNodeRefMut::Class(class) => {
gather_class(class, symbol_table, fqn_context, diagnostics); gather_class(class, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::Function(function) => { AstNodeRefMut::Function(function) => {
gather_function(function, symbol_table, fqn_context, diagnostics); gather_function(function, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::OperatorFunction(operator_function) => { AstNodeRefMut::OperatorFunction(operator_function) => {
gather_operator_function(operator_function, symbol_table, fqn_context, diagnostics); gather_operator_function(operator_function, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::PlatformFunction(platform_function) => { AstNodeRefMut::PlatformFunction(platform_function) => {
gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics); gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::PlatformOperatorFunction(platform_operator_function) => { AstNodeRefMut::PlatformOperatorFunction(platform_operator_function) => {
gather_platform_operator_function( gather_platform_operator_function(
platform_operator_function, platform_operator_function,
symbol_table, symbol_table,
@ -136,10 +137,10 @@ fn gather_node<'a>(
diagnostics, diagnostics,
); );
} }
AstNodeRef::InterfaceFunction(interface_function) => { AstNodeRefMut::InterfaceFunction(interface_function) => {
gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics); gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::InterfaceDefaultFunction(interface_default_function) => { AstNodeRefMut::InterfaceDefaultFunction(interface_default_function) => {
gather_interface_default_function( gather_interface_default_function(
interface_default_function, interface_default_function,
symbol_table, symbol_table,
@ -147,7 +148,7 @@ fn gather_node<'a>(
diagnostics, diagnostics,
); );
} }
AstNodeRef::InterfaceOperatorFunction(interface_operator_function) => { AstNodeRefMut::InterfaceOperatorFunction(interface_operator_function) => {
gather_interface_operator_function( gather_interface_operator_function(
interface_operator_function, interface_operator_function,
symbol_table, symbol_table,
@ -155,7 +156,7 @@ fn gather_node<'a>(
diagnostics, diagnostics,
); );
} }
AstNodeRef::InterfaceDefaultOperatorFunction(interface_default_operator_function) => { AstNodeRefMut::InterfaceDefaultOperatorFunction(interface_default_operator_function) => {
gather_interface_default_operator_function( gather_interface_default_operator_function(
interface_default_operator_function, interface_default_operator_function,
symbol_table, symbol_table,
@ -163,13 +164,13 @@ fn gather_node<'a>(
diagnostics, diagnostics,
); );
} }
AstNodeRef::FunctionBody(function_body) => { AstNodeRefMut::FunctionBody(function_body) => {
gather_function_body(function_body, symbol_table, fqn_context, diagnostics); gather_function_body(function_body, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::Member(member) => { AstNodeRefMut::Member(member) => {
gather_member(member, symbol_table, fqn_context, diagnostics); gather_member(member, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::VariableDeclaration(variable_declaration) => { AstNodeRefMut::VariableDeclaration(variable_declaration) => {
gather_variable_declaration( gather_variable_declaration(
variable_declaration, variable_declaration,
symbol_table, symbol_table,
@ -177,32 +178,32 @@ fn gather_node<'a>(
diagnostics, diagnostics,
); );
} }
AstNodeRef::IfClause(if_clause) => { AstNodeRefMut::IfClause(if_clause) => {
gather_if_clause(if_clause, symbol_table, fqn_context, diagnostics); gather_if_clause(if_clause, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::IfElseIf(if_else_if) => { AstNodeRefMut::IfElseIf(if_else_if) => {
gather_node_children(if_else_if, symbol_table, fqn_context, diagnostics); gather_node_children(if_else_if, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::WhileStatement(while_statement) => { AstNodeRefMut::WhileStatement(while_statement) => {
gather_while_statement(while_statement, symbol_table, fqn_context, diagnostics); gather_while_statement(while_statement, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::ForStatement(for_statement) => { AstNodeRefMut::ForStatement(for_statement) => {
gather_for_statement(for_statement, symbol_table, fqn_context, diagnostics); gather_for_statement(for_statement, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::VariableUse(variable_use) => { AstNodeRefMut::VariableUse(variable_use) => {
gather_variable_use(variable_use, symbol_table, diagnostics); gather_variable_use(variable_use, symbol_table, diagnostics);
} }
AstNodeRef::TernaryExpression(ternary_expression) => { AstNodeRefMut::TernaryExpression(ternary_expression) => {
gather_ternary_expression(ternary_expression, symbol_table, fqn_context, diagnostics); gather_ternary_expression(ternary_expression, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::Closure(closure) => { AstNodeRefMut::Closure(closure) => {
gather_closure(closure, symbol_table, fqn_context, diagnostics); gather_closure(closure, symbol_table, fqn_context, diagnostics);
} }
AstNodeRef::ClosureParameter(closure_parameter) => { AstNodeRefMut::ClosureParameter(closure_parameter) => {
gather_closure_parameter(closure_parameter, symbol_table, fqn_context, diagnostics); gather_closure_parameter(closure_parameter, symbol_table, fqn_context, diagnostics);
} }
_ => gather_node_children(node, symbol_table, fqn_context, diagnostics), _ => todo!()
} }
} }
@ -230,7 +231,7 @@ fn gather_generic_parameters<'a>(
} }
fn gather_parameter<'a>( fn gather_parameter<'a>(
parameter: &'a Parameter, parameter: &'a mut Parameter,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
@ -251,7 +252,7 @@ fn gather_parameter<'a>(
} }
pub fn gather_compilation_unit<'a>( pub fn gather_compilation_unit<'a>(
compilation_unit: &'a CompilationUnit, compilation_unit: &'a mut CompilationUnit,
file_name: &str, file_name: &str,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -337,7 +338,7 @@ fn gather_concrete_use_symbol(
} }
fn gather_module<'a>( fn gather_module<'a>(
module: &'a Module, module: &'a mut Module,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -362,7 +363,7 @@ fn gather_module<'a>(
fqn_context.push(module.identifier().name()); fqn_context.push(module.identifier().name());
symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name())); symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name()));
for declaration in module.declarations() { for declaration in module.declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics); gather_node(declaration, symbol_table, fqn_context, diagnostics);
} }
@ -371,7 +372,7 @@ fn gather_module<'a>(
} }
fn gather_interface<'a>( fn gather_interface<'a>(
interface: &'a Interface, interface: &'a mut Interface,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -399,7 +400,7 @@ fn gather_interface<'a>(
fqn_context.push(interface.identifier().name()); fqn_context.push(interface.identifier().name());
symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name())); symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name()));
for declaration in interface.declarations() { for declaration in interface.declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics); gather_node(declaration, symbol_table, fqn_context, diagnostics);
} }
@ -408,7 +409,7 @@ fn gather_interface<'a>(
} }
fn gather_class<'a>( fn gather_class<'a>(
class: &'a Class, class: &'a mut Class,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -437,12 +438,12 @@ fn gather_class<'a>(
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name())); symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
gather_node( gather_node(
class.class_constructor(), class.class_constructor_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
for declaration in class.class_level_declarations() { for declaration in class.class_level_declarations_mut() {
gather_node(declaration, symbol_table, fqn_context, diagnostics); gather_node(declaration, symbol_table, fqn_context, diagnostics);
} }
@ -451,7 +452,7 @@ fn gather_class<'a>(
} }
fn gather_function<'a>( fn gather_function<'a>(
function: &'a Function, function: &'a mut Function,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -474,21 +475,21 @@ fn gather_function<'a>(
); );
} }
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name())); symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
gather_node(function.generics(), symbol_table, fqn_context, diagnostics); gather_node(function.generics_mut(), symbol_table, fqn_context, diagnostics);
gather_node( gather_node(
function.parameters(), function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
function.return_type(), function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
function.function_body(), function.function_body_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -497,7 +498,7 @@ fn gather_function<'a>(
} }
fn gather_operator_function<'a>( fn gather_operator_function<'a>(
operator_function: &'a OperatorFunction, operator_function: &'a mut OperatorFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -526,25 +527,25 @@ fn gather_operator_function<'a>(
operator_function.operator().inner().name() operator_function.operator().inner().name()
)); ));
gather_node( gather_node(
operator_function.generics(), operator_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
operator_function.parameters(), operator_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
operator_function.return_type(), operator_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
operator_function.function_body(), operator_function.function_body_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -553,7 +554,7 @@ fn gather_operator_function<'a>(
} }
fn gather_platform_function<'a>( fn gather_platform_function<'a>(
platform_function: &'a PlatformFunction, platform_function: &'a mut PlatformFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -582,19 +583,19 @@ fn gather_platform_function<'a>(
platform_function.identifier().name() platform_function.identifier().name()
)); ));
gather_node( gather_node(
platform_function.generics(), platform_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
platform_function.parameters(), platform_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
platform_function.return_type(), platform_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -603,7 +604,7 @@ fn gather_platform_function<'a>(
} }
fn gather_platform_operator_function<'a>( fn gather_platform_operator_function<'a>(
platform_operator_function: &'a PlatformOperatorFunction, platform_operator_function: &'a mut PlatformOperatorFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -632,19 +633,19 @@ fn gather_platform_operator_function<'a>(
platform_operator_function.operator().inner().name() platform_operator_function.operator().inner().name()
)); ));
gather_node( gather_node(
platform_operator_function.generics(), platform_operator_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
platform_operator_function.parameters(), platform_operator_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
platform_operator_function.return_type(), platform_operator_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -653,7 +654,7 @@ fn gather_platform_operator_function<'a>(
} }
fn gather_interface_function<'a>( fn gather_interface_function<'a>(
interface_function: &'a InterfaceFunction, interface_function: &'a mut InterfaceFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -682,19 +683,19 @@ fn gather_interface_function<'a>(
interface_function.identifier().name() interface_function.identifier().name()
)); ));
gather_node( gather_node(
interface_function.generics(), interface_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_function.parameters(), interface_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_function.return_type(), interface_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -703,7 +704,7 @@ fn gather_interface_function<'a>(
} }
fn gather_interface_default_function<'a>( fn gather_interface_default_function<'a>(
interface_default_function: &'a InterfaceDefaultFunction, interface_default_function: &'a mut InterfaceDefaultFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -732,25 +733,25 @@ fn gather_interface_default_function<'a>(
interface_default_function.identifier().name() interface_default_function.identifier().name()
)); ));
gather_node( gather_node(
interface_default_function.generics(), interface_default_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_function.parameters(), interface_default_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_function.return_type(), interface_default_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_function.function_body(), interface_default_function.function_body_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -759,7 +760,7 @@ fn gather_interface_default_function<'a>(
} }
fn gather_interface_operator_function<'a>( fn gather_interface_operator_function<'a>(
interface_operator_function: &'a InterfaceOperatorFunction, interface_operator_function: &'a mut InterfaceOperatorFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -788,19 +789,19 @@ fn gather_interface_operator_function<'a>(
interface_operator_function.operator().inner().name() interface_operator_function.operator().inner().name()
)); ));
gather_node( gather_node(
interface_operator_function.generics(), interface_operator_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_operator_function.parameters(), interface_operator_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_operator_function.return_type(), interface_operator_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -809,7 +810,7 @@ fn gather_interface_operator_function<'a>(
} }
fn gather_interface_default_operator_function<'a>( fn gather_interface_default_operator_function<'a>(
interface_default_operator_function: &'a InterfaceDefaultOperatorFunction, interface_default_operator_function: &'a mut InterfaceDefaultOperatorFunction,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -852,25 +853,25 @@ fn gather_interface_default_operator_function<'a>(
.name() .name()
)); ));
gather_node( gather_node(
interface_default_operator_function.generics(), interface_default_operator_function.generics_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_operator_function.parameters(), interface_default_operator_function.parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_operator_function.return_type(), interface_default_operator_function.return_type_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
gather_node( gather_node(
interface_default_operator_function.function_body(), interface_default_operator_function.function_body_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -879,7 +880,7 @@ fn gather_interface_default_operator_function<'a>(
} }
fn gather_function_body<'a>( fn gather_function_body<'a>(
function_body: &'a FunctionBody, function_body: &'a mut FunctionBody,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -890,7 +891,7 @@ fn gather_function_body<'a>(
} }
fn gather_member<'a>( fn gather_member<'a>(
member: &'a Member, member: &'a mut Member,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -911,11 +912,11 @@ fn gather_member<'a>(
diagnostics, diagnostics,
); );
} }
gather_node(member.type_use(), symbol_table, fqn_context, diagnostics); gather_node(member.type_use_mut(), symbol_table, fqn_context, diagnostics);
} }
fn gather_variable_declaration<'a>( fn gather_variable_declaration<'a>(
variable_declaration: &'a VariableDeclaration, variable_declaration: &'a mut VariableDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -937,26 +938,26 @@ fn gather_variable_declaration<'a>(
diagnostics, diagnostics,
); );
} }
if let Some(expression) = variable_declaration.expression() { if let Some(expression) = variable_declaration.expression_mut() {
gather_node(expression, symbol_table, fqn_context, diagnostics); gather_node(expression, symbol_table, fqn_context, diagnostics);
} }
} }
fn gather_if_clause<'a>( fn gather_if_clause<'a>(
if_clause: &'a IfClause, if_clause: &'a mut IfClause,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
symbol_table.push_scope("IfClauseScope"); symbol_table.push_scope("IfClauseScope");
gather_node( gather_node(
if_clause.expression(), if_clause.expression_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
symbol_table.push_scope("IfClauseStatementsScope"); symbol_table.push_scope("IfClauseStatementsScope");
for statement in if_clause.statements() { for statement in if_clause.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics); gather_node(statement, symbol_table, fqn_context, diagnostics);
} }
symbol_table.pop_scope(); symbol_table.pop_scope();
@ -964,20 +965,20 @@ fn gather_if_clause<'a>(
} }
fn gather_while_statement<'a>( fn gather_while_statement<'a>(
while_statement: &'a WhileStatement, while_statement: &'a mut WhileStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
symbol_table.push_scope("WhileStatementScope"); symbol_table.push_scope("WhileStatementScope");
gather_node( gather_node(
while_statement.expression(), while_statement.expression_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
symbol_table.push_scope("WhileStatementStatementsScope"); symbol_table.push_scope("WhileStatementStatementsScope");
for statement in while_statement.statements() { for statement in while_statement.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics); gather_node(statement, symbol_table, fqn_context, diagnostics);
} }
symbol_table.pop_scope(); symbol_table.pop_scope();
@ -985,13 +986,13 @@ fn gather_while_statement<'a>(
} }
fn gather_for_statement<'a>( fn gather_for_statement<'a>(
for_statement: &'a ForStatement, for_statement: &'a mut ForStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
gather_node( gather_node(
for_statement.expression(), for_statement.expression_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
@ -1015,7 +1016,7 @@ fn gather_for_statement<'a>(
); );
} }
symbol_table.push_scope("ForStatementStatementsScope"); symbol_table.push_scope("ForStatementStatementsScope");
for statement in for_statement.statements() { for statement in for_statement.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics); gather_node(statement, symbol_table, fqn_context, diagnostics);
} }
symbol_table.pop_scope(); symbol_table.pop_scope();
@ -1043,7 +1044,7 @@ fn gather_variable_use<'a>(
} }
fn gather_ternary_expression<'a>( fn gather_ternary_expression<'a>(
ternary_expression: &'a TernaryExpression, ternary_expression: &'a mut TernaryExpression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -1054,20 +1055,20 @@ fn gather_ternary_expression<'a>(
} }
fn gather_closure<'a>( fn gather_closure<'a>(
closure: &'a Closure, closure: &'a mut Closure,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
symbol_table.push_scope("ClosureScope"); symbol_table.push_scope("ClosureScope");
gather_node( gather_node(
closure.closure_parameters(), closure.closure_parameters_mut(),
symbol_table, symbol_table,
fqn_context, fqn_context,
diagnostics, diagnostics,
); );
symbol_table.push_scope("ClosureStatementsScope"); symbol_table.push_scope("ClosureStatementsScope");
for statement in closure.statements() { for statement in closure.statements_mut() {
gather_node(statement, symbol_table, fqn_context, diagnostics); gather_node(statement, symbol_table, fqn_context, diagnostics);
} }
symbol_table.pop_scope(); symbol_table.pop_scope();
@ -1075,7 +1076,7 @@ fn gather_closure<'a>(
} }
fn gather_closure_parameter<'a>( fn gather_closure_parameter<'a>(
closure_parameter: &'a ClosureParameter, closure_parameter: &'a mut ClosureParameter,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -1096,7 +1097,7 @@ fn gather_closure_parameter<'a>(
diagnostics, diagnostics,
); );
} }
if let Some(type_use) = closure_parameter.type_use() { if let Some(type_use) = closure_parameter.type_use_mut() {
gather_node(type_use, symbol_table, fqn_context, diagnostics); gather_node(type_use, symbol_table, fqn_context, diagnostics);
} }
} }

View File

@ -23,7 +23,7 @@ The resolve phase has one main responsibility: resolve all references based on t
use crate::ast::ast_node::AstNode; use crate::ast::ast_node::AstNode;
use crate::ast::node::CompilationUnit; use crate::ast::node::CompilationUnit;
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::gather::gather_compilation_unit; use crate::name_analysis::first_pass::np1_compilation_unit;
use crate::name_analysis::symbol_table::SymbolTable; use crate::name_analysis::symbol_table::SymbolTable;
use codespan_reporting::files::Files; use codespan_reporting::files::Files;
use std::hash::Hash; use std::hash::Hash;
@ -31,26 +31,24 @@ use std::hash::Hash;
pub(self) mod fqn_context; pub(self) mod fqn_context;
mod gather; mod gather;
// mod resolve; // mod resolve;
mod first_pass;
mod scope_table;
mod second_pass;
pub mod symbol; pub mod symbol;
pub mod symbol_table; pub mod symbol_table;
mod scope_table; mod util;
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
compilation_units: &[Box<CompilationUnit>], compilation_units: &mut Vec<Box<CompilationUnit>>,
files: &'a F, files: &'a F,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
) -> Vec<DmDiagnostic> { ) -> Vec<DmDiagnostic> {
let mut diagnostics = vec![]; let mut diagnostics = vec![];
// gather symbols // gather symbols
for compilation_unit in compilation_units { for compilation_unit in compilation_units.iter_mut() {
let file_name = files.name(compilation_unit.file_id()).unwrap(); let file_name = files.name(compilation_unit.file_id()).unwrap();
gather_compilation_unit( np1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics);
compilation_unit,
&file_name,
symbol_table,
&mut diagnostics,
);
} }
// resolve symbols // resolve symbols

View File

@ -0,0 +1,87 @@
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
use crate::name_analysis::util::use_statement_base_fqn;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::range::Range;
fn handle_lookup_error(
err: SymbolLookupError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolLookupError::NoDefinition => {
let diagnostic = Diagnostic::error()
.with_message(format!(
"No such {} symbol '{}' in scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
);
diagnostics.push(diagnostic);
}
}
}
pub fn nap2_compilation_unit(
compilation_unit: &mut CompilationUnit,
symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
// TODO: check namespace for proper file name
for use_statement in compilation_unit.use_statements_mut() {
nap2_use_statement(use_statement, symbol_table, diagnostics);
}
// TODO: declarations
}
fn nap2_use_statement(
use_statement: &mut UseStatement,
symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let base_fqn = use_statement_base_fqn(use_statement);
let mut handle_concrete_use_symbol = |identifier: &Identifier| {
let fqn = format!("{}::{}", base_fqn, identifier.name());
if let Err(error) = symbol_table.resolve_usable_by_fqn(&fqn) {
handle_lookup_error(
error,
&fqn,
use_statement.file_id(),
use_statement.range(),
"Usable Symbol",
diagnostics,
);
}
};
match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => {
handle_concrete_use_symbol(identifier);
}
UseStatementSuffix::Star => {
if let Err(error) = symbol_table.resolve_usable_star(&base_fqn) {
handle_lookup_error(
error,
&base_fqn,
use_statement.file_id(),
use_statement.range(),
"Star Usable Symbol",
diagnostics,
);
}
}
UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() {
handle_concrete_use_symbol(identifier);
}
}
}
}

View File

@ -377,6 +377,20 @@ impl SymbolTable {
} }
Err(NoDefinition) Err(NoDefinition)
} }
pub fn resolve_usable_by_fqn(
&self,
fqn: &str
) -> Result<Symbol, SymbolLookupError> {
todo!()
}
pub fn resolve_usable_star(
&self,
base_fqn: &str,
) -> Result<(), SymbolLookupError> {
todo!()
}
} }
impl Display for SymbolTable { impl Display for SymbolTable {

11
src/name_analysis/util.rs Normal file
View File

@ -0,0 +1,11 @@
use crate::ast::node::UseStatement;
pub fn use_statement_base_fqn(
use_statement: &UseStatement
) -> String {
use_statement
.prefixes()
.map(|prefix| prefix.identifier().name())
.collect::<Vec<_>>()
.join("::")
}