Various new ideas for name analysis.
This commit is contained in:
parent
d32580a1d4
commit
af8f0b5dac
@ -1,5 +1,5 @@
|
||||
use convert_case::{Case, Casing};
|
||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
@ -10,20 +10,19 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
||||
.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) => vec![
|
||||
#child_ident
|
||||
]
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
#type_ident::#rule_ident(_) => vec![]
|
||||
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) => vec![
|
||||
#child_ident
|
||||
]
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
#type_ident::#rule_ident(_) => vec![]
|
||||
},
|
||||
},
|
||||
None => {
|
||||
quote! {
|
||||
@ -33,7 +32,35 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
||||
}
|
||||
})
|
||||
.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! {
|
||||
impl<'a> AstNode<'a> for #type_ident {
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,9 +10,15 @@ pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,9 +10,15 @@ pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,63 +1,47 @@
|
||||
mod enum_ast_node;
|
||||
mod leaf_enum_ast_node;
|
||||
mod struct_ast_node;
|
||||
mod leaf_struct_ast_node;
|
||||
mod polymorphic_type_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::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::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::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> {
|
||||
match build_spec {
|
||||
BuildSpec::Enum(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::LeafStruct(leaf_struct) => {
|
||||
Some(make_leaf_struct_ast_node_impl(leaf_struct))
|
||||
}
|
||||
BuildSpec::Enum(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::LeafStruct(leaf_struct) => Some(make_leaf_struct_ast_node_impl(leaf_struct)),
|
||||
BuildSpec::Production(_) => None,
|
||||
BuildSpec::NodeProduction(_) => None,
|
||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||
Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
|
||||
}
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||
Some(make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop))
|
||||
}
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some(
|
||||
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
||||
),
|
||||
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 {
|
||||
BuildSpec::Struct(struct_spec) => {
|
||||
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::LeafEnum(leaf_enum) => {
|
||||
Some(format_ident!("{}", leaf_enum.build()))
|
||||
}
|
||||
BuildSpec::Struct(struct_spec) => 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::LeafEnum(leaf_enum) => Some(format_ident!("{}", leaf_enum.build())),
|
||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||
Some(format_ident!("{}", polymorphic_type.name()))
|
||||
},
|
||||
}
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||
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::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> {
|
||||
match build_spec {
|
||||
BuildSpec::Enum(enum_spec) => {
|
||||
Some(format_ident!("{}", enum_spec.build()))
|
||||
make_type_ident(build_spec).map(|type_ident| {
|
||||
quote! {
|
||||
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
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -41,9 +41,17 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,19 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
|
||||
})
|
||||
.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! {
|
||||
impl<'a> AstNode<'a> for #type_ident {
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,19 +2,27 @@ use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChi
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.build());
|
||||
let child_adders = spec
|
||||
.children()
|
||||
fn make_child_adders(spec: &StructSpec, is_mut: bool) -> Vec<TokenStream> {
|
||||
let as_clause = if is_mut {
|
||||
quote! { as &mut dyn AstNode }
|
||||
} else {
|
||||
quote! { as &dyn AstNode }
|
||||
};
|
||||
|
||||
spec.children()
|
||||
.map(|child| match child {
|
||||
StructChild::SkipChild(_) => None,
|
||||
StructChild::VecChild(vec_child) => match vec_child.build() {
|
||||
VecChildBuild::String(_) => None,
|
||||
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! {
|
||||
for child in self.#child_ident() {
|
||||
children.push(child as &dyn AstNode);
|
||||
children.push(child #as_clause);
|
||||
}
|
||||
};
|
||||
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() {
|
||||
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() {
|
||||
Some(quote! {
|
||||
if let Some(#child_ident) = self.#child_ident() {
|
||||
children.push(#child_ident as &dyn AstNode);
|
||||
children.push(#child_ident #as_clause);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
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)
|
||||
.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! {
|
||||
impl<'a> AstNode<'a> for #type_ident {
|
||||
@ -51,9 +70,17 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||
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> {
|
||||
AstNodeRef::#type_ident(&self)
|
||||
}
|
||||
|
||||
fn as_node_ref_mut(&'a mut self) -> AstNodeRefMut<'a> {
|
||||
AstNodeRefMut::#type_ident(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,10 @@ mod spec;
|
||||
mod type_gen;
|
||||
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::deserialize::deserialize_yaml_spec;
|
||||
use crate::pretty_print::make_pretty_print_impl;
|
||||
@ -165,6 +168,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
.map(Option::unwrap)
|
||||
.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
|
||||
.iter()
|
||||
.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)
|
||||
.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! {
|
||||
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> {
|
||||
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_mut(&'a mut self) -> AstNodeRefMut<'a>;
|
||||
}
|
||||
|
||||
#(#impls)*
|
||||
|
||||
147
src/name_analysis/first_pass.rs
Normal file
147
src/name_analysis/first_pass.rs
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/// 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::{
|
||||
Class, Closure, ClosureParameter, CompilationUnit, ForStatement, Function, FunctionBody,
|
||||
GenericParameters, Identifier, IfClause, Interface, InterfaceDefaultFunction,
|
||||
@ -81,54 +81,55 @@ fn handle_lookup_error(
|
||||
}
|
||||
|
||||
fn gather_node_children<'a>(
|
||||
node: &'a dyn AstNode<'a>,
|
||||
node: &'a mut dyn AstNode<'a>,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
for child in node.children() {
|
||||
gather_node(child, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
node.for_each_child_mut(&mut |child| {
|
||||
gather_node(child, symbol_table, fqn_context, diagnostics);
|
||||
});
|
||||
}
|
||||
|
||||
fn gather_node<'a>(
|
||||
node: &'a dyn AstNode<'a>,
|
||||
node: &'a mut dyn AstNode<'a>,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
match node.as_node_ref() {
|
||||
AstNodeRef::GenericParameters(generic_parameters) => {
|
||||
let node_ref = node.as_node_ref_mut();
|
||||
match node_ref {
|
||||
AstNodeRefMut::GenericParameters(generic_parameters) => {
|
||||
gather_generic_parameters(generic_parameters, symbol_table, diagnostics);
|
||||
}
|
||||
AstNodeRef::Parameter(parameter) => {
|
||||
AstNodeRefMut::Parameter(parameter) => {
|
||||
gather_parameter(parameter, symbol_table, diagnostics);
|
||||
}
|
||||
AstNodeRef::Namespace(namespace) => {
|
||||
AstNodeRefMut::Namespace(namespace) => {
|
||||
gather_namespace(namespace, fqn_context);
|
||||
}
|
||||
AstNodeRef::UseStatement(use_statement) => {
|
||||
AstNodeRefMut::UseStatement(use_statement) => {
|
||||
gather_use_statement(use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
AstNodeRef::Module(module) => {
|
||||
AstNodeRefMut::Module(module) => {
|
||||
gather_module(module, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::Interface(interface) => {
|
||||
AstNodeRefMut::Interface(interface) => {
|
||||
gather_interface(interface, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::Class(class) => {
|
||||
AstNodeRefMut::Class(class) => {
|
||||
gather_class(class, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::Function(function) => {
|
||||
AstNodeRefMut::Function(function) => {
|
||||
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);
|
||||
}
|
||||
AstNodeRef::PlatformFunction(platform_function) => {
|
||||
AstNodeRefMut::PlatformFunction(platform_function) => {
|
||||
gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::PlatformOperatorFunction(platform_operator_function) => {
|
||||
AstNodeRefMut::PlatformOperatorFunction(platform_operator_function) => {
|
||||
gather_platform_operator_function(
|
||||
platform_operator_function,
|
||||
symbol_table,
|
||||
@ -136,10 +137,10 @@ fn gather_node<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
AstNodeRef::InterfaceFunction(interface_function) => {
|
||||
AstNodeRefMut::InterfaceFunction(interface_function) => {
|
||||
gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::InterfaceDefaultFunction(interface_default_function) => {
|
||||
AstNodeRefMut::InterfaceDefaultFunction(interface_default_function) => {
|
||||
gather_interface_default_function(
|
||||
interface_default_function,
|
||||
symbol_table,
|
||||
@ -147,7 +148,7 @@ fn gather_node<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
AstNodeRef::InterfaceOperatorFunction(interface_operator_function) => {
|
||||
AstNodeRefMut::InterfaceOperatorFunction(interface_operator_function) => {
|
||||
gather_interface_operator_function(
|
||||
interface_operator_function,
|
||||
symbol_table,
|
||||
@ -155,7 +156,7 @@ fn gather_node<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
AstNodeRef::InterfaceDefaultOperatorFunction(interface_default_operator_function) => {
|
||||
AstNodeRefMut::InterfaceDefaultOperatorFunction(interface_default_operator_function) => {
|
||||
gather_interface_default_operator_function(
|
||||
interface_default_operator_function,
|
||||
symbol_table,
|
||||
@ -163,13 +164,13 @@ fn gather_node<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
AstNodeRef::FunctionBody(function_body) => {
|
||||
AstNodeRefMut::FunctionBody(function_body) => {
|
||||
gather_function_body(function_body, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::Member(member) => {
|
||||
AstNodeRefMut::Member(member) => {
|
||||
gather_member(member, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
AstNodeRef::VariableDeclaration(variable_declaration) => {
|
||||
AstNodeRefMut::VariableDeclaration(variable_declaration) => {
|
||||
gather_variable_declaration(
|
||||
variable_declaration,
|
||||
symbol_table,
|
||||
@ -177,32 +178,32 @@ fn gather_node<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
AstNodeRef::IfClause(if_clause) => {
|
||||
AstNodeRefMut::IfClause(if_clause) => {
|
||||
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);
|
||||
}
|
||||
AstNodeRef::WhileStatement(while_statement) => {
|
||||
AstNodeRefMut::WhileStatement(while_statement) => {
|
||||
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);
|
||||
}
|
||||
AstNodeRef::VariableUse(variable_use) => {
|
||||
AstNodeRefMut::VariableUse(variable_use) => {
|
||||
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);
|
||||
}
|
||||
|
||||
AstNodeRef::Closure(closure) => {
|
||||
AstNodeRefMut::Closure(closure) => {
|
||||
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_node_children(node, symbol_table, fqn_context, diagnostics),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +231,7 @@ fn gather_generic_parameters<'a>(
|
||||
}
|
||||
|
||||
fn gather_parameter<'a>(
|
||||
parameter: &'a Parameter,
|
||||
parameter: &'a mut Parameter,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
@ -251,7 +252,7 @@ fn gather_parameter<'a>(
|
||||
}
|
||||
|
||||
pub fn gather_compilation_unit<'a>(
|
||||
compilation_unit: &'a CompilationUnit,
|
||||
compilation_unit: &'a mut CompilationUnit,
|
||||
file_name: &str,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -337,7 +338,7 @@ fn gather_concrete_use_symbol(
|
||||
}
|
||||
|
||||
fn gather_module<'a>(
|
||||
module: &'a Module,
|
||||
module: &'a mut Module,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -362,7 +363,7 @@ fn gather_module<'a>(
|
||||
fqn_context.push(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);
|
||||
}
|
||||
|
||||
@ -371,7 +372,7 @@ fn gather_module<'a>(
|
||||
}
|
||||
|
||||
fn gather_interface<'a>(
|
||||
interface: &'a Interface,
|
||||
interface: &'a mut Interface,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -399,7 +400,7 @@ fn gather_interface<'a>(
|
||||
fqn_context.push(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);
|
||||
}
|
||||
|
||||
@ -408,7 +409,7 @@ fn gather_interface<'a>(
|
||||
}
|
||||
|
||||
fn gather_class<'a>(
|
||||
class: &'a Class,
|
||||
class: &'a mut Class,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -437,12 +438,12 @@ fn gather_class<'a>(
|
||||
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
|
||||
|
||||
gather_node(
|
||||
class.class_constructor(),
|
||||
class.class_constructor_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
for declaration in class.class_level_declarations() {
|
||||
for declaration in class.class_level_declarations_mut() {
|
||||
gather_node(declaration, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
|
||||
@ -451,7 +452,7 @@ fn gather_class<'a>(
|
||||
}
|
||||
|
||||
fn gather_function<'a>(
|
||||
function: &'a Function,
|
||||
function: &'a mut Function,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -474,21 +475,21 @@ fn gather_function<'a>(
|
||||
);
|
||||
}
|
||||
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(
|
||||
function.parameters(),
|
||||
function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
function.return_type(),
|
||||
function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
function.function_body(),
|
||||
function.function_body_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -497,7 +498,7 @@ fn gather_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_operator_function<'a>(
|
||||
operator_function: &'a OperatorFunction,
|
||||
operator_function: &'a mut OperatorFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -526,25 +527,25 @@ fn gather_operator_function<'a>(
|
||||
operator_function.operator().inner().name()
|
||||
));
|
||||
gather_node(
|
||||
operator_function.generics(),
|
||||
operator_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
operator_function.parameters(),
|
||||
operator_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
operator_function.return_type(),
|
||||
operator_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
operator_function.function_body(),
|
||||
operator_function.function_body_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -553,7 +554,7 @@ fn gather_operator_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_platform_function<'a>(
|
||||
platform_function: &'a PlatformFunction,
|
||||
platform_function: &'a mut PlatformFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -582,19 +583,19 @@ fn gather_platform_function<'a>(
|
||||
platform_function.identifier().name()
|
||||
));
|
||||
gather_node(
|
||||
platform_function.generics(),
|
||||
platform_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
platform_function.parameters(),
|
||||
platform_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
platform_function.return_type(),
|
||||
platform_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -603,7 +604,7 @@ fn gather_platform_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_platform_operator_function<'a>(
|
||||
platform_operator_function: &'a PlatformOperatorFunction,
|
||||
platform_operator_function: &'a mut PlatformOperatorFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -632,19 +633,19 @@ fn gather_platform_operator_function<'a>(
|
||||
platform_operator_function.operator().inner().name()
|
||||
));
|
||||
gather_node(
|
||||
platform_operator_function.generics(),
|
||||
platform_operator_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
platform_operator_function.parameters(),
|
||||
platform_operator_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
platform_operator_function.return_type(),
|
||||
platform_operator_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -653,7 +654,7 @@ fn gather_platform_operator_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_interface_function<'a>(
|
||||
interface_function: &'a InterfaceFunction,
|
||||
interface_function: &'a mut InterfaceFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -682,19 +683,19 @@ fn gather_interface_function<'a>(
|
||||
interface_function.identifier().name()
|
||||
));
|
||||
gather_node(
|
||||
interface_function.generics(),
|
||||
interface_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_function.parameters(),
|
||||
interface_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_function.return_type(),
|
||||
interface_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -703,7 +704,7 @@ fn gather_interface_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_interface_default_function<'a>(
|
||||
interface_default_function: &'a InterfaceDefaultFunction,
|
||||
interface_default_function: &'a mut InterfaceDefaultFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -732,25 +733,25 @@ fn gather_interface_default_function<'a>(
|
||||
interface_default_function.identifier().name()
|
||||
));
|
||||
gather_node(
|
||||
interface_default_function.generics(),
|
||||
interface_default_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_function.parameters(),
|
||||
interface_default_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_function.return_type(),
|
||||
interface_default_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_function.function_body(),
|
||||
interface_default_function.function_body_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -759,7 +760,7 @@ fn gather_interface_default_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_interface_operator_function<'a>(
|
||||
interface_operator_function: &'a InterfaceOperatorFunction,
|
||||
interface_operator_function: &'a mut InterfaceOperatorFunction,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -788,19 +789,19 @@ fn gather_interface_operator_function<'a>(
|
||||
interface_operator_function.operator().inner().name()
|
||||
));
|
||||
gather_node(
|
||||
interface_operator_function.generics(),
|
||||
interface_operator_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_operator_function.parameters(),
|
||||
interface_operator_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_operator_function.return_type(),
|
||||
interface_operator_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -809,7 +810,7 @@ fn gather_interface_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,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -852,25 +853,25 @@ fn gather_interface_default_operator_function<'a>(
|
||||
.name()
|
||||
));
|
||||
gather_node(
|
||||
interface_default_operator_function.generics(),
|
||||
interface_default_operator_function.generics_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_operator_function.parameters(),
|
||||
interface_default_operator_function.parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_operator_function.return_type(),
|
||||
interface_default_operator_function.return_type_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
gather_node(
|
||||
interface_default_operator_function.function_body(),
|
||||
interface_default_operator_function.function_body_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -879,7 +880,7 @@ fn gather_interface_default_operator_function<'a>(
|
||||
}
|
||||
|
||||
fn gather_function_body<'a>(
|
||||
function_body: &'a FunctionBody,
|
||||
function_body: &'a mut FunctionBody,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -890,7 +891,7 @@ fn gather_function_body<'a>(
|
||||
}
|
||||
|
||||
fn gather_member<'a>(
|
||||
member: &'a Member,
|
||||
member: &'a mut Member,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -911,11 +912,11 @@ fn gather_member<'a>(
|
||||
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>(
|
||||
variable_declaration: &'a VariableDeclaration,
|
||||
variable_declaration: &'a mut VariableDeclaration,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -937,26 +938,26 @@ fn gather_variable_declaration<'a>(
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
if let Some(expression) = variable_declaration.expression() {
|
||||
if let Some(expression) = variable_declaration.expression_mut() {
|
||||
gather_node(expression, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
fn gather_if_clause<'a>(
|
||||
if_clause: &'a IfClause,
|
||||
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(),
|
||||
if_clause.expression_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
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);
|
||||
}
|
||||
symbol_table.pop_scope();
|
||||
@ -964,20 +965,20 @@ fn gather_if_clause<'a>(
|
||||
}
|
||||
|
||||
fn gather_while_statement<'a>(
|
||||
while_statement: &'a WhileStatement,
|
||||
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(),
|
||||
while_statement.expression_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
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);
|
||||
}
|
||||
symbol_table.pop_scope();
|
||||
@ -985,13 +986,13 @@ fn gather_while_statement<'a>(
|
||||
}
|
||||
|
||||
fn gather_for_statement<'a>(
|
||||
for_statement: &'a ForStatement,
|
||||
for_statement: &'a mut ForStatement,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
gather_node(
|
||||
for_statement.expression(),
|
||||
for_statement.expression_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
@ -1015,7 +1016,7 @@ fn gather_for_statement<'a>(
|
||||
);
|
||||
}
|
||||
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);
|
||||
}
|
||||
symbol_table.pop_scope();
|
||||
@ -1043,7 +1044,7 @@ fn gather_variable_use<'a>(
|
||||
}
|
||||
|
||||
fn gather_ternary_expression<'a>(
|
||||
ternary_expression: &'a TernaryExpression,
|
||||
ternary_expression: &'a mut TernaryExpression,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -1054,20 +1055,20 @@ fn gather_ternary_expression<'a>(
|
||||
}
|
||||
|
||||
fn gather_closure<'a>(
|
||||
closure: &'a Closure,
|
||||
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(),
|
||||
closure.closure_parameters_mut(),
|
||||
symbol_table,
|
||||
fqn_context,
|
||||
diagnostics,
|
||||
);
|
||||
symbol_table.push_scope("ClosureStatementsScope");
|
||||
for statement in closure.statements() {
|
||||
for statement in closure.statements_mut() {
|
||||
gather_node(statement, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
symbol_table.pop_scope();
|
||||
@ -1075,7 +1076,7 @@ fn gather_closure<'a>(
|
||||
}
|
||||
|
||||
fn gather_closure_parameter<'a>(
|
||||
closure_parameter: &'a ClosureParameter,
|
||||
closure_parameter: &'a mut ClosureParameter,
|
||||
symbol_table: &mut SymbolTable,
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
@ -1096,7 +1097,7 @@ fn gather_closure_parameter<'a>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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::node::CompilationUnit;
|
||||
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 codespan_reporting::files::Files;
|
||||
use std::hash::Hash;
|
||||
@ -31,26 +31,24 @@ use std::hash::Hash;
|
||||
pub(self) mod fqn_context;
|
||||
mod gather;
|
||||
// mod resolve;
|
||||
mod first_pass;
|
||||
mod scope_table;
|
||||
mod second_pass;
|
||||
pub mod symbol;
|
||||
pub mod symbol_table;
|
||||
mod scope_table;
|
||||
mod util;
|
||||
|
||||
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,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> Vec<DmDiagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
// 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();
|
||||
gather_compilation_unit(
|
||||
compilation_unit,
|
||||
&file_name,
|
||||
symbol_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
np1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics);
|
||||
}
|
||||
|
||||
// resolve symbols
|
||||
|
||||
87
src/name_analysis/second_pass.rs
Normal file
87
src/name_analysis/second_pass.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,6 +377,20 @@ impl SymbolTable {
|
||||
}
|
||||
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 {
|
||||
|
||||
11
src/name_analysis/util.rs
Normal file
11
src/name_analysis/util.rs
Normal 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("::")
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user