Compare commits
2 Commits
734a00ea92
...
8eb13791ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8eb13791ee | ||
|
|
7ffa516c03 |
44
Cargo.lock
generated
44
Cargo.lock
generated
@ -283,28 +283,21 @@ version = "2.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.20.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest"
|
name = "pest"
|
||||||
version = "2.8.0"
|
version = "2.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"thiserror",
|
|
||||||
"ucd-trie",
|
"ucd-trie",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_derive"
|
name = "pest_derive"
|
||||||
version = "2.8.0"
|
version = "2.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
|
checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_generator",
|
"pest_generator",
|
||||||
@ -312,9 +305,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_generator"
|
name = "pest_generator"
|
||||||
version = "2.8.0"
|
version = "2.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
|
checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
@ -325,11 +318,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_meta"
|
name = "pest_meta"
|
||||||
version = "2.8.0"
|
version = "2.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
|
checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
|
||||||
"pest",
|
"pest",
|
||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
@ -419,26 +411,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
|||||||
@ -12,9 +12,9 @@ name = "dmc"
|
|||||||
path = "src/bin/dmc/main.rs"
|
path = "src/bin/dmc/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pest = { version = "2.8.0" }
|
pest = { version = "2.8.4" }
|
||||||
clap = { version = "4.5.23", features = ["derive"] }
|
clap = { version = "4.5.23", features = ["derive"] }
|
||||||
pest_derive = { version = "2.8.0", features = ["grammar-extras"] }
|
pest_derive = { version = "2.8.4", features = ["grammar-extras"] }
|
||||||
codespan-reporting = "0.12.0"
|
codespan-reporting = "0.12.0"
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
indoc = "2.0.6"
|
indoc = "2.0.6"
|
||||||
|
|||||||
@ -21,16 +21,21 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
.map(|child| {
|
.map(|child| {
|
||||||
let child_ident = match child {
|
let child_ident = match child {
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
format_ident!("{}", use_current.name())
|
Some(format_ident!("{}", use_current.name()))
|
||||||
}
|
}
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
format_ident!("{}", on_each.name())
|
Some(format_ident!("{}", on_each.name()))
|
||||||
}
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(_) => None,
|
||||||
};
|
};
|
||||||
quote! {
|
child_ident.map(|child_ident| {
|
||||||
children.push(self.#child_ident() as &dyn AstNode);
|
quote! {
|
||||||
}
|
children.push(self.#child_ident() as &dyn AstNode);
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
|||||||
@ -4,7 +4,8 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
|||||||
PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleChildOnEach,
|
PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleChildOnEach,
|
||||||
PolymorphicEnumLoopRulePassThrough,
|
PolymorphicEnumLoopRulePassThrough,
|
||||||
};
|
};
|
||||||
use proc_macro2::TokenStream;
|
use crate::spec::SpecialChildKind;
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> TokenStream {
|
fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> TokenStream {
|
||||||
@ -54,6 +55,16 @@ fn make_build(
|
|||||||
quote! { Box::new(result.unwrap()) }
|
quote! { Box::new(result.unwrap()) }
|
||||||
}
|
}
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child },
|
PolymorphicEnumLoopRuleBuildChild::OnEach(_) => quote! { on_each_child },
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(special_child) => {
|
||||||
|
match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
|
quote! { file_id }
|
||||||
|
}
|
||||||
|
SpecialChildKind::Range => {
|
||||||
|
quote! { Range { start: as_span.start(), end: as_span.end() } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -76,11 +87,27 @@ fn make_match_arm(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_preamble(spec: &PolymorphicEnumLoopBuildSpec, pair_ident: &Ident) -> TokenStream {
|
||||||
|
if spec.rules().any(|rule| match rule {
|
||||||
|
PolymorphicEnumLoopRule::Build(build) => build.children().any(|child| match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}),
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
quote! { let as_span = #pair_ident.as_span(); }
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||||
let return_type_ident = format_ident!("{}", spec.kind());
|
let return_type_ident = format_ident!("{}", spec.kind());
|
||||||
|
|
||||||
|
let preamble = make_preamble(spec, &pair_ident);
|
||||||
|
|
||||||
let iter_expr = if spec.reverse() {
|
let iter_expr = if spec.reverse() {
|
||||||
quote! { #pair_ident.into_inner().rev() }
|
quote! { #pair_ident.into_inner().rev() }
|
||||||
} else {
|
} else {
|
||||||
@ -94,6 +121,7 @@ pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec)
|
|||||||
|
|
||||||
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
|
||||||
let mut result: Option<#return_type_ident> = None;
|
let mut result: Option<#return_type_ident> = None;
|
||||||
for inner_pair in #iter_expr {
|
for inner_pair in #iter_expr {
|
||||||
match inner_pair.as_rule() {
|
match inner_pair.as_rule() {
|
||||||
|
|||||||
@ -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, StructChild, StructSpec, VecChild, VecChildBuild,
|
||||||
|
};
|
||||||
|
use crate::spec::{SpecialChild, SpecialChildKind};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
|||||||
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
||||||
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
||||||
};
|
};
|
||||||
|
use crate::spec::{SpecialChild, SpecialChildKind, StructField};
|
||||||
use yaml_rust2::Yaml;
|
use yaml_rust2::Yaml;
|
||||||
|
|
||||||
fn deserialize_build_child(child_name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuildChild {
|
fn deserialize_build_child(child_name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuildChild {
|
||||||
@ -17,6 +18,13 @@ fn deserialize_build_child(child_name: &str, props: &Yaml) -> PolymorphicEnumLoo
|
|||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(PolymorphicEnumLoopRuleChildOnEach::new(
|
PolymorphicEnumLoopRuleBuildChild::OnEach(PolymorphicEnumLoopRuleChildOnEach::new(
|
||||||
child_name, rule,
|
child_name, rule,
|
||||||
))
|
))
|
||||||
|
} else if props["special"].is_hash() {
|
||||||
|
let kind = match props["special"]["kind"].as_str().unwrap() {
|
||||||
|
"range" => SpecialChildKind::Range,
|
||||||
|
"file_id" => SpecialChildKind::FileId,
|
||||||
|
_ => panic!("Unknown special child kind"),
|
||||||
|
};
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(SpecialChild::new(child_name, kind))
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected 'use_current' or 'on_each' hash for polymorphic enum loop build child");
|
panic!("Expected 'use_current' or 'on_each' hash for polymorphic enum loop build child");
|
||||||
}
|
}
|
||||||
@ -35,15 +43,30 @@ fn deserialize_build(name: &str, props: &Yaml) -> PolymorphicEnumLoopRuleBuild {
|
|||||||
.map(Box::new)
|
.map(Box::new)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
PolymorphicEnumLoopRuleBuild::new(name, variant, children)
|
let fields = props["fields"]
|
||||||
|
.as_vec()
|
||||||
|
.map(|fields| {
|
||||||
|
fields.iter()
|
||||||
|
.map(|field_yaml| {
|
||||||
|
let (field_name, field_props) = unwrap_single_member_hash(field_yaml);
|
||||||
|
let kind = field_props["kind"].as_str().unwrap();
|
||||||
|
StructField::new(
|
||||||
|
&field_name,
|
||||||
|
kind,
|
||||||
|
None,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| vec![]);
|
||||||
|
|
||||||
|
PolymorphicEnumLoopRuleBuild::new(name, variant, children, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_pass_through(name: &str, props: &Yaml) -> PolymorphicEnumLoopRulePassThrough {
|
fn deserialize_pass_through(name: &str, props: &Yaml) -> PolymorphicEnumLoopRulePassThrough {
|
||||||
let kind = props["kind"].as_str().unwrap();
|
let kind = props["kind"].as_str().unwrap();
|
||||||
let with = make_build_fn_name(
|
let with = make_build_fn_name(props["with"].as_str().unwrap_or(kind));
|
||||||
props["with"].as_str()
|
|
||||||
.unwrap_or(kind)
|
|
||||||
);
|
|
||||||
PolymorphicEnumLoopRulePassThrough::new(name, kind, &with)
|
PolymorphicEnumLoopRulePassThrough::new(name, kind, &with)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use convert_case::{Case, Casing};
|
|||||||
|
|
||||||
use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_member_hash};
|
use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_member_hash};
|
||||||
use crate::spec::struct_spec::*;
|
use crate::spec::struct_spec::*;
|
||||||
|
use crate::spec::{SpecialChild, SpecialChildKind, StructField, StructFieldWrap};
|
||||||
use yaml_rust2::Yaml;
|
use yaml_rust2::Yaml;
|
||||||
|
|
||||||
fn deserialize_field(field_yaml: &Yaml) -> StructField {
|
fn deserialize_field(field_yaml: &Yaml) -> StructField {
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
||||||
|
use crate::spec::polymorphic_enum_inner_build::{
|
||||||
|
PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind,
|
||||||
|
};
|
||||||
use crate::spec::polymorphic_enum_loop_spec::{
|
use crate::spec::polymorphic_enum_loop_spec::{
|
||||||
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild,
|
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild,
|
||||||
};
|
};
|
||||||
@ -10,7 +13,6 @@ use crate::spec::BuildSpec;
|
|||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember, PolymorphicEnumInnerBuildMemberKind};
|
|
||||||
|
|
||||||
fn make_result() -> TokenStream {
|
fn make_result() -> TokenStream {
|
||||||
quote! { std::fmt::Result }
|
quote! { std::fmt::Result }
|
||||||
@ -22,7 +24,8 @@ fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -
|
|||||||
|
|
||||||
let type_string = spec.name();
|
let type_string = spec.name();
|
||||||
|
|
||||||
let child_matchers = spec.members()
|
let child_matchers = spec
|
||||||
|
.members()
|
||||||
.map(|member| {
|
.map(|member| {
|
||||||
let variant_ident = format_ident!("{}", member.name());
|
let variant_ident = format_ident!("{}", member.name());
|
||||||
match member.kind() {
|
match member.kind() {
|
||||||
@ -78,6 +81,10 @@ fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> To
|
|||||||
|
|
||||||
let child_print_statements = build
|
let child_print_statements = build
|
||||||
.children()
|
.children()
|
||||||
|
.filter(|child| match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(_) => false,
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
.map(|child| {
|
.map(|child| {
|
||||||
let child_ident = match child {
|
let child_ident = match child {
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
@ -86,6 +93,7 @@ fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> To
|
|||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
format_ident!("{}", on_each.name())
|
format_ident!("{}", on_each.name())
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
self.#child_ident().pretty_print(writer)?;
|
self.#child_ident().pretty_print(writer)?;
|
||||||
@ -330,9 +338,9 @@ pub fn make_pretty_print_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||||
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => Some(
|
||||||
Some(make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build))
|
make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build),
|
||||||
}
|
),
|
||||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
|
||||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
use leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
use leaf_struct_spec::LeafStructBuildSpec;
|
use leaf_struct_spec::LeafStructBuildSpec;
|
||||||
use node_production_spec::NodeProductionBuildSpec;
|
use node_production_spec::NodeProductionBuildSpec;
|
||||||
use polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
use polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
||||||
use polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
use polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||||
|
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||||
use polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
use polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||||
|
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||||
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
||||||
use production_spec::ProductionBuildSpec;
|
use production_spec::ProductionBuildSpec;
|
||||||
use struct_spec::StructSpec;
|
use struct_spec::StructSpec;
|
||||||
use tree_enum_spec::TreeEnumBuildSpec;
|
use tree_enum_spec::TreeEnumBuildSpec;
|
||||||
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
|
||||||
|
|
||||||
pub(crate) mod leaf_enum_spec;
|
pub(crate) mod leaf_enum_spec;
|
||||||
pub(crate) mod leaf_struct_spec;
|
pub(crate) mod leaf_struct_spec;
|
||||||
@ -38,3 +38,72 @@ pub enum BuildSpec {
|
|||||||
PolymorphicLeafEnum(PolymorphicLeafEnum),
|
PolymorphicLeafEnum(PolymorphicLeafEnum),
|
||||||
PolymorphicTreeEnum(PolymorphicTreeEnumSpec),
|
PolymorphicTreeEnum(PolymorphicTreeEnumSpec),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SpecialChild {
|
||||||
|
name: String,
|
||||||
|
kind: SpecialChildKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecialChild {
|
||||||
|
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &SpecialChildKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SpecialChildKind {
|
||||||
|
FileId,
|
||||||
|
Range,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StructField {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
wrap: Option<StructFieldWrap>,
|
||||||
|
vec: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructField {
|
||||||
|
pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>, vec: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind: kind.to_string(),
|
||||||
|
wrap,
|
||||||
|
vec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &str {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wrap(&self) -> Option<&StructFieldWrap> {
|
||||||
|
self.wrap.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vec(&self) -> bool {
|
||||||
|
self.vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum StructFieldWrap {
|
||||||
|
RcRefCell,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use crate::spec::{SpecialChild, StructField};
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopBuildSpec {
|
pub struct PolymorphicEnumLoopBuildSpec {
|
||||||
name: String,
|
name: String,
|
||||||
kind: String,
|
kind: String,
|
||||||
@ -6,7 +8,12 @@ pub struct PolymorphicEnumLoopBuildSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PolymorphicEnumLoopBuildSpec {
|
impl PolymorphicEnumLoopBuildSpec {
|
||||||
pub fn new(name: &str, kind: &str, reverse: bool, rules: Vec<Box<PolymorphicEnumLoopRule>>) -> Self {
|
pub fn new(
|
||||||
|
name: &str,
|
||||||
|
kind: &str,
|
||||||
|
reverse: bool,
|
||||||
|
rules: Vec<Box<PolymorphicEnumLoopRule>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
kind: kind.to_string(),
|
kind: kind.to_string(),
|
||||||
@ -69,14 +76,21 @@ pub struct PolymorphicEnumLoopRuleBuild {
|
|||||||
name: String,
|
name: String,
|
||||||
variant: String,
|
variant: String,
|
||||||
children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>,
|
children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>,
|
||||||
|
fields: Vec<StructField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PolymorphicEnumLoopRuleBuild {
|
impl PolymorphicEnumLoopRuleBuild {
|
||||||
pub fn new(name: &str, variant: &str, children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>) -> Self {
|
pub fn new(
|
||||||
|
name: &str,
|
||||||
|
variant: &str,
|
||||||
|
children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>,
|
||||||
|
fields: Vec<StructField>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
variant: variant.to_string(),
|
variant: variant.to_string(),
|
||||||
children,
|
children,
|
||||||
|
fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,11 +105,16 @@ impl PolymorphicEnumLoopRuleBuild {
|
|||||||
pub fn children(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRuleBuildChild> {
|
pub fn children(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRuleBuildChild> {
|
||||||
self.children.iter().map(Box::as_ref)
|
self.children.iter().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> &[StructField] {
|
||||||
|
&self.fields
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PolymorphicEnumLoopRuleBuildChild {
|
pub enum PolymorphicEnumLoopRuleBuildChild {
|
||||||
UseCurrent(PolymorphicEnumLoopChildUseCurrent),
|
UseCurrent(PolymorphicEnumLoopChildUseCurrent),
|
||||||
OnEach(PolymorphicEnumLoopRuleChildOnEach),
|
OnEach(PolymorphicEnumLoopRuleChildOnEach),
|
||||||
|
Special(SpecialChild),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PolymorphicEnumLoopChildUseCurrent {
|
pub struct PolymorphicEnumLoopChildUseCurrent {
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use crate::spec::{SpecialChild, StructField};
|
||||||
|
|
||||||
pub struct StructSpec {
|
pub struct StructSpec {
|
||||||
build: String,
|
build: String,
|
||||||
children: Vec<Box<StructChild>>,
|
children: Vec<Box<StructChild>>,
|
||||||
@ -246,72 +248,3 @@ impl BooleanMemberBuild {
|
|||||||
pub enum BooleanMemberBuildOn {
|
pub enum BooleanMemberBuildOn {
|
||||||
RulePresent,
|
RulePresent,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SpecialChild {
|
|
||||||
name: String,
|
|
||||||
kind: SpecialChildKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpecialChild {
|
|
||||||
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &SpecialChildKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum SpecialChildKind {
|
|
||||||
FileId,
|
|
||||||
Range,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StructField {
|
|
||||||
name: String,
|
|
||||||
kind: String,
|
|
||||||
wrap: Option<StructFieldWrap>,
|
|
||||||
vec: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StructField {
|
|
||||||
pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>, vec: bool) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
kind: kind.to_string(),
|
|
||||||
wrap,
|
|
||||||
vec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> &str {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap(&self) -> Option<&StructFieldWrap> {
|
|
||||||
self.wrap.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vec(&self) -> bool {
|
|
||||||
self.vec
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum StructFieldWrap {
|
|
||||||
RcRefCell,
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,78 +1,171 @@
|
|||||||
use crate::spec::polymorphic_enum_loop_spec::{PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild};
|
use crate::spec::polymorphic_enum_loop_spec::{
|
||||||
|
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild,
|
||||||
|
};
|
||||||
|
use crate::spec::SpecialChildKind;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_loop_type(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
pub fn make_polymorphic_enum_loop_type(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
|
|
||||||
let build = spec.rules()
|
let build = spec
|
||||||
.find(|rule| {
|
.rules()
|
||||||
match rule {
|
.find(|rule| match rule {
|
||||||
PolymorphicEnumLoopRule::Build(_) => true,
|
PolymorphicEnumLoopRule::Build(_) => true,
|
||||||
_ => false
|
_ => false,
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.map(|rule| {
|
.map(|rule| match rule {
|
||||||
match rule {
|
PolymorphicEnumLoopRule::Build(build) => build,
|
||||||
PolymorphicEnumLoopRule::Build(build) => build,
|
_ => unreachable!(),
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let annotated_members = build.children()
|
let annotated_members = build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
|
let child_ident = format_ident!("{}", use_current.name());
|
||||||
|
let child_type_ident = format_ident!("{}", use_current.kind());
|
||||||
|
quote! {
|
||||||
|
#child_ident: Box<#child_type_ident>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
|
let child_ident = format_ident!("{}", on_each.name());
|
||||||
|
let child_type_ident = format_ident!("{}", on_each.rule());
|
||||||
|
quote! {
|
||||||
|
#child_ident: Box<#child_type_ident>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(special_child) => {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
let child_type_ident = match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
|
quote! { usize }
|
||||||
|
}
|
||||||
|
SpecialChildKind::Range => {
|
||||||
|
quote! { Range<usize> }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#child_ident: #child_type_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let annotated_fields = build
|
||||||
|
.fields()
|
||||||
|
.iter()
|
||||||
|
.map(|field| {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
let field_type = format_ident!("{}", field.kind());
|
||||||
|
quote! {
|
||||||
|
#field_ident: Option<#field_type>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let member_names = build
|
||||||
|
.children()
|
||||||
|
.map(|child| match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
|
format_ident!("{}", use_current.name())
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
|
format_ident!("{}", on_each.name())
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(special_child) => {
|
||||||
|
format_ident!("{}", special_child.name())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let field_initializers = build
|
||||||
|
.fields()
|
||||||
|
.iter()
|
||||||
|
.map(|field| {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
quote! { #field_ident: None }
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let accessors = build
|
||||||
|
.children()
|
||||||
.map(|child| {
|
.map(|child| {
|
||||||
match child {
|
let (child_ident, child_type_ident) = match child {
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
let child_ident = format_ident!("{}", use_current.name());
|
let child_ident = format_ident!("{}", use_current.name());
|
||||||
let child_type_ident = format_ident!("{}", use_current.kind());
|
let child_type_ident = format_ident!("{}", use_current.kind());
|
||||||
quote! {
|
(child_ident, quote! { #child_type_ident })
|
||||||
#child_ident: Box<#child_type_ident>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
let child_ident = format_ident!("{}", on_each.name());
|
let child_ident = format_ident!("{}", on_each.name());
|
||||||
let child_type_ident = format_ident!("{}", on_each.rule());
|
let child_type_ident = format_ident!("{}", on_each.rule());
|
||||||
quote! {
|
(child_ident, quote! { #child_type_ident })
|
||||||
#child_ident: Box<#child_type_ident>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
PolymorphicEnumLoopRuleBuildChild::Special(special_child) => {
|
||||||
})
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
.collect::<Vec<_>>();
|
let child_type_ident = match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
let member_names = build.children()
|
quote! { usize }
|
||||||
.map(|child| {
|
}
|
||||||
match child {
|
SpecialChildKind::Range => {
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
quote! { Range<usize> }
|
||||||
format_ident!("{}", use_current.name())
|
}
|
||||||
}
|
};
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
(child_ident, child_type_ident)
|
||||||
format_ident!("{}", on_each.name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let accessors = build.children()
|
|
||||||
.map(|child| {
|
|
||||||
let (child_ident, child_type_ident) = match child {
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
|
||||||
(format_ident!("{}", use_current.name()), format_ident!("{}", use_current.kind()))
|
|
||||||
}
|
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
|
||||||
(format_ident!("{}", on_each.name()), format_ident!("{}", on_each.rule()))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let child_mut_ident = format_ident!("{}_mut", child_ident);
|
let child_mut_ident = format_ident!("{}_mut", child_ident);
|
||||||
|
|
||||||
|
let as_ref = match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(_) => {
|
||||||
|
quote! { &self.#child_ident }
|
||||||
|
}
|
||||||
|
_ => quote! { self.#child_ident.as_ref() },
|
||||||
|
};
|
||||||
|
|
||||||
|
let as_mut = match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::Special(_) => {
|
||||||
|
quote! { &mut self.#child_ident }
|
||||||
|
}
|
||||||
|
_ => quote! { self.#child_ident.as_mut() },
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #child_ident(&self) -> &#child_type_ident {
|
pub fn #child_ident(&self) -> &#child_type_ident {
|
||||||
self.#child_ident.as_ref()
|
#as_ref
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn #child_mut_ident(&mut self) -> &mut #child_type_ident {
|
pub fn #child_mut_ident(&mut self) -> &mut #child_type_ident {
|
||||||
self.#child_ident.as_mut()
|
#as_mut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let field_accessors = build
|
||||||
|
.fields()
|
||||||
|
.iter()
|
||||||
|
.map(|field| {
|
||||||
|
let field_ident = format_ident!("{}", field.name());
|
||||||
|
let field_ident_mut = format_ident!("{}_mut", field.name());
|
||||||
|
let field_type = format_ident!("{}", field.kind());
|
||||||
|
|
||||||
|
let set_ident = format_ident!("set_{}", 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_ident(&mut self, #field_ident: #field_type) {
|
||||||
|
self.#field_ident = Some(#field_ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -80,17 +173,21 @@ pub fn make_polymorphic_enum_loop_type(spec: &PolymorphicEnumLoopBuildSpec) -> T
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub struct #type_ident {
|
pub struct #type_ident {
|
||||||
#(#annotated_members),*
|
#(#annotated_members,)*
|
||||||
|
#(#annotated_fields,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #type_ident {
|
impl #type_ident {
|
||||||
pub fn new(#(#annotated_members),*) -> Self {
|
pub fn new(#(#annotated_members),*) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#(#member_names),*
|
#(#member_names,)*
|
||||||
|
#(#field_initializers,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#accessors)*
|
#(#accessors)*
|
||||||
|
|
||||||
|
#(#field_accessors)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::spec::struct_spec::{
|
use crate::spec::struct_spec::{
|
||||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField,
|
MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild,
|
||||||
StructFieldWrap, StructSpec, VecChild, VecChildBuild,
|
|
||||||
};
|
};
|
||||||
|
use crate::spec::{SpecialChild, SpecialChildKind, StructField, StructFieldWrap};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
|||||||
3
examples/incompat.dm
Normal file
3
examples/incompat.dm
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main()
|
||||||
|
let x = 1 + 2L
|
||||||
|
end
|
||||||
@ -37,7 +37,9 @@ pub mod node {
|
|||||||
Expression::Ternary(ternary_expression) => {
|
Expression::Ternary(ternary_expression) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Expression::Or(or_expression) => {todo!()}
|
Expression::Or(or_expression) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
Expression::And(and_expression) => {
|
Expression::And(and_expression) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -47,9 +49,10 @@ pub mod node {
|
|||||||
Expression::Shift(shift_expression) => {
|
Expression::Shift(shift_expression) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Expression::Additive(additive_expression) => {
|
Expression::Additive(additive_expression) => additive_expression
|
||||||
todo!()
|
.analyzed_kind()
|
||||||
}
|
.expect("AdditiveExpression's analyzed_kind not set.")
|
||||||
|
.clone(),
|
||||||
Expression::Multiplicative(multiplicative_expression) => {
|
Expression::Multiplicative(multiplicative_expression) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -59,12 +62,11 @@ pub mod node {
|
|||||||
Expression::Suffix(suffix_expression) => {
|
Expression::Suffix(suffix_expression) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Expression::Literal(literal) => {
|
Expression::Literal(literal) => literal.analyzed_kind(),
|
||||||
literal.analyzed_kind()
|
Expression::Identifier(identifier) => identifier
|
||||||
}
|
.analyzed_kind()
|
||||||
Expression::Identifier(identifier) => {
|
.expect("IdentifierExpression's analyzed_kind not set.")
|
||||||
identifier.analyzed_kind().expect("IdentifierExpression's analyzed_kind not set.").clone()
|
.clone(),
|
||||||
}
|
|
||||||
Expression::Fqn(fqn) => {
|
Expression::Fqn(fqn) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -81,27 +83,17 @@ pub mod node {
|
|||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn analyzed_kind(&self) -> Kind {
|
pub fn analyzed_kind(&self) -> Kind {
|
||||||
match self {
|
match self {
|
||||||
Literal::IntLiteral(_) => {
|
Literal::IntLiteral(_) => Kind::Primitive(PrimitiveKind::Int.into()),
|
||||||
Kind::Primitive(PrimitiveKind::Int.into())
|
Literal::LongLiteral(_) => Kind::Primitive(PrimitiveKind::Long.into()),
|
||||||
}
|
Literal::DoubleLiteral(_) => Kind::Primitive(PrimitiveKind::Double.into()),
|
||||||
Literal::LongLiteral(_) => {
|
Literal::SingleQuoteString(_) => Kind::Primitive(PrimitiveKind::String.into()),
|
||||||
Kind::Primitive(PrimitiveKind::Long.into())
|
|
||||||
}
|
|
||||||
Literal::DoubleLiteral(_) => {
|
|
||||||
Kind::Primitive(PrimitiveKind::Double.into())
|
|
||||||
}
|
|
||||||
Literal::SingleQuoteString(_) => {
|
|
||||||
Kind::Primitive(PrimitiveKind::String.into())
|
|
||||||
}
|
|
||||||
Literal::DString(_) => {
|
Literal::DString(_) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Literal::BacktickString(_) => {
|
Literal::BacktickString(_) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Literal::BooleanLiteral(_) => {
|
Literal::BooleanLiteral(_) => Kind::Primitive(PrimitiveKind::Boolean.into()),
|
||||||
Kind::Primitive(PrimitiveKind::Boolean.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,128 @@
|
|||||||
use crate::name_analysis::name_analysis;
|
use codespan_reporting::files::SimpleFiles;
|
||||||
|
use codespan_reporting::term;
|
||||||
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
use deimos::asm::assemble_ir::assemble_ir_function;
|
use deimos::asm::assemble_ir::assemble_ir_function;
|
||||||
|
use deimos::ast::build::build_ast;
|
||||||
use deimos::ast::node::CompilationUnit;
|
use deimos::ast::node::CompilationUnit;
|
||||||
use deimos::ir::lower_ast::lower_compilation_unit;
|
use deimos::ir::lower_ast::lower_compilation_unit;
|
||||||
use deimos::ir::Ir;
|
use deimos::ir::Ir;
|
||||||
|
use deimos::name_analysis::analyze_names;
|
||||||
|
use deimos::name_analysis::symbol_table::SymbolTable;
|
||||||
|
use deimos::parser::{DeimosParser, Rule};
|
||||||
|
use deimos::std_core::add_std_core_symbols;
|
||||||
use deimos::type_analysis::analyze_types;
|
use deimos::type_analysis::analyze_types;
|
||||||
|
use pest::Parser;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
struct ParseErrors {
|
||||||
|
errors: Vec<pest::error::Error<Rule>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ParseErrors {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ParseErrors {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
writeln!(f, "There were errors during parsing.")?;
|
||||||
|
for parse_error in &self.errors {
|
||||||
|
writeln!(f, "{}", parse_error)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ParseErrors {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CompilationErrors {
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CompilationErrors {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
if self.count == 1 {
|
||||||
|
writeln!(f, "There was 1 error during compilation. See above.")
|
||||||
|
} else {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"There were {} errors during compilation. See above.",
|
||||||
|
self.count
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for CompilationErrors {}
|
||||||
|
|
||||||
pub fn compile_to_ir(
|
pub fn compile_to_ir(
|
||||||
paths: &[PathBuf],
|
paths: &[PathBuf],
|
||||||
) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
||||||
let mut compilation_units = name_analysis(&paths)?;
|
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
|
||||||
|
for path in paths {
|
||||||
|
let src = std::fs::read_to_string(path).unwrap();
|
||||||
|
paths_and_sources.insert(path.display().to_string(), src);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut compilation_units = vec![];
|
||||||
|
let mut files: SimpleFiles<&str, &str> = SimpleFiles::new();
|
||||||
|
let mut parse_errors = vec![];
|
||||||
|
|
||||||
|
for (path, source) in &paths_and_sources {
|
||||||
|
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
|
||||||
|
match parse_result {
|
||||||
|
Ok(mut pairs) => {
|
||||||
|
let file_id = files.add(path, source);
|
||||||
|
let compilation_unit = build_ast(file_id, &mut pairs);
|
||||||
|
compilation_units.push(compilation_unit);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
parse_errors.push(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parse_errors.is_empty() {
|
||||||
|
return Err(Box::new(ParseErrors {
|
||||||
|
errors: parse_errors,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
|
||||||
|
|
||||||
|
let name_diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table);
|
||||||
|
|
||||||
|
if name_diagnostics.is_empty() {
|
||||||
|
println!("Name analysis complete.");
|
||||||
|
} else {
|
||||||
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
|
let config = term::Config::default();
|
||||||
|
for diagnostic in &name_diagnostics {
|
||||||
|
term::emit(&mut writer.lock(), &config, &files, diagnostic)?;
|
||||||
|
}
|
||||||
|
return Err(Box::new(CompilationErrors {
|
||||||
|
count: name_diagnostics.len(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
let type_diagnostics = analyze_types(&mut compilation_units);
|
let type_diagnostics = analyze_types(&mut compilation_units);
|
||||||
|
|
||||||
if !type_diagnostics.is_empty() {
|
if type_diagnostics.is_empty() {
|
||||||
eprintln!("There were type diagnostics")
|
println!("Type analysis complete.");
|
||||||
|
} else {
|
||||||
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
|
let config = term::Config::default();
|
||||||
|
for diagnostic in &type_diagnostics {
|
||||||
|
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
|
||||||
|
}
|
||||||
|
return Err(Box::new(CompilationErrors {
|
||||||
|
count: type_diagnostics.len(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
for compilation_unit in &compilation_units {
|
for compilation_unit in &compilation_units {
|
||||||
|
|||||||
@ -1057,6 +1057,15 @@ AdditiveExpression:
|
|||||||
- rhs:
|
- rhs:
|
||||||
on_each:
|
on_each:
|
||||||
rule: AdditiveRhs
|
rule: AdditiveRhs
|
||||||
|
- file_id:
|
||||||
|
special:
|
||||||
|
kind: file_id
|
||||||
|
- range:
|
||||||
|
special:
|
||||||
|
kind: range
|
||||||
|
fields:
|
||||||
|
- analyzed_kind:
|
||||||
|
kind: Kind
|
||||||
AdditiveRhs:
|
AdditiveRhs:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use crate::name_analysis::symbol::ExpressibleSymbol;
|
|||||||
use crate::type_analysis::kinds::class_kind::ClassKind;
|
use crate::type_analysis::kinds::class_kind::ClassKind;
|
||||||
use crate::type_analysis::kinds::function_kind::FunctionKind;
|
use crate::type_analysis::kinds::function_kind::FunctionKind;
|
||||||
use crate::type_analysis::kinds::Kind;
|
use crate::type_analysis::kinds::Kind;
|
||||||
|
use codespan_reporting::diagnostic::Label;
|
||||||
use codespan_reporting::files::Files;
|
use codespan_reporting::files::Files;
|
||||||
|
|
||||||
pub fn analyze_types(compilation_units: &mut [CompilationUnit]) -> Vec<DmDiagnostic> {
|
pub fn analyze_types(compilation_units: &mut [CompilationUnit]) -> Vec<DmDiagnostic> {
|
||||||
@ -193,14 +194,20 @@ fn ta_additive_expression(
|
|||||||
let right_kind = additive_expression.rhs().expression().analyzed_kind();
|
let right_kind = additive_expression.rhs().expression().analyzed_kind();
|
||||||
|
|
||||||
if left_kind != right_kind {
|
if left_kind != right_kind {
|
||||||
diagnostics.push(DmDiagnostic::error().with_message(&format!(
|
diagnostics.push(
|
||||||
"Incompatible types for additive expression: {} vs. {}",
|
DmDiagnostic::error()
|
||||||
left_kind, right_kind
|
.with_message(&format!(
|
||||||
)));
|
"Incompatible types for additive expression: {} vs. {}",
|
||||||
todo!("Error file_id and range; set Error type on additive expression")
|
left_kind, right_kind
|
||||||
} else {
|
))
|
||||||
todo!("set analyzed type for additive expression")
|
.with_label(Label::primary(
|
||||||
|
*additive_expression.file_id(),
|
||||||
|
*additive_expression.range(),
|
||||||
|
)
|
||||||
|
.with_message("Incompatible types here.")),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
additive_expression.set_analyzed_kind(left_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ta_identifier_expression(identifier_expression: &mut IdentifierExpression) {
|
fn ta_identifier_expression(identifier_expression: &mut IdentifierExpression) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user