Compare commits
No commits in common. "b5c0e44eeb41c0766f1c8b7110a712ae0930ad95" and "65136c3a1c6fa3153fab366e96c9699daa947cf9" have entirely different histories.
b5c0e44eeb
...
65136c3a1c
@ -1,5 +1,5 @@
|
||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
||||
use convert_case::{Case, Casing};
|
||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
@ -10,19 +10,20 @@ 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
|
||||
]
|
||||
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![]
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
#type_ident::#rule_ident(_) => vec![]
|
||||
},
|
||||
},
|
||||
None => {
|
||||
quote! {
|
||||
@ -32,35 +33,7 @@ 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>> {
|
||||
@ -69,19 +42,9 @@ 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,15 +10,9 @@ 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,15 +10,9 @@ 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,47 +1,63 @@
|
||||
mod enum_ast_node;
|
||||
mod leaf_enum_ast_node;
|
||||
mod leaf_struct_ast_node;
|
||||
mod polymorphic_enum_loop_ast_node;
|
||||
mod polymorphic_type_ast_node;
|
||||
mod struct_ast_node;
|
||||
mod leaf_struct_ast_node;
|
||||
mod polymorphic_type_ast_node;
|
||||
mod polymorphic_enum_loop_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,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
||||
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
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()))
|
||||
}
|
||||
@ -49,36 +65,40 @@ fn make_type_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
||||
BuildSpec::Production(_) => None,
|
||||
BuildSpec::NodeProduction(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
.map(|type_ident| {
|
||||
quote! {
|
||||
#type_ident(&'a #type_ident)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_ast_node_ref_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||
make_type_ident(build_spec).map(|type_ident| {
|
||||
quote! {
|
||||
AstNodeRef::#type_ident(inner) => *inner
|
||||
match build_spec {
|
||||
BuildSpec::Enum(enum_spec) => {
|
||||
Some(format_ident!("{}", enum_spec.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::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::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,17 +41,9 @@ 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,19 +16,6 @@ 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>> {
|
||||
@ -37,19 +24,9 @@ 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,27 +2,19 @@ use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChi
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
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()
|
||||
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.build());
|
||||
let child_adders = 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 = if is_mut {
|
||||
format_ident!("{}_mut", vec_child.name())
|
||||
} else {
|
||||
format_ident!("{}", vec_child.name())
|
||||
};
|
||||
let child_ident = format_ident!("{}", vec_child.name());
|
||||
let children_stream = quote! {
|
||||
for child in self.#child_ident() {
|
||||
children.push(child #as_clause);
|
||||
children.push(child as &dyn AstNode);
|
||||
}
|
||||
};
|
||||
Some(children_stream)
|
||||
@ -30,21 +22,16 @@ fn make_child_adders(spec: &StructSpec, is_mut: bool) -> Vec<TokenStream> {
|
||||
},
|
||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
||||
MemberChildBuild::Node(_) => {
|
||||
let child_ident = if is_mut {
|
||||
format_ident!("{}_mut", member_child.name())
|
||||
} else {
|
||||
format_ident!("{}", member_child.name())
|
||||
};
|
||||
|
||||
let child_ident = format_ident!("{}", member_child.name());
|
||||
if member_child.optional() {
|
||||
Some(quote! {
|
||||
if let Some(#child_ident) = self.#child_ident() {
|
||||
children.push(#child_ident #as_clause);
|
||||
children.push(#child_ident as &dyn AstNode);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Some(quote! {
|
||||
children.push(self.#child_ident() #as_clause)
|
||||
children.push(self.#child_ident() as &dyn AstNode)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -54,13 +41,7 @@ fn make_child_adders(spec: &StructSpec, is_mut: bool) -> Vec<TokenStream> {
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.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);
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
impl<'a> AstNode<'a> for #type_ident {
|
||||
@ -70,17 +51,9 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,22 +5,6 @@ use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_me
|
||||
use crate::spec::struct_spec::*;
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
fn deserialize_field(field_yaml: &Yaml) -> StructField {
|
||||
let (name, props) = unwrap_single_member_hash(field_yaml);
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let wrap = if let Some(wrap) = props["wrap"].as_str() {
|
||||
match wrap {
|
||||
"rc_ref_cell" => {
|
||||
Some(StructFieldWrap::RcRefCell)
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
StructField::new(&name, kind, wrap)
|
||||
}
|
||||
|
||||
fn deserialize_skip_child(props: &Yaml) -> StructChild {
|
||||
let rule = props["rule"].as_str().unwrap();
|
||||
StructChild::SkipChild(SkipChild::new(rule))
|
||||
@ -167,18 +151,6 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
} else {
|
||||
deserialize_error!("array", "children", name);
|
||||
};
|
||||
|
||||
let fields = if struct_yaml["fields"].is_array() {
|
||||
struct_yaml["fields"].as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|field| deserialize_field(field))
|
||||
.map(Box::new)
|
||||
.collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let derive = if struct_yaml["derive"].is_array() {
|
||||
struct_yaml["derive"].as_vec()
|
||||
.unwrap()
|
||||
@ -189,5 +161,5 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
vec![]
|
||||
};
|
||||
|
||||
StructSpec::new(name, children, fields, derive)
|
||||
StructSpec::new(name, children, derive)
|
||||
}
|
||||
|
||||
@ -6,10 +6,7 @@ mod spec;
|
||||
mod type_gen;
|
||||
mod walk;
|
||||
|
||||
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::ast_node::{make_ast_enum_member, make_ast_node_impl, 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;
|
||||
@ -114,9 +111,6 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
.collect::<Vec<_>>();
|
||||
let combined = quote! {
|
||||
use std::range::Range;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
|
||||
#(#types)*
|
||||
};
|
||||
@ -171,13 +165,6 @@ 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))
|
||||
@ -185,13 +172,6 @@ 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::*;
|
||||
|
||||
@ -207,26 +187,10 @@ 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)*
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
pub struct StructSpec {
|
||||
build: String,
|
||||
children: Vec<Box<StructChild>>,
|
||||
fields: Vec<Box<StructField>>,
|
||||
derive: Vec<String>,
|
||||
}
|
||||
|
||||
impl StructSpec {
|
||||
pub fn new(build: &str, children: Vec<Box<StructChild>>, fields: Vec<Box<StructField>>, derive: Vec<String>) -> Self {
|
||||
pub fn new(build: &str, children: Vec<Box<StructChild>>, derive: Vec<String>) -> Self {
|
||||
Self {
|
||||
build: build.to_string(),
|
||||
children,
|
||||
fields,
|
||||
derive,
|
||||
}
|
||||
}
|
||||
@ -25,10 +23,6 @@ impl StructSpec {
|
||||
self.children.iter().map(Box::as_ref)
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> impl Iterator<Item = &StructField> {
|
||||
self.fields.iter().map(Box::as_ref)
|
||||
}
|
||||
|
||||
pub fn derive(&self) -> &[String] {
|
||||
&self.derive
|
||||
}
|
||||
@ -272,37 +266,3 @@ pub enum SpecialChildKind {
|
||||
FileId,
|
||||
Range,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StructField {
|
||||
name: String,
|
||||
kind: String,
|
||||
wrap: Option<StructFieldWrap>,
|
||||
}
|
||||
|
||||
impl StructField {
|
||||
pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
kind: kind.to_string(),
|
||||
wrap,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &str {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn wrap(&self) -> Option<&StructFieldWrap> {
|
||||
self.wrap.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StructFieldWrap {
|
||||
RcRefCell
|
||||
}
|
||||
|
||||
@ -1,66 +1,10 @@
|
||||
use crate::spec::struct_spec::{
|
||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField,
|
||||
StructFieldWrap, StructSpec, VecChild, VecChildBuild,
|
||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
||||
VecChild, VecChildBuild,
|
||||
};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
fn make_field_accessors(field: &StructField) -> TokenStream {
|
||||
let field_ident = format_ident!("{}", field.name());
|
||||
let field_type = {
|
||||
let inner = format_ident!("{}", field.kind());
|
||||
if let Some(wrap) = field.wrap() {
|
||||
match wrap {
|
||||
StructFieldWrap::RcRefCell => {
|
||||
quote! { Rc<RefCell<#inner>> }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! { #inner }
|
||||
}
|
||||
};
|
||||
let set_field_ident = format_ident!("set_{}", field.name());
|
||||
let field_ident_mut = format_ident!("{}_mut", field.name());
|
||||
|
||||
quote! {
|
||||
pub fn #field_ident(&self) -> Option<&#field_type> {
|
||||
self.#field_ident.as_ref()
|
||||
}
|
||||
|
||||
pub fn #field_ident_mut(&mut self) -> Option<&mut #field_type> {
|
||||
self.#field_ident.as_mut()
|
||||
}
|
||||
|
||||
pub fn #set_field_ident(&mut self, #field_ident: #field_type) {
|
||||
self.#field_ident = Some(#field_ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_field_initializer(field: &StructField) -> TokenStream {
|
||||
let field_ident = format_ident!("{}", field.name());
|
||||
quote! { #field_ident: None }
|
||||
}
|
||||
|
||||
fn make_annotated_field(field: &StructField) -> TokenStream {
|
||||
let field_ident = format_ident!("{}", field.name());
|
||||
let field_type = if let Some(wrap) = field.wrap() {
|
||||
match wrap {
|
||||
StructFieldWrap::RcRefCell => {
|
||||
let inner = format_ident!("{}", field.kind());
|
||||
quote! { Rc<RefCell<#inner>> }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let inner = format_ident!("{}", field.kind());
|
||||
quote! { #inner }
|
||||
};
|
||||
|
||||
quote! {
|
||||
#field_ident: Option<#field_type>
|
||||
}
|
||||
}
|
||||
|
||||
fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream {
|
||||
let child_ident = format_ident!("{}", vec_child.name());
|
||||
match vec_child.build() {
|
||||
@ -240,18 +184,13 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
||||
|
||||
pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", build_spec.build());
|
||||
let annotated_children_members = build_spec
|
||||
let annotated_members = build_spec
|
||||
.children()
|
||||
.map(|child| make_annotated_member(child))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let annotated_fields = build_spec
|
||||
.fields()
|
||||
.map(|field| make_annotated_field(field))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let member_names = build_spec
|
||||
.children()
|
||||
.map(|child| make_member_ident(child))
|
||||
@ -259,28 +198,17 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let field_initializers = build_spec
|
||||
.fields()
|
||||
.map(|field| make_field_initializer(field))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let child_accessors = build_spec
|
||||
let accessors = build_spec
|
||||
.children()
|
||||
.map(|child| make_accessors(child))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let field_accessors = build_spec
|
||||
.fields()
|
||||
.map(|field| make_field_accessors(field))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let struct_stream = {
|
||||
let base = quote! {
|
||||
pub struct #type_ident {
|
||||
#(#annotated_children_members,)*
|
||||
#(#annotated_fields,)*
|
||||
#(#annotated_members),*
|
||||
}
|
||||
};
|
||||
if !build_spec.derive().is_empty() {
|
||||
@ -303,15 +231,13 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||
#struct_stream
|
||||
|
||||
impl #type_ident {
|
||||
pub fn new(#(#annotated_children_members),*) -> Self {
|
||||
pub fn new(#(#annotated_members),*) -> Self {
|
||||
Self {
|
||||
#(#member_names,)*
|
||||
#(#field_initializers,)*
|
||||
#(#member_names),*
|
||||
}
|
||||
}
|
||||
|
||||
#(#child_accessors)*
|
||||
#(#field_accessors)*
|
||||
#(#accessors)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Err
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
|
||||
|
||||
let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table);
|
||||
let diagnostics = analyze_names(&compilation_units, &files, &mut symbol_table);
|
||||
if diagnostics.is_empty() {
|
||||
println!("Name analysis complete.");
|
||||
println!("{}", symbol_table);
|
||||
|
||||
@ -1,178 +0,0 @@
|
||||
use std::cell::RefCell;
|
||||
use crate::ast::node::{CompilationUnit, Identifier, 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, UseSymbol};
|
||||
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;
|
||||
use std::rc::Rc;
|
||||
|
||||
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 nap1_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() {
|
||||
nap1_use_statement(use_statement, symbol_table, diagnostics);
|
||||
}
|
||||
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
|
||||
fn handle_concrete_use_statement(
|
||||
use_statement: &mut UseStatement,
|
||||
identifier: &Identifier,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let base_fqn = use_statement_base_fqn(use_statement);
|
||||
let to_insert = ConcreteUseSymbol::new(
|
||||
&base_fqn,
|
||||
identifier.name(),
|
||||
Some(SourceDefinition::from_identifier(identifier))
|
||||
);
|
||||
match symbol_table.insert_concrete_use_symbol(to_insert) {
|
||||
Ok(inserted) => {
|
||||
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(inserted))));
|
||||
}
|
||||
Err(insert_error) => {
|
||||
handle_insert_error(
|
||||
insert_error,
|
||||
identifier.name(),
|
||||
identifier.file_id(),
|
||||
identifier.range(),
|
||||
"Use Symbol",
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn nap1_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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -23,37 +23,43 @@ 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::first_pass::nap1_compilation_unit;
|
||||
use crate::name_analysis::second_pass::nap2_compilation_unit;
|
||||
use crate::name_analysis::gather::gather_compilation_unit;
|
||||
use crate::name_analysis::symbol_table::SymbolTable;
|
||||
use codespan_reporting::files::Files;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use crate::name_analysis::scope_table::ScopeTable;
|
||||
|
||||
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 util;
|
||||
mod scope_table;
|
||||
|
||||
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
|
||||
compilation_units: &mut Vec<Box<CompilationUnit>>,
|
||||
compilation_units: &[Box<CompilationUnit>],
|
||||
files: &'a F,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> Vec<DmDiagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
let mut scope_table = ScopeTable::new();
|
||||
|
||||
// gather symbols
|
||||
for compilation_unit in compilation_units.iter_mut() {
|
||||
for compilation_unit in compilation_units {
|
||||
let file_name = files.name(compilation_unit.file_id()).unwrap();
|
||||
nap1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics);
|
||||
gather_compilation_unit(
|
||||
compilation_unit,
|
||||
&file_name,
|
||||
symbol_table,
|
||||
&mut scope_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
|
||||
// resolve symbols
|
||||
for compilation_unit in compilation_units {
|
||||
nap2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||
// resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||
}
|
||||
|
||||
diagnostics.into()
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
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());
|
||||
match symbol_table.resolve_concrete_usable_by_fqn(&fqn) {
|
||||
Ok(resolved_symbol) => match *use_statement.use_symbol().unwrap().borrow() {
|
||||
UseSymbol::Concrete(ref concrete_use_symbol) => {
|
||||
concrete_use_symbol
|
||||
.borrow_mut()
|
||||
.set_resolved_symbol(resolved_symbol);
|
||||
}
|
||||
_ => panic!("Unexpected symbol type"),
|
||||
},
|
||||
Err(lookup_error) => {
|
||||
handle_lookup_error(
|
||||
lookup_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,30 +4,26 @@ pub(crate) mod module_symbol;
|
||||
pub(crate) mod parameter_symbol;
|
||||
pub(crate) mod source_definition;
|
||||
pub(crate) mod type_symbol;
|
||||
pub(crate) mod usable_symbol;
|
||||
pub(crate) mod use_symbol;
|
||||
pub(crate) mod variable_symbol;
|
||||
|
||||
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||
use class_member_symbol::ClassMemberSymbol;
|
||||
use function_symbol::FunctionSymbol;
|
||||
use module_symbol::ModuleSymbol;
|
||||
use parameter_symbol::ParameterSymbol;
|
||||
use source_definition::SourceDefinition;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use type_symbol::TypeSymbol;
|
||||
use variable_symbol::VariableSymbol;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Symbol {
|
||||
Use(UseSymbol),
|
||||
ConcreteUse(ConcreteUseSymbol),
|
||||
StarUse(StarUseSymbol),
|
||||
Module(ModuleSymbol),
|
||||
Type(TypeSymbol),
|
||||
ConcreteType(Rc<RefCell<ConcreteTypeSymbol>>),
|
||||
Function(FunctionSymbol),
|
||||
Parameter(ParameterSymbol),
|
||||
Variable(VariableSymbol),
|
||||
@ -35,18 +31,16 @@ pub enum Symbol {
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
pub fn definition(&self) -> Option<SourceDefinition> {
|
||||
pub fn definition(&self) -> Option<&SourceDefinition> {
|
||||
match self {
|
||||
Symbol::Use(use_symbol) => use_symbol.source_definition(),
|
||||
Symbol::Module(module) => module.source_definition().cloned(),
|
||||
Symbol::Type(type_symbol) => type_symbol.source_definition().cloned(),
|
||||
Symbol::ConcreteType(concrete_type_symbol) => concrete_type_symbol.borrow().source_definition().cloned(),
|
||||
Symbol::Function(function_symbol) => function_symbol.source_definition().cloned(),
|
||||
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(),
|
||||
Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(),
|
||||
Symbol::ClassMember(class_member_symbol) => {
|
||||
class_member_symbol.source_definition().cloned()
|
||||
}
|
||||
Symbol::ConcreteUse(concrete) => concrete.source_definition(),
|
||||
Symbol::StarUse(star) => star.source_definition(),
|
||||
Symbol::Module(module) => module.source_definition(),
|
||||
Symbol::Type(type_symbol) => type_symbol.source_definition(),
|
||||
Symbol::Function(function_symbol) => function_symbol.source_definition(),
|
||||
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(),
|
||||
Symbol::Variable(variable_symbol) => variable_symbol.source_definition(),
|
||||
Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_definition(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ConcreteUsableSymbol {
|
||||
Type(Rc<RefCell<ConcreteTypeSymbol>>),
|
||||
Function(Rc<RefCell<FunctionSymbol>>),
|
||||
}
|
||||
@ -1,30 +1,11 @@
|
||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UseSymbol {
|
||||
Concrete(Rc<RefCell<ConcreteUseSymbol>>),
|
||||
Star(StarUseSymbol),
|
||||
}
|
||||
|
||||
impl UseSymbol {
|
||||
pub fn source_definition(&self) -> Option<SourceDefinition> {
|
||||
match self {
|
||||
UseSymbol::Concrete(concrete) => concrete.borrow().source_definition().cloned(),
|
||||
UseSymbol::Star(star) => star.source_definition().cloned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConcreteUseSymbol {
|
||||
base_fqn: String,
|
||||
declared_name: String,
|
||||
source_definition: Option<SourceDefinition>,
|
||||
resolved_symbol: Option<ConcreteUsableSymbol>,
|
||||
}
|
||||
|
||||
impl ConcreteUseSymbol {
|
||||
@ -37,7 +18,6 @@ impl ConcreteUseSymbol {
|
||||
base_fqn: base_fqn.to_string(),
|
||||
declared_name: declared_name.to_string(),
|
||||
source_definition,
|
||||
resolved_symbol: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,14 +32,6 @@ impl ConcreteUseSymbol {
|
||||
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||
self.source_definition.as_ref()
|
||||
}
|
||||
|
||||
pub fn resolved_symbol(&self) -> Option<&ConcreteUsableSymbol> {
|
||||
self.resolved_symbol.as_ref()
|
||||
}
|
||||
|
||||
pub fn set_resolved_symbol(&mut self, symbol: ConcreteUsableSymbol) {
|
||||
self.resolved_symbol = Some(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ConcreteUseSymbol {
|
||||
|
||||
@ -2,19 +2,15 @@ use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
|
||||
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol};
|
||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||
use crate::name_analysis::symbol::*;
|
||||
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
||||
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
||||
use scope::Scope;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod scope;
|
||||
|
||||
@ -48,14 +44,13 @@ impl SymbolTable {
|
||||
}
|
||||
|
||||
pub fn push_scope(&mut self, debug_name: &str) {
|
||||
let id_to_push = self.scopes.len();
|
||||
let id = self.scopes.len();
|
||||
self.scopes.push(Scope::new(
|
||||
Some(self.current_scope_id),
|
||||
id_to_push,
|
||||
id,
|
||||
debug_name.to_string(),
|
||||
));
|
||||
self.current_scope_mut().add_child(id_to_push);
|
||||
self.current_scope_id = id_to_push;
|
||||
self.current_scope_id = id;
|
||||
}
|
||||
|
||||
pub fn pop_scope(&mut self) {
|
||||
@ -75,17 +70,20 @@ impl SymbolTable {
|
||||
fn find_current_scope_concrete_use_symbol(
|
||||
&self,
|
||||
declared_name: &str,
|
||||
) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
) -> Option<&ConcreteUseSymbol> {
|
||||
self.current_scope()
|
||||
.concrete_use_symbols()
|
||||
.get(declared_name)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> {
|
||||
self.current_scope().star_use_symbols().get(base_fqn)
|
||||
}
|
||||
|
||||
fn find_current_scope_type_symbol(&self, declared_name: &str) -> Option<&TypeSymbol> {
|
||||
self.current_scope().type_symbols().get(declared_name)
|
||||
}
|
||||
|
||||
fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> {
|
||||
self.current_scope().module_symbols().get(declared_name)
|
||||
}
|
||||
@ -121,13 +119,11 @@ impl SymbolTable {
|
||||
|
||||
fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option<Symbol> {
|
||||
self.find_current_scope_concrete_use_symbol(declared_name)
|
||||
.map(|concrete_use_symbol| {
|
||||
Symbol::Use(UseSymbol::Concrete(concrete_use_symbol.clone()))
|
||||
.map(|concrete_use_symbol| Symbol::ConcreteUse(concrete_use_symbol.clone()))
|
||||
.or_else(|| {
|
||||
self.find_current_scope_type_symbol(declared_name)
|
||||
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
})
|
||||
// .or_else(|| {
|
||||
// self.find_current_scope_type_symbol(declared_name)
|
||||
// .map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
// })
|
||||
.or_else(|| {
|
||||
self.find_current_scope_module_symbol(declared_name)
|
||||
.map(|module_symbol| Symbol::Module(module_symbol.clone()))
|
||||
@ -137,22 +133,17 @@ impl SymbolTable {
|
||||
pub fn insert_concrete_use_symbol(
|
||||
&mut self,
|
||||
concrete_use_symbol: ConcreteUseSymbol,
|
||||
) -> Result<Rc<RefCell<ConcreteUseSymbol>>, SymbolInsertError> {
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
let name = concrete_use_symbol.declared_name().to_string();
|
||||
self.current_scope_mut()
|
||||
.concrete_use_symbols_mut()
|
||||
.insert(name.clone(), Rc::new(RefCell::new(concrete_use_symbol)));
|
||||
Ok(self
|
||||
.current_scope()
|
||||
.concrete_use_symbols()
|
||||
.get(&name)
|
||||
.cloned()
|
||||
.unwrap())
|
||||
self.current_scope_mut().concrete_use_symbols_mut().insert(
|
||||
concrete_use_symbol.declared_name().to_string(),
|
||||
concrete_use_symbol,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,9 +154,9 @@ impl SymbolTable {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(Symbol::Use(UseSymbol::Star(
|
||||
Err(SymbolAlreadyDefined(Symbol::StarUse(
|
||||
defined_symbol.clone(),
|
||||
))))
|
||||
)))
|
||||
} else {
|
||||
self.current_scope_mut()
|
||||
.star_use_symbols_mut()
|
||||
@ -190,23 +181,15 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_current_scope_concrete_type_symbol(
|
||||
&self,
|
||||
declared_name: &str,
|
||||
) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> {
|
||||
self.current_scope().get_concrete_type_symbol(declared_name)
|
||||
}
|
||||
|
||||
pub fn insert_concrete_type_symbol(
|
||||
&mut self,
|
||||
symbol: ConcreteTypeSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_type) =
|
||||
self.find_current_scope_concrete_type_symbol(symbol.declared_name())
|
||||
pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_usable_symbol(type_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(Symbol::ConcreteType(defined_type)))
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
self.current_scope_mut().insert_concrete_type_symbol(symbol);
|
||||
self.current_scope_mut()
|
||||
.type_symbols_mut()
|
||||
.insert(type_symbol.declared_name().to_string(), type_symbol);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -281,6 +264,66 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_type_in_scope_by_declared_name<'a>(
|
||||
scope: &'a Scope,
|
||||
declared_name: &str,
|
||||
) -> Option<&'a TypeSymbol> {
|
||||
scope.type_symbols().get(declared_name)
|
||||
}
|
||||
|
||||
pub fn lookup_type_by_declared_name(
|
||||
&self,
|
||||
declared_name: &str,
|
||||
scope_id: usize,
|
||||
) -> Result<&TypeSymbol, SymbolLookupError> {
|
||||
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||
while let Some(scope) = scope_opt {
|
||||
if let Some(symbol) = Self::lookup_type_in_scope_by_declared_name(scope, declared_name)
|
||||
{
|
||||
return Ok(symbol);
|
||||
}
|
||||
scope_opt = if let Some(parent_id) = scope.parent() {
|
||||
Some(&self.scopes[parent_id])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
fn lookup_type_in_scope_by_fqn<'a>(scope: &'a Scope, fqn: &str) -> Option<&'a TypeSymbol> {
|
||||
for type_symbol in scope.type_symbols().values() {
|
||||
match type_symbol {
|
||||
TypeSymbol::Concrete(concrete_type_symbol) => {
|
||||
if concrete_type_symbol.fqn() == fqn {
|
||||
return Some(type_symbol);
|
||||
}
|
||||
}
|
||||
TypeSymbol::Generic(_) => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn lookup_type_by_fqn(
|
||||
&self,
|
||||
fqn: &str,
|
||||
scope_id: usize,
|
||||
) -> Result<&TypeSymbol, SymbolLookupError> {
|
||||
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||
while let Some(scope) = scope_opt {
|
||||
if let Some(type_symbol) = Self::lookup_type_in_scope_by_fqn(scope, fqn) {
|
||||
return Ok(type_symbol);
|
||||
}
|
||||
scope_opt = if let Some(parent_id) = scope.parent() {
|
||||
Some(&self.scopes[parent_id])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
fn lookup_addressable_in_scope_by_identifier(
|
||||
scope: &Scope,
|
||||
identifier: &str,
|
||||
@ -307,12 +350,12 @@ impl SymbolTable {
|
||||
.get(identifier)
|
||||
.map(|function_symbol| Symbol::Function(function_symbol.clone()))
|
||||
})
|
||||
// .or_else(|| {
|
||||
// scope
|
||||
// .type_symbols()
|
||||
// .get(identifier)
|
||||
// .map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
// })
|
||||
.or_else(|| {
|
||||
scope
|
||||
.type_symbols()
|
||||
.get(identifier)
|
||||
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lookup_addressable_by_identifier(
|
||||
@ -334,39 +377,6 @@ impl SymbolTable {
|
||||
}
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
pub fn resolve_concrete_usable_by_fqn(
|
||||
&self,
|
||||
fqn: &str,
|
||||
) -> Result<ConcreteUsableSymbol, SymbolLookupError> {
|
||||
// breadth-first search, use a queue
|
||||
let mut search_stack: VecDeque<usize> = VecDeque::new();
|
||||
search_stack.push_back(0); // global scope
|
||||
|
||||
while let Some(scope_id) = search_stack.pop_front() {
|
||||
let scope = &self.scopes[scope_id];
|
||||
for child_id in scope.children() {
|
||||
search_stack.push_back(child_id);
|
||||
}
|
||||
|
||||
if let Some(concrete_type_symbol) = scope.get_concrete_type_symbol_by_fqn(fqn) {
|
||||
return Ok(ConcreteUsableSymbol::Type(concrete_type_symbol));
|
||||
}
|
||||
|
||||
// TODO: this is inefficient. Use a (cached) hash table of Fqn => Rc<RefCell<symbol>>
|
||||
for function_symbol in scope.function_symbols().values() {
|
||||
if function_symbol.fqn() == fqn {
|
||||
return Ok(ConcreteUsableSymbol::Function(todo!()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
pub fn resolve_usable_star(&self, base_fqn: &str) -> Result<(), SymbolLookupError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SymbolTable {
|
||||
|
||||
@ -2,24 +2,20 @@ use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
|
||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol};
|
||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scope {
|
||||
parent: Option<usize>,
|
||||
id: usize,
|
||||
children: Vec<usize>,
|
||||
concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>,
|
||||
concrete_use_symbols: HashMap<String, ConcreteUseSymbol>,
|
||||
star_use_symbols: HashMap<String, StarUseSymbol>,
|
||||
module_symbols: HashMap<String, ModuleSymbol>,
|
||||
concrete_type_symbols: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>,
|
||||
concrete_type_symbols_by_fqn: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>,
|
||||
type_symbols: HashMap<String, TypeSymbol>,
|
||||
function_symbols: HashMap<String, FunctionSymbol>,
|
||||
parameter_symbols: HashMap<String, ParameterSymbol>,
|
||||
variable_symbols: HashMap<String, VariableSymbol>,
|
||||
@ -32,12 +28,10 @@ impl Scope {
|
||||
Self {
|
||||
parent,
|
||||
id,
|
||||
children: vec![],
|
||||
concrete_use_symbols: HashMap::new(),
|
||||
star_use_symbols: HashMap::new(),
|
||||
module_symbols: HashMap::new(),
|
||||
concrete_type_symbols: HashMap::new(),
|
||||
concrete_type_symbols_by_fqn: HashMap::new(),
|
||||
type_symbols: HashMap::new(),
|
||||
function_symbols: HashMap::new(),
|
||||
parameter_symbols: HashMap::new(),
|
||||
variable_symbols: HashMap::new(),
|
||||
@ -54,21 +48,11 @@ impl Scope {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, child_id: usize) {
|
||||
self.children.push(child_id);
|
||||
}
|
||||
|
||||
pub fn children(&self) -> Vec<usize> {
|
||||
self.children.clone()
|
||||
}
|
||||
|
||||
pub fn concrete_use_symbols(&self) -> &HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
pub fn concrete_use_symbols(&self) -> &HashMap<String, ConcreteUseSymbol> {
|
||||
&self.concrete_use_symbols
|
||||
}
|
||||
|
||||
pub fn concrete_use_symbols_mut(
|
||||
&mut self,
|
||||
) -> &mut HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
pub fn concrete_use_symbols_mut(&mut self) -> &mut HashMap<String, ConcreteUseSymbol> {
|
||||
&mut self.concrete_use_symbols
|
||||
}
|
||||
|
||||
@ -88,24 +72,12 @@ impl Scope {
|
||||
&mut self.module_symbols
|
||||
}
|
||||
|
||||
pub fn insert_concrete_type_symbol(&mut self, symbol: ConcreteTypeSymbol) {
|
||||
let as_rc = Rc::new(RefCell::new(symbol));
|
||||
self.concrete_type_symbols.insert(
|
||||
as_rc.borrow().declared_name().to_string(),
|
||||
as_rc.clone(),
|
||||
);
|
||||
self.concrete_type_symbols_by_fqn.insert(
|
||||
as_rc.borrow().fqn().to_string(),
|
||||
as_rc.clone(),
|
||||
);
|
||||
pub fn type_symbols(&self) -> &HashMap<String, TypeSymbol> {
|
||||
&self.type_symbols
|
||||
}
|
||||
|
||||
pub fn get_concrete_type_symbol(&self, declared_name: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> {
|
||||
self.concrete_type_symbols.get(declared_name).cloned()
|
||||
}
|
||||
|
||||
pub fn get_concrete_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> {
|
||||
self.concrete_type_symbols_by_fqn.get(fqn).cloned()
|
||||
|
||||
pub fn type_symbols_mut(&mut self) -> &mut HashMap<String, TypeSymbol> {
|
||||
&mut self.type_symbols
|
||||
}
|
||||
|
||||
pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> {
|
||||
@ -159,15 +131,13 @@ impl Display for Scope {
|
||||
f,
|
||||
"----Scope {} (p: {}) {}----",
|
||||
self.id(),
|
||||
self.parent()
|
||||
.map(|parent_id| format!("{}", parent_id))
|
||||
.unwrap_or_else(|| "None".to_string()),
|
||||
self.parent().map(|parent_id| format!("{}", parent_id)).unwrap_or_else(|| "None".to_string()),
|
||||
self.debug_name()
|
||||
)?;
|
||||
write_symbols!(f, self.concrete_use_symbols());
|
||||
write_symbols!(f, self.star_use_symbols());
|
||||
write_symbols!(f, self.module_symbols());
|
||||
todo!("self.concrete_type_symbols");
|
||||
write_symbols!(f, self.type_symbols());
|
||||
write_symbols!(f, self.function_symbols());
|
||||
write_symbols!(f, self.parameter_symbols());
|
||||
write_symbols!(f, self.variable_symbols());
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
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("::")
|
||||
}
|
||||
@ -248,10 +248,6 @@ UseStatement:
|
||||
- range:
|
||||
special:
|
||||
kind: range
|
||||
fields:
|
||||
- use_symbol:
|
||||
kind: UseSymbol
|
||||
wrap: rc_ref_cell
|
||||
UseStatementPrefix:
|
||||
struct:
|
||||
children:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user