Compare commits

...

2 Commits

Author SHA1 Message Date
Jesse Brault
8eb13791ee Update pest. 2025-11-23 20:15:28 -06:00
Jesse Brault
7ffa516c03 Add fields and special children for Polymorphic enum loop specs. 2025-11-23 14:22:33 -06:00
18 changed files with 534 additions and 261 deletions

44
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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! {

View File

@ -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() {

View File

@ -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};
@ -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,
} }
} }
@ -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)),
} }
@ -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

View File

@ -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)
} }
@ -63,7 +86,7 @@ fn deserialize_rule(rule_name: &str, props: &Yaml) -> PolymorphicEnumLoopRule {
pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> PolymorphicEnumLoopBuildSpec { pub fn deserialize_polymorphic_enum_loop(name: &str, props: &Yaml) -> PolymorphicEnumLoopBuildSpec {
let kind = props["kind"].as_str().unwrap(); let kind = props["kind"].as_str().unwrap();
let reverse = get_as_bool(&props["reverse"]); let reverse = get_as_bool(&props["reverse"]);
let rules = props["rules"] let rules = props["rules"]
.as_vec() .as_vec()
.unwrap() .unwrap()

View File

@ -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 {

View File

@ -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 }
@ -19,10 +21,11 @@ fn make_result() -> TokenStream {
fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -> TokenStream { fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
let type_ident = format_ident!("{}", spec.name()); let type_ident = format_ident!("{}", spec.name());
let result = make_result(); let result = make_result();
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() {
@ -43,7 +46,7 @@ fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
quote! { quote! {
impl PrettyPrint for #type_ident { impl PrettyPrint for #type_ident {
fn pretty_print(&self, writer: &mut IndentWriter) -> #result { fn pretty_print(&self, writer: &mut IndentWriter) -> #result {
@ -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,
} }

View File

@ -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,
}

View File

@ -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(),
@ -22,7 +29,7 @@ impl PolymorphicEnumLoopBuildSpec {
pub fn kind(&self) -> &str { pub fn kind(&self) -> &str {
&self.kind &self.kind
} }
pub fn reverse(&self) -> bool { pub fn reverse(&self) -> bool {
self.reverse self.reverse
} }
@ -51,15 +58,15 @@ impl PolymorphicEnumLoopRulePassThrough {
with: with.to_string(), with: with.to_string(),
} }
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn kind(&self) -> &str { pub fn kind(&self) -> &str {
&self.kind &self.kind
} }
pub fn with(&self) -> &str { pub fn with(&self) -> &str {
&self.with &self.with
} }
@ -69,17 +76,24 @@ 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,
} }
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
@ -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 {
@ -110,7 +129,7 @@ impl PolymorphicEnumLoopChildUseCurrent {
kind: kind.to_string(), kind: kind.to_string(),
} }
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
@ -136,7 +155,7 @@ impl PolymorphicEnumLoopRuleChildOnEach {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn rule(&self) -> &str { pub fn rule(&self) -> &str {
&self.rule &self.rule
} }

View File

@ -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,
}

View File

@ -1,96 +1,193 @@
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<_>>(); .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);
}
}
})
.collect::<Vec<_>>();
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)*
} }
} }
} }

View File

@ -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
View File

@ -0,0 +1,3 @@
fn main()
let x = 1 + 2L
end

View File

@ -30,14 +30,16 @@ pub mod node {
} }
} }
} }
impl Expression { impl Expression {
pub fn analyzed_kind(&self) -> Kind { pub fn analyzed_kind(&self) -> Kind {
match self { match self {
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!()
} }
@ -77,31 +79,21 @@ 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())
}
} }
} }
} }

View File

@ -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 {

View File

@ -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:

View File

@ -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) {