Compare commits
3 Commits
d5ac6dfc2d
...
eda25307b0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eda25307b0 | ||
|
|
542d5f6c80 | ||
|
|
3ab59961dd |
@ -1,39 +1,50 @@
|
|||||||
|
use crate::spec::tree_enum_spec::{
|
||||||
|
EnumRuleChildKind, TreeEnumBuildSpec, TreeEnumRule,
|
||||||
|
};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_match_arm(rule: &TreeEnumRule, type_ident: &Ident, is_mut: bool) -> TokenStream {
|
||||||
|
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));
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#type_ident::#rule_ident(#child_ident) => vec![
|
||||||
|
#child_ident.#as_node_ref_ident()
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => quote! {
|
||||||
|
#type_ident::#rule_ident(_) => vec![]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
quote! {
|
||||||
|
#type_ident::#rule_ident => vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", enum_spec.build());
|
let type_ident = format_ident!("{}", enum_spec.build());
|
||||||
let match_arms = enum_spec
|
let match_arms = enum_spec
|
||||||
.rules()
|
.rules()
|
||||||
.map(|rule| {
|
.map(|rule| make_match_arm(rule, &type_ident, false))
|
||||||
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.as_node_ref()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => quote! {
|
|
||||||
#type_ident::#rule_ident(_) => vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
quote! {
|
|
||||||
#type_ident::#rule_ident => vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
let match_arms_mut = enum_spec
|
||||||
|
.rules()
|
||||||
|
.map(|rule| make_match_arm(rule, &type_ident, true))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl AstNode for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
@ -42,9 +53,19 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
match self {
|
||||||
|
#(#match_arms_mut,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
|
|
||||||
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
@ -9,10 +9,18 @@ pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
|||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,18 @@ pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream
|
|||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,63 +1,47 @@
|
|||||||
mod enum_ast_node;
|
mod enum_ast_node;
|
||||||
mod leaf_enum_ast_node;
|
mod leaf_enum_ast_node;
|
||||||
mod struct_ast_node;
|
|
||||||
mod leaf_struct_ast_node;
|
mod leaf_struct_ast_node;
|
||||||
mod polymorphic_type_ast_node;
|
|
||||||
mod polymorphic_enum_loop_ast_node;
|
mod polymorphic_enum_loop_ast_node;
|
||||||
|
mod polymorphic_type_ast_node;
|
||||||
|
mod struct_ast_node;
|
||||||
|
|
||||||
use crate::spec::BuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
||||||
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
||||||
|
use crate::spec::BuildSpec;
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Enum(enum_spec) => {
|
BuildSpec::Enum(enum_spec) => Some(make_enum_ast_node_impl(enum_spec)),
|
||||||
Some(make_enum_ast_node_impl(enum_spec))
|
BuildSpec::LeafEnum(leaf_enum) => Some(make_leaf_enum_ast_node_impl(leaf_enum)),
|
||||||
}
|
BuildSpec::Struct(struct_spec) => Some(make_struct_ast_node_impl(struct_spec)),
|
||||||
BuildSpec::LeafEnum(leaf_enum) => {
|
BuildSpec::LeafStruct(leaf_struct) => Some(make_leaf_struct_ast_node_impl(leaf_struct)),
|
||||||
Some(make_leaf_enum_ast_node_impl(leaf_enum))
|
|
||||||
}
|
|
||||||
BuildSpec::Struct(struct_spec) => {
|
|
||||||
Some(make_struct_ast_node_impl(struct_spec))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafStruct(leaf_struct) => {
|
|
||||||
Some(make_leaf_struct_ast_node_impl(leaf_struct))
|
|
||||||
}
|
|
||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
BuildSpec::NodeProduction(_) => None,
|
BuildSpec::NodeProduction(_) => None,
|
||||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||||
Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
|
Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some(
|
||||||
Some(make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop))
|
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
||||||
}
|
),
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
fn make_ast_enum_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Struct(struct_spec) => {
|
BuildSpec::Struct(struct_spec) => Some(format_ident!("{}", struct_spec.build())),
|
||||||
Some(format_ident!("{}", struct_spec.build()))
|
BuildSpec::LeafStruct(leaf_struct) => Some(format_ident!("{}", leaf_struct.build())),
|
||||||
}
|
BuildSpec::Enum(enum_spec) => Some(format_ident!("{}", enum_spec.build())),
|
||||||
BuildSpec::LeafStruct(leaf_struct) => {
|
BuildSpec::LeafEnum(leaf_enum) => Some(format_ident!("{}", leaf_enum.build())),
|
||||||
Some(format_ident!("{}", leaf_struct.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::Enum(enum_spec) => {
|
|
||||||
Some(format_ident!("{}", enum_spec.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafEnum(leaf_enum) => {
|
|
||||||
Some(format_ident!("{}", leaf_enum.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||||
Some(format_ident!("{}", polymorphic_type.name()))
|
Some(format_ident!("{}", polymorphic_type.name()))
|
||||||
},
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||||
Some(format_ident!("{}", polymorphic_enum_loop.name()))
|
Some(format_ident!("{}", polymorphic_enum_loop.name()))
|
||||||
}
|
}
|
||||||
@ -65,9 +49,20 @@ pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
BuildSpec::NodeProduction(_) => None,
|
BuildSpec::NodeProduction(_) => None,
|
||||||
}
|
}
|
||||||
.map(|type_ident| {
|
}
|
||||||
quote! {
|
|
||||||
#type_ident(&'a #type_ident)
|
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
}
|
make_ast_enum_ident(build_spec).map(|type_ident| {
|
||||||
})
|
quote! {
|
||||||
}
|
#type_ident(&'a #type_ident)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_ast_enum_member_mut(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
|
make_ast_enum_ident(build_spec).map(|type_ident| {
|
||||||
|
quote! {
|
||||||
|
#type_ident(&'a mut #type_ident)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,33 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_child_adder(child: &PolymorphicEnumLoopRuleBuildChild, is_mut: bool) -> TokenStream {
|
||||||
|
let child_ident = {
|
||||||
|
let base = match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
|
format_ident!("{}", use_current.name())
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
|
format_ident!("{}", on_each.name())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if is_mut {
|
||||||
|
format_ident!("{}_mut", base)
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
children.push(self.#child_ident().#as_node_ref_ident());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_loop_ast_node_impl(
|
pub fn make_polymorphic_enum_loop_ast_node_impl(
|
||||||
spec: &PolymorphicEnumLoopBuildSpec,
|
spec: &PolymorphicEnumLoopBuildSpec,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
@ -18,19 +45,12 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let child_adders = build_rule
|
let child_adders = build_rule
|
||||||
.children()
|
.children()
|
||||||
.map(|child| {
|
.map(|child| make_child_adder(child, false))
|
||||||
let child_ident = match child {
|
.collect::<Vec<_>>();
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
|
||||||
format_ident!("{}", use_current.name())
|
let child_adders_mut = build_rule
|
||||||
}
|
.children()
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
.map(|child| make_child_adder(child, true))
|
||||||
format_ident!("{}", on_each.name())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
children.push(self.#child_ident().as_node_ref())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@ -41,9 +61,19 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
let mut children: Vec<AstNodeRefMut> = vec![];
|
||||||
|
#(#child_adders_mut;)*
|
||||||
|
children
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,36 @@
|
|||||||
use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
use crate::spec::polymorphic_type_spec::{PolymorphicTypeBuildSpec, PolymorphicTypeVariant};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_match_arm(
|
||||||
|
variant: &PolymorphicTypeVariant,
|
||||||
|
type_ident: &Ident,
|
||||||
|
is_mut: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
let variant_ident = format_ident!("{}", variant.name());
|
||||||
|
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#type_ident::#variant_ident(#child_ident) => vec![#child_ident.#as_node_ref_ident()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
let match_arms = spec
|
let match_arms = spec
|
||||||
.variants()
|
.variants()
|
||||||
.map(|variant| {
|
.map(|variant| make_match_arm(variant, &type_ident, false))
|
||||||
let variant_ident = format_ident!("{}", variant.name());
|
.collect::<Vec<_>>();
|
||||||
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
|
||||||
quote! {
|
let match_arms_mut = spec
|
||||||
#type_ident::#variant_ident(#child_ident) => vec![#child_ident.as_node_ref()]
|
.variants()
|
||||||
}
|
.map(|variant| make_match_arm(variant, &type_ident, true))
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@ -24,9 +41,19 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
match self {
|
||||||
|
#(#match_arms_mut,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,43 +2,69 @@ use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChi
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_child_adder(child: &StructChild, is_mut: bool) -> Option<TokenStream> {
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
format_ident!("as_node_ref_mut")
|
||||||
|
} else {
|
||||||
|
format_ident!("as_node_ref")
|
||||||
|
};
|
||||||
|
|
||||||
|
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 children_stream = quote! {
|
||||||
|
for child in self.#child_ident().map(AstNode::#as_node_ref_ident) {
|
||||||
|
children.push(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(children_stream)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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())
|
||||||
|
};
|
||||||
|
if member_child.optional() {
|
||||||
|
Some(quote! {
|
||||||
|
if let Some(#child_ident) = self.#child_ident() {
|
||||||
|
children.push(#child_ident.#as_node_ref_ident());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
children.push(self.#child_ident().#as_node_ref_ident());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MemberChildBuild::Boolean(_) => None,
|
||||||
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
let child_adders = spec
|
let child_adders = spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| match child {
|
.map(|child| make_child_adder(child, false))
|
||||||
StructChild::SkipChild(_) => None,
|
.filter(Option::is_some)
|
||||||
StructChild::VecChild(vec_child) => match vec_child.build() {
|
.map(Option::unwrap)
|
||||||
VecChildBuild::String(_) => None,
|
.collect::<Vec<_>>();
|
||||||
VecChildBuild::Node(_) => {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
let child_adders_mut = spec
|
||||||
let children_stream = quote! {
|
.children()
|
||||||
for child in self.#child_ident().map(AstNode::as_node_ref) {
|
.map(|child| make_child_adder(child, true))
|
||||||
children.push(child);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(children_stream)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
|
||||||
MemberChildBuild::Node(_) => {
|
|
||||||
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_node_ref());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
children.push(self.#child_ident().as_node_ref())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MemberChildBuild::Boolean(_) => None,
|
|
||||||
},
|
|
||||||
StructChild::Special(_) => None,
|
|
||||||
})
|
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -51,9 +77,19 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
let mut children: Vec<AstNodeRefMut> = vec![];
|
||||||
|
#(#child_adders_mut;)*
|
||||||
|
children
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||||
use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, VecChild, VecChildBuild};
|
use crate::spec::struct_spec::{
|
||||||
|
MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
||||||
|
VecChild, VecChildBuild,
|
||||||
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
@ -118,14 +121,14 @@ fn make_boolean_member_child_match_action(name: &str) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
StructChild::SkipChild(skip_child) => {
|
StructChild::SkipChild(skip_child) => {
|
||||||
let rule_ident = format_ident!("{}", skip_child.rule());
|
let rule_ident = format_ident!("{}", skip_child.rule());
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
Rule::#rule_ident => {}
|
Rule::#rule_ident => {}
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
StructChild::VecChild(vec_child) => {
|
StructChild::VecChild(vec_child) => {
|
||||||
let rule_ident = format_ident!("{}", vec_child.rule());
|
let rule_ident = format_ident!("{}", vec_child.rule());
|
||||||
let action = make_vec_child_match_action(vec_child);
|
let action = make_vec_child_match_action(vec_child);
|
||||||
@ -133,28 +136,24 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
Rule::#rule_ident => { #action }
|
Rule::#rule_ident => { #action }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
StructChild::MemberChild(member_child) => {
|
StructChild::MemberChild(member_child) => match member_child.build() {
|
||||||
match member_child.build() {
|
MemberChildBuild::Node(node_member_build) => {
|
||||||
MemberChildBuild::Node(node_member_build) => {
|
let rule_ident = format_ident!("{}", member_child.rule());
|
||||||
let rule_ident = format_ident!("{}", member_child.rule());
|
let action =
|
||||||
let action = make_node_member_child_match_action(
|
make_node_member_child_match_action(member_child.name(), node_member_build);
|
||||||
member_child.name(),
|
Some(quote! {
|
||||||
node_member_build
|
Rule::#rule_ident => { #action }
|
||||||
);
|
})
|
||||||
Some(quote! {
|
}
|
||||||
Rule::#rule_ident => { #action }
|
MemberChildBuild::Boolean(_) => {
|
||||||
})
|
let rule_ident = format_ident!("{}", member_child.rule());
|
||||||
}
|
let action = make_boolean_member_child_match_action(member_child.name());
|
||||||
MemberChildBuild::Boolean(_) => {
|
Some(quote! {
|
||||||
let rule_ident = format_ident!("{}", member_child.rule());
|
Rule::#rule_ident => { #action }
|
||||||
let action = make_boolean_member_child_match_action(member_child.name());
|
})
|
||||||
Some(quote! {
|
|
||||||
Rule::#rule_ident => { #action }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StructChild::Special(_) => None
|
StructChild::Special(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +191,7 @@ fn make_special_child_arg(special_child: &SpecialChild) -> TokenStream {
|
|||||||
quote! { #child_ident }
|
quote! { #child_ident }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
fn make_child_arg(child_spec: &StructChild) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_arg(vec_child)),
|
StructChild::VecChild(vec_child) => Some(make_vec_child_arg(vec_child)),
|
||||||
@ -204,7 +203,7 @@ fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenS
|
|||||||
)),
|
)),
|
||||||
MemberChildBuild::Boolean(_) => {
|
MemberChildBuild::Boolean(_) => {
|
||||||
Some(make_boolean_member_child_arg(member_child.name()))
|
Some(make_boolean_member_child_arg(member_child.name()))
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
StructChild::Special(special_child) => Some(make_special_child_arg(special_child)),
|
StructChild::Special(special_child) => Some(make_special_child_arg(special_child)),
|
||||||
}
|
}
|
||||||
@ -214,7 +213,7 @@ fn make_return_value_stream(build_spec: &StructSpec, pair_ident: &Ident) -> Toke
|
|||||||
let type_ident = format_ident!("{}", build_spec.build());
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
let child_args = build_spec
|
let child_args = build_spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| make_child_arg(child, pair_ident))
|
.map(|child| make_child_arg(child))
|
||||||
.filter(|child_arg| child_arg.is_some())
|
.filter(|child_arg| child_arg.is_some())
|
||||||
.map(|child_arg| child_arg.unwrap())
|
.map(|child_arg| child_arg.unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -230,9 +229,9 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
let preamble = make_preamble(build_spec, &pair_ident);
|
let preamble = make_preamble(build_spec, &pair_ident);
|
||||||
|
|
||||||
let special_children = make_special_children(build_spec);
|
let special_children = make_special_children(build_spec);
|
||||||
|
|
||||||
let child_holders = build_spec
|
let child_holders = build_spec
|
||||||
@ -261,9 +260,9 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
quote! {
|
quote! {
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
#preamble
|
#preamble
|
||||||
|
|
||||||
#(#special_children;)*
|
#(#special_children;)*
|
||||||
|
|
||||||
#(#child_holders;)*
|
#(#child_holders;)*
|
||||||
|
|
||||||
#iter_stream
|
#iter_stream
|
||||||
|
|||||||
@ -5,6 +5,23 @@ use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_me
|
|||||||
use crate::spec::struct_spec::*;
|
use crate::spec::struct_spec::*;
|
||||||
use yaml_rust2::Yaml;
|
use yaml_rust2::Yaml;
|
||||||
|
|
||||||
|
fn deserialize_fields(fields: &Yaml) -> Vec<Box<StructField>> {
|
||||||
|
fields
|
||||||
|
.as_vec()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|field| unwrap_single_member_hash(field))
|
||||||
|
.map(|(name, props)| {
|
||||||
|
let kind = match props["kind"].as_str().unwrap() {
|
||||||
|
"usize" => StructFieldKind::USize,
|
||||||
|
_ => panic!()
|
||||||
|
};
|
||||||
|
StructField::new(&name, kind, get_as_bool(&props["optional"]))
|
||||||
|
})
|
||||||
|
.map(Box::new)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_skip_child(props: &Yaml) -> StructChild {
|
fn deserialize_skip_child(props: &Yaml) -> StructChild {
|
||||||
let rule = props["rule"].as_str().unwrap();
|
let rule = props["rule"].as_str().unwrap();
|
||||||
StructChild::SkipChild(SkipChild::new(rule))
|
StructChild::SkipChild(SkipChild::new(rule))
|
||||||
@ -96,8 +113,12 @@ fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild {
|
|||||||
match props["kind"].as_str().unwrap() {
|
match props["kind"].as_str().unwrap() {
|
||||||
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
|
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
|
||||||
"range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)),
|
"range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)),
|
||||||
_ => panic!("Invalid special child kind {} in {}", props["kind"].as_str().unwrap(), name),
|
_ => panic!(
|
||||||
}
|
"Invalid special child kind {} in {}",
|
||||||
|
props["kind"].as_str().unwrap(),
|
||||||
|
name
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
||||||
@ -108,7 +129,7 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
|||||||
} else if props["member"].is_hash() {
|
} else if props["member"].is_hash() {
|
||||||
deserialize_member_child(name, &props["member"])
|
deserialize_member_child(name, &props["member"])
|
||||||
} else if props["special"].is_hash() {
|
} else if props["special"].is_hash() {
|
||||||
deserialize_special_child(name, &props["special"])
|
deserialize_special_child(name, &props["special"])
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
||||||
}
|
}
|
||||||
@ -151,5 +172,11 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
|||||||
} else {
|
} else {
|
||||||
deserialize_error!("array", "children", name);
|
deserialize_error!("array", "children", name);
|
||||||
};
|
};
|
||||||
StructSpec::new(name, children)
|
let fields = if struct_yaml["fields"].is_array() {
|
||||||
|
deserialize_fields(&struct_yaml["fields"])
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
StructSpec::new(name, children, fields)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ mod spec;
|
|||||||
mod type_gen;
|
mod type_gen;
|
||||||
mod walk;
|
mod walk;
|
||||||
|
|
||||||
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
use crate::ast_node::{make_ast_enum_member, make_ast_enum_member_mut, make_ast_node_impl};
|
||||||
use crate::build_fn::make_build_fn;
|
use crate::build_fn::make_build_fn;
|
||||||
use crate::deserialize::deserialize_yaml_spec;
|
use crate::deserialize::deserialize_yaml_spec;
|
||||||
use crate::pretty_print::make_pretty_print_impl;
|
use crate::pretty_print::make_pretty_print_impl;
|
||||||
@ -165,6 +165,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let ast_enum_members_mut = build_specs
|
||||||
|
.iter()
|
||||||
|
.map(|build_spec| make_ast_enum_member_mut(build_spec))
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
use crate::ast::node::*;
|
use crate::ast::node::*;
|
||||||
|
|
||||||
@ -172,10 +179,18 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
#(#ast_enum_members,)*
|
#(#ast_enum_members,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AstNodeRefMut<'a> {
|
||||||
|
#(#ast_enum_members_mut,)*
|
||||||
|
}
|
||||||
|
|
||||||
pub trait AstNode {
|
pub trait AstNode {
|
||||||
fn children(&self) -> Vec<AstNodeRef>;
|
fn children(&self) -> Vec<AstNodeRef>;
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut>;
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef;
|
fn as_node_ref(&self) -> AstNodeRef;
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut;
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#impls)*
|
#(#impls)*
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
pub struct StructSpec {
|
pub struct StructSpec {
|
||||||
build: String,
|
build: String,
|
||||||
children: Vec<Box<StructChild>>,
|
children: Vec<Box<StructChild>>,
|
||||||
|
fields: Vec<Box<StructField>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StructSpec {
|
impl StructSpec {
|
||||||
pub fn new(build: &str, children: Vec<Box<StructChild>>) -> Self {
|
pub fn new(
|
||||||
|
build: &str,
|
||||||
|
children: Vec<Box<StructChild>>,
|
||||||
|
fields: Vec<Box<StructField>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
build: build.to_string(),
|
build: build.to_string(),
|
||||||
children,
|
children,
|
||||||
|
fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +26,10 @@ impl StructSpec {
|
|||||||
pub fn children(&self) -> impl Iterator<Item = &StructChild> {
|
pub fn children(&self) -> impl Iterator<Item = &StructChild> {
|
||||||
self.children.iter().map(Box::as_ref)
|
self.children.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> impl Iterator<Item = &StructField> {
|
||||||
|
self.fields.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum StructChild {
|
pub enum StructChild {
|
||||||
@ -36,13 +46,11 @@ impl StructChild {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_special(&self) -> Option<&SpecialChild> {
|
pub fn unwrap_special(&self) -> Option<&SpecialChild> {
|
||||||
match self {
|
match self {
|
||||||
StructChild::Special(special_child) => {
|
StructChild::Special(special_child) => Some(special_child),
|
||||||
Some(special_child)
|
_ => None,
|
||||||
},
|
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,14 +250,14 @@ impl SpecialChild {
|
|||||||
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
kind
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> &SpecialChildKind {
|
pub fn kind(&self) -> &SpecialChildKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
@ -260,3 +268,35 @@ pub enum SpecialChildKind {
|
|||||||
FileId,
|
FileId,
|
||||||
Range,
|
Range,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct StructField {
|
||||||
|
name: String,
|
||||||
|
kind: StructFieldKind,
|
||||||
|
optional: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructField {
|
||||||
|
pub fn new(name: &str, kind: StructFieldKind, optional: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind,
|
||||||
|
optional,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &StructFieldKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn optional(&self) -> bool {
|
||||||
|
self.optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum StructFieldKind {
|
||||||
|
USize,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::spec::struct_spec::{
|
use crate::spec::struct_spec::{
|
||||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField,
|
||||||
VecChild, VecChildBuild,
|
StructFieldKind, StructSpec, VecChild, VecChildBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -99,7 +99,7 @@ fn make_special_child_accessors(special_child: &SpecialChild) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_accessors(child: &StructChild) -> Option<TokenStream> {
|
fn make_child_accessors(child: &StructChild) -> Option<TokenStream> {
|
||||||
match child {
|
match child {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
||||||
@ -182,15 +182,68 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_annotated_field(field: &StructField) -> TokenStream {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
let field_type_ident = match field.kind() {
|
||||||
|
StructFieldKind::USize => quote! { usize },
|
||||||
|
};
|
||||||
|
if field.optional() {
|
||||||
|
quote! {
|
||||||
|
#field_ident: Option<#field_type_ident>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#field_ident: #field_type_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_field_init(field: &StructField) -> TokenStream {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
if field.optional() {
|
||||||
|
quote! {
|
||||||
|
#field_ident: None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_field_accessors(field: &StructField) -> TokenStream {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
let field_type_ident = match field.kind() {
|
||||||
|
StructFieldKind::USize => quote! { usize },
|
||||||
|
};
|
||||||
|
if field.optional() {
|
||||||
|
let setter_ident = format_ident!("set_{}", field.name());
|
||||||
|
quote! {
|
||||||
|
pub fn #field_ident(&self) -> Option<#field_type_ident> {
|
||||||
|
self.#field_ident
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #setter_ident(&mut self, #field_ident: #field_type_ident) {
|
||||||
|
self.#field_ident = Some(#field_ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", build_spec.build());
|
let type_ident = format_ident!("{}", build_spec.build());
|
||||||
let annotated_members = build_spec
|
let annotated_children = build_spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| make_annotated_member(child))
|
.map(|child| make_annotated_member(child))
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let annotated_fields = build_spec
|
||||||
|
.fields()
|
||||||
|
.map(|field| make_annotated_field(field))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let member_names = build_spec
|
let member_names = build_spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| make_member_ident(child))
|
.map(|child| make_member_ident(child))
|
||||||
@ -198,26 +251,39 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
|||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let accessors = build_spec
|
let field_inits = build_spec
|
||||||
|
.fields()
|
||||||
|
.map(|field| make_field_init(field))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let child_accessors = build_spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| make_accessors(child))
|
.map(|child| make_child_accessors(child))
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let field_accessors = build_spec
|
||||||
|
.fields()
|
||||||
|
.map(|field| make_field_accessors(field))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub struct #type_ident {
|
pub struct #type_ident {
|
||||||
#(#annotated_members),*
|
#(#annotated_children,)*
|
||||||
|
#(#annotated_fields,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #type_ident {
|
impl #type_ident {
|
||||||
pub fn new(#(#annotated_members),*) -> Self {
|
pub fn new(#(#annotated_children),*) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#(#member_names),*
|
#(#member_names,)*
|
||||||
|
#(#field_inits,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#accessors)*
|
#(#child_accessors)*
|
||||||
|
#(#field_accessors)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,36 @@
|
|||||||
pub mod node {
|
pub mod node {
|
||||||
include!(concat!(env!("OUT_DIR"), "/src/ast/node.rs"));
|
include!(concat!(env!("OUT_DIR"), "/src/ast/node.rs"));
|
||||||
|
|
||||||
|
impl OperatorInner {
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
OperatorInner::Or => "op_or",
|
||||||
|
OperatorInner::And => "op_and",
|
||||||
|
OperatorInner::EqualTo => "op_eq",
|
||||||
|
OperatorInner::NotEqualTo => "op_neq",
|
||||||
|
OperatorInner::Greater => "op_gt",
|
||||||
|
OperatorInner::Less => "op_lt",
|
||||||
|
OperatorInner::GreaterEqual => "op_ge",
|
||||||
|
OperatorInner::LessEqual => "op_le",
|
||||||
|
OperatorInner::Add => "op_add",
|
||||||
|
OperatorInner::Subtract => "op_sub",
|
||||||
|
OperatorInner::Multiply => "op_mul",
|
||||||
|
OperatorInner::Divide => "op_div",
|
||||||
|
OperatorInner::Modulo => "op_mod",
|
||||||
|
OperatorInner::LeftShift => "op_ls",
|
||||||
|
OperatorInner::RightShift => "op_rs",
|
||||||
|
OperatorInner::Spread => "op_spread",
|
||||||
|
OperatorInner::Star => "op_star",
|
||||||
|
OperatorInner::Not => "op_not",
|
||||||
|
OperatorInner::Negative => "op_neg",
|
||||||
|
OperatorInner::PlusPlus => "op_pp",
|
||||||
|
OperatorInner::MinusMinus => "op_mm",
|
||||||
|
OperatorInner::CallOp => "op_call",
|
||||||
|
OperatorInner::Index => "op_index",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Parameters {
|
impl Default for Parameters {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(vec![])
|
Self::new(vec![])
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
use crate::ast::ast_node::{AstNode, AstNodeRef};
|
use crate::ast::ast_node::{AstNode, AstNodeRef};
|
||||||
use crate::ast::node::{
|
use crate::ast::node::{
|
||||||
Class, CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Interface,
|
Class, CompilationUnit, Function, FunctionBody, Identifier, Interface,
|
||||||
Module, Namespace, Statement, UseStatement, UseStatementSuffix, VariableDeclaration,
|
InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction,
|
||||||
|
InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, PlatformFunction,
|
||||||
|
PlatformOperatorFunction, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse,
|
||||||
};
|
};
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::fqn_context::FqnContext;
|
use crate::name_analysis::fqn_context::FqnContext;
|
||||||
|
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
|
||||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
@ -67,9 +70,14 @@ fn gather_node(
|
|||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
match node {
|
match node {
|
||||||
AstNodeRef::Operator(_) => {}
|
AstNodeRef::Operator(_) => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
AstNodeRef::OperatorInner(_) => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
AstNodeRef::Identifier(_) => {
|
AstNodeRef::Identifier(_) => {
|
||||||
unreachable!()
|
unreachable!();
|
||||||
}
|
}
|
||||||
AstNodeRef::FullyQualifiedName(_) => {}
|
AstNodeRef::FullyQualifiedName(_) => {}
|
||||||
AstNodeRef::TypeUseList(_) => {}
|
AstNodeRef::TypeUseList(_) => {}
|
||||||
@ -98,13 +106,13 @@ fn gather_node(
|
|||||||
gather_use_statement(use_statement, symbol_table, diagnostics);
|
gather_use_statement(use_statement, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
AstNodeRef::UseStatementPrefix(_) => {
|
AstNodeRef::UseStatementPrefix(_) => {
|
||||||
unreachable!()
|
unreachable!();
|
||||||
}
|
}
|
||||||
AstNodeRef::UseStatementSuffix(_) => {
|
AstNodeRef::UseStatementSuffix(_) => {
|
||||||
unreachable!()
|
unreachable!();
|
||||||
}
|
}
|
||||||
AstNodeRef::UseList(_) => {
|
AstNodeRef::UseList(_) => {
|
||||||
unreachable!()
|
unreachable!();
|
||||||
}
|
}
|
||||||
AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => {
|
AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => {
|
||||||
gather_node_children(
|
gather_node_children(
|
||||||
@ -142,62 +150,76 @@ fn gather_node(
|
|||||||
AstNodeRef::Function(function) => {
|
AstNodeRef::Function(function) => {
|
||||||
gather_function(function, symbol_table, fqn_context, diagnostics);
|
gather_function(function, symbol_table, fqn_context, diagnostics);
|
||||||
}
|
}
|
||||||
AstNodeRef::OperatorFunction(_) => {}
|
AstNodeRef::OperatorFunction(operator_function) => {
|
||||||
AstNodeRef::PlatformFunction(_) => {}
|
gather_operator_function(operator_function, symbol_table, fqn_context, diagnostics);
|
||||||
AstNodeRef::InterfaceFunction(_) => {}
|
}
|
||||||
AstNodeRef::InterfaceDefaultFunction(_) => {}
|
AstNodeRef::PlatformFunction(platform_function) => {
|
||||||
AstNodeRef::InterfaceOperatorFunction(_) => {}
|
gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics);
|
||||||
AstNodeRef::InterfaceDefaultOperatorFunction(_) => {}
|
}
|
||||||
AstNodeRef::FunctionBody(function_body) => match function_body {
|
AstNodeRef::PlatformOperatorFunction(platform_operator_function) => {
|
||||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
gather_platform_operator_function(
|
||||||
gather_node(
|
platform_operator_function,
|
||||||
alias_body.as_node_ref(),
|
symbol_table,
|
||||||
symbol_table,
|
fqn_context,
|
||||||
fqn_context,
|
diagnostics,
|
||||||
diagnostics,
|
);
|
||||||
);
|
}
|
||||||
}
|
AstNodeRef::InterfaceFunction(interface_function) => {
|
||||||
FunctionBody::FunctionEqualsBody(equals_body) => {
|
gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics);
|
||||||
gather_node(
|
}
|
||||||
equals_body.as_node_ref(),
|
AstNodeRef::InterfaceDefaultFunction(interface_default_function) => {
|
||||||
symbol_table,
|
gather_interface_default_function(
|
||||||
fqn_context,
|
interface_default_function,
|
||||||
diagnostics,
|
symbol_table,
|
||||||
);
|
fqn_context,
|
||||||
}
|
diagnostics,
|
||||||
FunctionBody::FunctionBlockBody(block_body) => {
|
);
|
||||||
gather_node(
|
}
|
||||||
block_body.as_node_ref(),
|
AstNodeRef::InterfaceOperatorFunction(interface_operator_function) => {
|
||||||
symbol_table,
|
gather_interface_operator_function(
|
||||||
fqn_context,
|
interface_operator_function,
|
||||||
diagnostics,
|
symbol_table,
|
||||||
);
|
fqn_context,
|
||||||
}
|
diagnostics,
|
||||||
},
|
);
|
||||||
AstNodeRef::FunctionEqualsBody(_) => {}
|
}
|
||||||
AstNodeRef::FunctionAliasBody(_) => {}
|
AstNodeRef::InterfaceDefaultOperatorFunction(interface_default_operator_function) => {
|
||||||
AstNodeRef::FunctionBlockBody(block_body) => {
|
gather_interface_default_operator_function(
|
||||||
gather_function_block_body(block_body, symbol_table, fqn_context, diagnostics);
|
interface_default_operator_function,
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
AstNodeRef::FunctionBody(function_body) => {
|
||||||
|
gather_function_body(function_body, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::FunctionEqualsBody(function_equals_body) => {
|
||||||
|
gather_node_children(function_equals_body, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::FunctionAliasBody(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
AstNodeRef::FunctionBlockBody(function_block_body) => {
|
||||||
|
gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::ClassConstructor(class_constructor) => {
|
||||||
|
gather_node_children(class_constructor, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Member(member) => {
|
||||||
|
gather_member(member, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::Statement(statement) => {
|
||||||
|
gather_node_children(statement, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
|
AstNodeRef::VariableDeclaration(variable_declaration) => {
|
||||||
|
gather_variable_declaration(
|
||||||
|
variable_declaration,
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
AstNodeRef::ClassConstructor(_) => {}
|
|
||||||
AstNodeRef::Member(_) => {}
|
|
||||||
AstNodeRef::Statement(statement) => match statement {
|
|
||||||
Statement::VariableDeclaration(variable_declaration) => {
|
|
||||||
gather_node(
|
|
||||||
variable_declaration.as_node_ref(),
|
|
||||||
symbol_table,
|
|
||||||
fqn_context,
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Statement::AssignmentStatement(_) => {}
|
|
||||||
Statement::ExpressionStatement(_) => {}
|
|
||||||
Statement::UseStatement(_) => {}
|
|
||||||
Statement::IfStatement(_) => {}
|
|
||||||
Statement::WhileStatement(_) => {}
|
|
||||||
Statement::ForStatement(_) => {}
|
|
||||||
},
|
|
||||||
AstNodeRef::VariableDeclaration(_) => {}
|
|
||||||
AstNodeRef::AssignmentStatement(_) => {}
|
AstNodeRef::AssignmentStatement(_) => {}
|
||||||
AstNodeRef::ExpressionStatement(_) => {}
|
AstNodeRef::ExpressionStatement(_) => {}
|
||||||
AstNodeRef::IfStatement(_) => {}
|
AstNodeRef::IfStatement(_) => {}
|
||||||
@ -206,6 +228,11 @@ fn gather_node(
|
|||||||
AstNodeRef::IfElse(_) => {}
|
AstNodeRef::IfElse(_) => {}
|
||||||
AstNodeRef::WhileStatement(_) => {}
|
AstNodeRef::WhileStatement(_) => {}
|
||||||
AstNodeRef::ForStatement(_) => {}
|
AstNodeRef::ForStatement(_) => {}
|
||||||
|
AstNodeRef::LValue(_) => {}
|
||||||
|
AstNodeRef::LValueSuffix(_) => {}
|
||||||
|
AstNodeRef::VariableUse(variable_use) => {
|
||||||
|
gather_variable_use(variable_use, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
AstNodeRef::Expression(_) => {}
|
AstNodeRef::Expression(_) => {}
|
||||||
AstNodeRef::TernaryExpression(_) => {}
|
AstNodeRef::TernaryExpression(_) => {}
|
||||||
AstNodeRef::TernaryRhs(_) => {}
|
AstNodeRef::TernaryRhs(_) => {}
|
||||||
@ -443,6 +470,12 @@ fn gather_class(
|
|||||||
fqn_context.push(class.identifier().name());
|
fqn_context.push(class.identifier().name());
|
||||||
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
|
symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name()));
|
||||||
|
|
||||||
|
gather_node(
|
||||||
|
class.class_constructor().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
for declaration in class.class_level_declarations() {
|
for declaration in class.class_level_declarations() {
|
||||||
gather_node(
|
gather_node(
|
||||||
declaration.as_node_ref(),
|
declaration.as_node_ref(),
|
||||||
@ -479,25 +512,488 @@ fn gather_function(
|
|||||||
diagnostics,
|
diagnostics,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
|
||||||
|
gather_node(
|
||||||
|
function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
gather_node(
|
gather_node(
|
||||||
function.function_body().as_node_ref(),
|
function.function_body().as_node_ref(),
|
||||||
symbol_table,
|
symbol_table,
|
||||||
fqn_context,
|
fqn_context,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
);
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_function_block_body(
|
fn gather_operator_function(
|
||||||
function_block_body: &FunctionBlockBody,
|
operator_function: &OperatorFunction,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
fqn_context: &mut FqnContext,
|
fqn_context: &mut FqnContext,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
symbol_table.push_scope("FunctionBlockBody");
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics);
|
&fqn_context.resolve(&operator_function.operator().inner().name()),
|
||||||
|
operator_function.operator().inner().name(),
|
||||||
|
operator_function.is_public(),
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_operator(
|
||||||
|
operator_function.operator(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
operator_function.operator().inner().name(),
|
||||||
|
operator_function.operator().file_id(),
|
||||||
|
operator_function.operator().range(),
|
||||||
|
"Operator",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"FunctionScope {}",
|
||||||
|
operator_function.operator().inner().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
operator_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
operator_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
operator_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
operator_function.function_body().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gather_platform_function(
|
||||||
|
platform_function: &PlatformFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(platform_function.identifier().name()),
|
||||||
|
platform_function.identifier().name(),
|
||||||
|
platform_function.is_public(),
|
||||||
|
true,
|
||||||
|
Some(SourceDefinition::from_identifier(
|
||||||
|
platform_function.identifier(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
platform_function.identifier().name(),
|
||||||
|
platform_function.identifier().file_id(),
|
||||||
|
platform_function.identifier().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"PlatformFunctionScope {}",
|
||||||
|
platform_function.identifier().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
platform_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
platform_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
platform_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_platform_operator_function(
|
||||||
|
platform_operator_function: &PlatformOperatorFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(platform_operator_function.operator().inner().name()),
|
||||||
|
platform_operator_function.operator().inner().name(),
|
||||||
|
platform_operator_function.is_public(),
|
||||||
|
true,
|
||||||
|
Some(SourceDefinition::from_operator(
|
||||||
|
platform_operator_function.operator(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
platform_operator_function.operator().inner().name(),
|
||||||
|
platform_operator_function.operator().file_id(),
|
||||||
|
platform_operator_function.operator().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"PlatformOperatorFunctionScope {}",
|
||||||
|
platform_operator_function.operator().inner().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
platform_operator_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
platform_operator_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
platform_operator_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_interface_function(
|
||||||
|
interface_function: &InterfaceFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(interface_function.identifier().name()),
|
||||||
|
interface_function.identifier().name(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_identifier(
|
||||||
|
interface_function.identifier(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
interface_function.identifier().name(),
|
||||||
|
interface_function.identifier().file_id(),
|
||||||
|
interface_function.identifier().range(),
|
||||||
|
"Type",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"InterfaceFunctionScope {}",
|
||||||
|
interface_function.identifier().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
interface_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_interface_default_function(
|
||||||
|
interface_default_function: &InterfaceDefaultFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(interface_default_function.identifier().name()),
|
||||||
|
interface_default_function.identifier().name(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_identifier(
|
||||||
|
interface_default_function.identifier(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
interface_default_function.identifier().name(),
|
||||||
|
interface_default_function.identifier().file_id(),
|
||||||
|
interface_default_function.identifier().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"InterfaceDefaultFunctionScope {}",
|
||||||
|
interface_default_function.identifier().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
interface_default_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_function.function_body().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_interface_operator_function(
|
||||||
|
interface_operator_function: &InterfaceOperatorFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(interface_operator_function.operator().inner().name()),
|
||||||
|
interface_operator_function.operator().inner().name(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_operator(
|
||||||
|
interface_operator_function.operator(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
interface_operator_function.operator().inner().name(),
|
||||||
|
interface_operator_function.operator().file_id(),
|
||||||
|
interface_operator_function.operator().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"InterfaceOperatorFunctionScope {}",
|
||||||
|
interface_operator_function.operator().inner().name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
interface_operator_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_operator_function.parameters().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_operator_function.return_type().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_interface_default_operator_function(
|
||||||
|
interface_default_operator_function: &InterfaceDefaultOperatorFunction,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let function_symbol = FunctionSymbol::without_parameters_or_return_type(
|
||||||
|
&fqn_context.resolve(
|
||||||
|
interface_default_operator_function
|
||||||
|
.operator()
|
||||||
|
.inner()
|
||||||
|
.name(),
|
||||||
|
),
|
||||||
|
interface_default_operator_function
|
||||||
|
.operator()
|
||||||
|
.inner()
|
||||||
|
.name(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Some(SourceDefinition::from_operator(
|
||||||
|
interface_default_operator_function.operator(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
interface_default_operator_function
|
||||||
|
.operator()
|
||||||
|
.inner()
|
||||||
|
.name(),
|
||||||
|
interface_default_operator_function.operator().file_id(),
|
||||||
|
interface_default_operator_function.operator().range(),
|
||||||
|
"Function",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"InterfaceDefaultOperatorFunctionScope {}",
|
||||||
|
interface_default_operator_function
|
||||||
|
.operator()
|
||||||
|
.inner()
|
||||||
|
.name()
|
||||||
|
));
|
||||||
|
gather_node(
|
||||||
|
interface_default_operator_function.generics().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_operator_function
|
||||||
|
.parameters()
|
||||||
|
.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_operator_function
|
||||||
|
.return_type()
|
||||||
|
.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
gather_node(
|
||||||
|
interface_default_operator_function
|
||||||
|
.function_body()
|
||||||
|
.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_function_body(
|
||||||
|
function_body: &FunctionBody,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
symbol_table.push_scope("FunctionBodyScope");
|
||||||
|
match function_body {
|
||||||
|
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||||
|
gather_node(
|
||||||
|
alias_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionEqualsBody(equals_body) => {
|
||||||
|
gather_node(
|
||||||
|
equals_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionBlockBody(block_body) => {
|
||||||
|
gather_node(
|
||||||
|
block_body.as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gather_member(
|
||||||
|
member: &Member,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
let member_symbol = ClassMemberSymbol::new(
|
||||||
|
member.is_public(),
|
||||||
|
member.is_mut(),
|
||||||
|
member.identifier().name(),
|
||||||
|
Some(SourceDefinition::from_identifier(member.identifier())),
|
||||||
|
);
|
||||||
|
if let Err(insert_error) = symbol_table.insert_class_member_symbol(member_symbol) {
|
||||||
|
handle_insert_error(
|
||||||
|
insert_error,
|
||||||
|
member.identifier().name(),
|
||||||
|
member.identifier().file_id(),
|
||||||
|
member.identifier().range(),
|
||||||
|
"Class Member",
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gather_node(
|
||||||
|
member.type_use().as_node_ref(),
|
||||||
|
symbol_table,
|
||||||
|
fqn_context,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn gather_variable_declaration(
|
fn gather_variable_declaration(
|
||||||
variable_declaration: &VariableDeclaration,
|
variable_declaration: &VariableDeclaration,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
@ -530,3 +1026,12 @@ fn gather_variable_declaration(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gather_variable_use(
|
||||||
|
variable_use: &mut VariableUse,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
variable_use.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
}
|
||||||
|
|||||||
@ -3,32 +3,39 @@ use std::fmt::{Debug, Formatter};
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClassMemberSymbol {
|
pub struct ClassMemberSymbol {
|
||||||
|
is_public: bool,
|
||||||
|
is_mut: bool,
|
||||||
declared_name: String,
|
declared_name: String,
|
||||||
is_field: bool,
|
|
||||||
source_definition: Option<SourceDefinition>,
|
source_definition: Option<SourceDefinition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClassMemberSymbol {
|
impl ClassMemberSymbol {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
is_public: bool,
|
||||||
|
is_mut: bool,
|
||||||
declared_name: &str,
|
declared_name: &str,
|
||||||
is_field: bool,
|
|
||||||
source_definition: Option<SourceDefinition>,
|
source_definition: Option<SourceDefinition>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
is_public,
|
||||||
|
is_mut,
|
||||||
declared_name: declared_name.to_string(),
|
declared_name: declared_name.to_string(),
|
||||||
is_field,
|
|
||||||
source_definition,
|
source_definition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_public(&self) -> bool {
|
||||||
|
self.is_public
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_mut(&self) -> bool {
|
||||||
|
self.is_mut
|
||||||
|
}
|
||||||
|
|
||||||
pub fn declared_name(&self) -> &str {
|
pub fn declared_name(&self) -> &str {
|
||||||
&self.declared_name
|
&self.declared_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_field(&self) -> bool {
|
|
||||||
self.is_field
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||||
self.source_definition.as_ref()
|
self.source_definition.as_ref()
|
||||||
}
|
}
|
||||||
@ -37,8 +44,9 @@ impl ClassMemberSymbol {
|
|||||||
impl Debug for ClassMemberSymbol {
|
impl Debug for ClassMemberSymbol {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("ClassMemberSymbol")
|
f.debug_struct("ClassMemberSymbol")
|
||||||
|
.field("is_public", &self.is_public)
|
||||||
|
.field("is_mut", &self.is_mut)
|
||||||
.field("declared_name", &self.declared_name)
|
.field("declared_name", &self.declared_name)
|
||||||
.field("is_field", &self.is_field)
|
|
||||||
.field("source_definition", &self.source_definition)
|
.field("source_definition", &self.source_definition)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::range::Range;
|
use std::range::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::ast::node::{Identifier, UseStatement};
|
use crate::ast::node::{Identifier, Operator, UseStatement};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SourceDefinition {
|
pub struct SourceDefinition {
|
||||||
@ -16,14 +16,6 @@ impl SourceDefinition {
|
|||||||
range: identifier.range(),
|
range: identifier.range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self {
|
|
||||||
let borrowed = identifier.borrow();
|
|
||||||
SourceDefinition {
|
|
||||||
file_id: borrowed.file_id(),
|
|
||||||
range: borrowed.range(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
|
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -31,6 +23,13 @@ impl SourceDefinition {
|
|||||||
range: use_statement.range(),
|
range: use_statement.range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_operator(operator: &Operator) -> Self {
|
||||||
|
Self {
|
||||||
|
file_id: operator.file_id(),
|
||||||
|
range: operator.range(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn file_id(&self) -> usize {
|
pub fn file_id(&self) -> usize {
|
||||||
self.file_id
|
self.file_id
|
||||||
|
|||||||
@ -57,11 +57,11 @@ impl SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn current_scope(&self) -> &Scope {
|
fn current_scope(&self) -> &Scope {
|
||||||
self.scopes.last().unwrap()
|
&self.scopes[self.current_scope_id]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_scope_mut(&mut self) -> &mut Scope {
|
fn current_scope_mut(&mut self) -> &mut Scope {
|
||||||
self.scopes.last_mut().unwrap()
|
&mut self.scopes[self.current_scope_id]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_current_scope_concrete_use_symbol(
|
fn find_current_scope_concrete_use_symbol(
|
||||||
|
|||||||
@ -127,7 +127,13 @@ macro_rules! write_symbols {
|
|||||||
|
|
||||||
impl Display for Scope {
|
impl Display for Scope {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, "----Scope {} {}----", self.id(), self.debug_name())?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"----Scope {} (p: {}) {}----",
|
||||||
|
self.id(),
|
||||||
|
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.concrete_use_symbols());
|
||||||
write_symbols!(f, self.star_use_symbols());
|
write_symbols!(f, self.star_use_symbols());
|
||||||
write_symbols!(f, self.module_symbols());
|
write_symbols!(f, self.module_symbols());
|
||||||
|
|||||||
@ -1,6 +1,18 @@
|
|||||||
# $schema: ./ast.schema.yaml
|
# $schema: ./ast.schema.yaml
|
||||||
# Operators
|
# Operators
|
||||||
Operator:
|
Operator:
|
||||||
|
struct:
|
||||||
|
children:
|
||||||
|
- inner:
|
||||||
|
member:
|
||||||
|
rule: OperatorInner
|
||||||
|
- file_id:
|
||||||
|
special:
|
||||||
|
kind: file_id
|
||||||
|
- range:
|
||||||
|
special:
|
||||||
|
kind: range
|
||||||
|
OperatorInner:
|
||||||
leaf_enum:
|
leaf_enum:
|
||||||
rules:
|
rules:
|
||||||
- Or
|
- Or
|
||||||
@ -429,6 +441,30 @@ PlatformFunction:
|
|||||||
- identifier
|
- identifier
|
||||||
- parameters
|
- parameters
|
||||||
- return_type
|
- return_type
|
||||||
|
PlatformOperatorFunction:
|
||||||
|
struct:
|
||||||
|
children:
|
||||||
|
- is_public:
|
||||||
|
member:
|
||||||
|
rule: Pub
|
||||||
|
build:
|
||||||
|
boolean:
|
||||||
|
on: rule_present
|
||||||
|
- platform_kw:
|
||||||
|
skip:
|
||||||
|
rule: Platform
|
||||||
|
- op_kw:
|
||||||
|
skip:
|
||||||
|
rule: Op
|
||||||
|
- generics:
|
||||||
|
member:
|
||||||
|
rule: GenericParameters
|
||||||
|
build:
|
||||||
|
node:
|
||||||
|
or_else_default: true
|
||||||
|
- operator
|
||||||
|
- parameters
|
||||||
|
- return_type
|
||||||
InterfaceFunction:
|
InterfaceFunction:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
@ -592,12 +628,8 @@ VariableDeclaration:
|
|||||||
AssignmentStatement:
|
AssignmentStatement:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- left:
|
- l_value
|
||||||
member:
|
- expression
|
||||||
rule: Expression
|
|
||||||
- right:
|
|
||||||
member:
|
|
||||||
rule: Expression
|
|
||||||
ExpressionStatement:
|
ExpressionStatement:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
@ -679,6 +711,30 @@ ForStatement:
|
|||||||
skip:
|
skip:
|
||||||
rule: End
|
rule: End
|
||||||
|
|
||||||
|
# LValue
|
||||||
|
LValue:
|
||||||
|
struct:
|
||||||
|
children:
|
||||||
|
- variable_use
|
||||||
|
- suffixes:
|
||||||
|
vec:
|
||||||
|
rule: LValueSuffix
|
||||||
|
LValueSuffix:
|
||||||
|
tree_enum:
|
||||||
|
rules:
|
||||||
|
- ObjectProperty
|
||||||
|
- ObjectIndex
|
||||||
|
|
||||||
|
# VariableUse
|
||||||
|
VariableUse:
|
||||||
|
struct:
|
||||||
|
children:
|
||||||
|
- identifier
|
||||||
|
fields:
|
||||||
|
- scope_id:
|
||||||
|
kind: usize
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Expressions
|
# Expressions
|
||||||
Expression:
|
Expression:
|
||||||
polymorphic_type:
|
polymorphic_type:
|
||||||
@ -713,6 +769,9 @@ Expression:
|
|||||||
- Literal:
|
- Literal:
|
||||||
inner:
|
inner:
|
||||||
kind: Literal
|
kind: Literal
|
||||||
|
- VariableUse:
|
||||||
|
inner:
|
||||||
|
kind: VariableUse
|
||||||
- Fqn:
|
- Fqn:
|
||||||
inner:
|
inner:
|
||||||
kind: FullyQualifiedName
|
kind: FullyQualifiedName
|
||||||
@ -1055,6 +1114,9 @@ PrimaryExpression:
|
|||||||
- Literal:
|
- Literal:
|
||||||
inner:
|
inner:
|
||||||
kind: Literal
|
kind: Literal
|
||||||
|
- VariableUse:
|
||||||
|
inner:
|
||||||
|
kind: VariableUse
|
||||||
- Fqn:
|
- Fqn:
|
||||||
inner:
|
inner:
|
||||||
kind: FullyQualifiedName
|
kind: FullyQualifiedName
|
||||||
|
|||||||
@ -131,6 +131,10 @@ Index = { "[]" }
|
|||||||
BorrowMut = { Borrow ~ Mut }
|
BorrowMut = { Borrow ~ Mut }
|
||||||
|
|
||||||
Operator = {
|
Operator = {
|
||||||
|
OperatorInner
|
||||||
|
}
|
||||||
|
|
||||||
|
OperatorInner = {
|
||||||
Or
|
Or
|
||||||
| And
|
| And
|
||||||
| EqualTo
|
| EqualTo
|
||||||
@ -431,6 +435,16 @@ PlatformFunction = {
|
|||||||
~ ReturnType
|
~ ReturnType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlatformOperatorFunction = {
|
||||||
|
Pub?
|
||||||
|
~ Platform
|
||||||
|
~ Op
|
||||||
|
~ GenericParameters?
|
||||||
|
~ Operator
|
||||||
|
~ Parameters
|
||||||
|
~ ReturnType
|
||||||
|
}
|
||||||
|
|
||||||
InterfaceFunction = {
|
InterfaceFunction = {
|
||||||
Fn
|
Fn
|
||||||
~ GenericParameters?
|
~ GenericParameters?
|
||||||
@ -528,7 +542,7 @@ VariableDeclaration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssignmentStatement = {
|
AssignmentStatement = {
|
||||||
Expression
|
LValue
|
||||||
~ "="
|
~ "="
|
||||||
~ Expression
|
~ Expression
|
||||||
}
|
}
|
||||||
@ -579,6 +593,24 @@ ForStatement = {
|
|||||||
~ End
|
~ End
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LValue
|
||||||
|
|
||||||
|
LValue = {
|
||||||
|
VariableUse
|
||||||
|
~ LValueSuffix*
|
||||||
|
}
|
||||||
|
|
||||||
|
LValueSuffix = {
|
||||||
|
ObjectProperty
|
||||||
|
| ObjectIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variable Use
|
||||||
|
|
||||||
|
VariableUse = {
|
||||||
|
Identifier
|
||||||
|
}
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
|
|
||||||
Expression = {
|
Expression = {
|
||||||
@ -727,6 +759,7 @@ ObjectIndex = {
|
|||||||
|
|
||||||
PrimaryExpression = {
|
PrimaryExpression = {
|
||||||
Literal
|
Literal
|
||||||
|
| VariableUse
|
||||||
| FullyQualifiedName
|
| FullyQualifiedName
|
||||||
| Closure
|
| Closure
|
||||||
| ListExpression
|
| ListExpression
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user