Add fields and special children for Polymorphic enum loop specs.
This commit is contained in:
parent
734a00ea92
commit
7ffa516c03
@ -21,16 +21,21 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
||||
.map(|child| {
|
||||
let child_ident = match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||
format_ident!("{}", use_current.name())
|
||||
Some(format_ident!("{}", use_current.name()))
|
||||
}
|
||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||
format_ident!("{}", on_each.name())
|
||||
Some(format_ident!("{}", on_each.name()))
|
||||
}
|
||||
PolymorphicEnumLoopRuleBuildChild::Special(_) => None,
|
||||
};
|
||||
quote! {
|
||||
children.push(self.#child_ident() as &dyn AstNode);
|
||||
}
|
||||
child_ident.map(|child_ident| {
|
||||
quote! {
|
||||
children.push(self.#child_ident() as &dyn AstNode);
|
||||
}
|
||||
})
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
|
||||
@ -4,7 +4,8 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
||||
PolymorphicEnumLoopRuleBuildChild, PolymorphicEnumLoopRuleChildOnEach,
|
||||
PolymorphicEnumLoopRulePassThrough,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use crate::spec::SpecialChildKind;
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
fn make_pass_through(pass_through: &PolymorphicEnumLoopRulePassThrough) -> TokenStream {
|
||||
@ -54,6 +55,16 @@ fn make_build(
|
||||
quote! { Box::new(result.unwrap()) }
|
||||
}
|
||||
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<_>>();
|
||||
|
||||
@ -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 {
|
||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||
let return_type_ident = format_ident!("{}", spec.kind());
|
||||
|
||||
let preamble = make_preamble(spec, &pair_ident);
|
||||
|
||||
let iter_expr = if spec.reverse() {
|
||||
quote! { #pair_ident.into_inner().rev() }
|
||||
} else {
|
||||
@ -94,6 +121,7 @@ pub fn make_polymorphic_enum_loop_build_fn(spec: &PolymorphicEnumLoopBuildSpec)
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
#preamble
|
||||
let mut result: Option<#return_type_ident> = None;
|
||||
for inner_pair in #iter_expr {
|
||||
match inner_pair.as_rule() {
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
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 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 {
|
||||
StructChild::SkipChild(skip_child) => {
|
||||
let rule_ident = format_ident!("{}", skip_child.rule());
|
||||
Some(quote! {
|
||||
Rule::#rule_ident => {}
|
||||
})
|
||||
},
|
||||
}
|
||||
StructChild::VecChild(vec_child) => {
|
||||
let rule_ident = format_ident!("{}", vec_child.rule());
|
||||
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 }
|
||||
})
|
||||
}
|
||||
StructChild::MemberChild(member_child) => {
|
||||
match member_child.build() {
|
||||
MemberChildBuild::Node(node_member_build) => {
|
||||
let rule_ident = format_ident!("{}", member_child.rule());
|
||||
let action = make_node_member_child_match_action(
|
||||
member_child.name(),
|
||||
node_member_build
|
||||
);
|
||||
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());
|
||||
Some(quote! {
|
||||
Rule::#rule_ident => { #action }
|
||||
})
|
||||
}
|
||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
||||
MemberChildBuild::Node(node_member_build) => {
|
||||
let rule_ident = format_ident!("{}", member_child.rule());
|
||||
let action =
|
||||
make_node_member_child_match_action(member_child.name(), node_member_build);
|
||||
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());
|
||||
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(_) => {
|
||||
Some(make_boolean_member_child_arg(member_child.name()))
|
||||
},
|
||||
}
|
||||
},
|
||||
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 pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||
|
||||
|
||||
let preamble = make_preamble(build_spec, &pair_ident);
|
||||
|
||||
|
||||
let special_children = make_special_children(build_spec);
|
||||
|
||||
let child_holders = build_spec
|
||||
@ -261,9 +260,9 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
||||
quote! {
|
||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
#preamble
|
||||
|
||||
|
||||
#(#special_children;)*
|
||||
|
||||
|
||||
#(#child_holders;)*
|
||||
|
||||
#iter_stream
|
||||
|
||||
@ -4,6 +4,7 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
||||
PolymorphicEnumLoopRuleBuild, PolymorphicEnumLoopRuleBuildChild,
|
||||
PolymorphicEnumLoopRuleChildOnEach, PolymorphicEnumLoopRulePassThrough,
|
||||
};
|
||||
use crate::spec::{SpecialChild, SpecialChildKind, StructField};
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
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(
|
||||
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 {
|
||||
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)
|
||||
.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 {
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let with = make_build_fn_name(
|
||||
props["with"].as_str()
|
||||
.unwrap_or(kind)
|
||||
);
|
||||
let with = make_build_fn_name(props["with"].as_str().unwrap_or(kind));
|
||||
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 {
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let reverse = get_as_bool(&props["reverse"]);
|
||||
|
||||
|
||||
let rules = props["rules"]
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
|
||||
@ -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::spec::struct_spec::*;
|
||||
use crate::spec::{SpecialChild, SpecialChildKind, StructField, StructFieldWrap};
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
fn deserialize_field(field_yaml: &Yaml) -> StructField {
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
||||
use crate::spec::leaf_struct_spec::{LeafStructBuildSpec, LeafStructMemberKind};
|
||||
use crate::spec::polymorphic_enum_inner_build::{
|
||||
PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMemberKind,
|
||||
};
|
||||
use crate::spec::polymorphic_enum_loop_spec::{
|
||||
PolymorphicEnumLoopBuildSpec, PolymorphicEnumLoopRule, PolymorphicEnumLoopRuleBuildChild,
|
||||
};
|
||||
@ -10,7 +13,6 @@ use crate::spec::BuildSpec;
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use crate::spec::polymorphic_enum_inner_build::{PolymorphicEnumInnerBuild, PolymorphicEnumInnerBuildMember, PolymorphicEnumInnerBuildMemberKind};
|
||||
|
||||
fn make_result() -> TokenStream {
|
||||
quote! { std::fmt::Result }
|
||||
@ -19,10 +21,11 @@ fn make_result() -> TokenStream {
|
||||
fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.name());
|
||||
let result = make_result();
|
||||
|
||||
|
||||
let type_string = spec.name();
|
||||
|
||||
let child_matchers = spec.members()
|
||||
|
||||
let child_matchers = spec
|
||||
.members()
|
||||
.map(|member| {
|
||||
let variant_ident = format_ident!("{}", member.name());
|
||||
match member.kind() {
|
||||
@ -43,7 +46,7 @@ fn make_polymorphic_enum_inner_build_p2_impl(spec: &PolymorphicEnumInnerBuild) -
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
quote! {
|
||||
impl PrettyPrint for #type_ident {
|
||||
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
|
||||
.children()
|
||||
.filter(|child| match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::Special(_) => false,
|
||||
_ => true,
|
||||
})
|
||||
.map(|child| {
|
||||
let child_ident = match child {
|
||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||
@ -86,6 +93,7 @@ fn make_polymorphic_enum_loop_p2_impl(spec: &PolymorphicEnumLoopBuildSpec) -> To
|
||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||
format_ident!("{}", on_each.name())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
quote! {
|
||||
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) => {
|
||||
Some(make_polymorphic_enum_loop_p2_impl(polymorphic_enum_loop))
|
||||
}
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => {
|
||||
Some(make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build))
|
||||
}
|
||||
BuildSpec::PolymorphicEnumInnerBuild(polymorphic_enum_inner_build) => Some(
|
||||
make_polymorphic_enum_inner_build_p2_impl(polymorphic_enum_inner_build),
|
||||
),
|
||||
BuildSpec::PolymorphicLeafEnum(_) => None,
|
||||
BuildSpec::PolymorphicTreeEnum(_) => None,
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
||||
use leaf_struct_spec::LeafStructBuildSpec;
|
||||
use node_production_spec::NodeProductionBuildSpec;
|
||||
use polymorphic_enum_inner_build::PolymorphicEnumInnerBuild;
|
||||
use polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||
use polymorphic_leaf_enum::PolymorphicLeafEnum;
|
||||
use polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
||||
use production_spec::ProductionBuildSpec;
|
||||
use struct_spec::StructSpec;
|
||||
use tree_enum_spec::TreeEnumBuildSpec;
|
||||
use polymorphic_tree_enum_spec::PolymorphicTreeEnumSpec;
|
||||
|
||||
pub(crate) mod leaf_enum_spec;
|
||||
pub(crate) mod leaf_struct_spec;
|
||||
@ -38,3 +38,72 @@ pub enum BuildSpec {
|
||||
PolymorphicLeafEnum(PolymorphicLeafEnum),
|
||||
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 {
|
||||
name: String,
|
||||
kind: String,
|
||||
@ -6,7 +8,12 @@ pub struct 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 {
|
||||
name: name.to_string(),
|
||||
kind: kind.to_string(),
|
||||
@ -22,7 +29,7 @@ impl PolymorphicEnumLoopBuildSpec {
|
||||
pub fn kind(&self) -> &str {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
|
||||
pub fn reverse(&self) -> bool {
|
||||
self.reverse
|
||||
}
|
||||
@ -51,15 +58,15 @@ impl PolymorphicEnumLoopRulePassThrough {
|
||||
with: with.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
|
||||
pub fn kind(&self) -> &str {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
|
||||
pub fn with(&self) -> &str {
|
||||
&self.with
|
||||
}
|
||||
@ -69,17 +76,24 @@ pub struct PolymorphicEnumLoopRuleBuild {
|
||||
name: String,
|
||||
variant: String,
|
||||
children: Vec<Box<PolymorphicEnumLoopRuleBuildChild>>,
|
||||
fields: Vec<StructField>,
|
||||
}
|
||||
|
||||
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 {
|
||||
name: name.to_string(),
|
||||
variant: variant.to_string(),
|
||||
children,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
@ -91,11 +105,16 @@ impl PolymorphicEnumLoopRuleBuild {
|
||||
pub fn children(&self) -> impl Iterator<Item = &PolymorphicEnumLoopRuleBuildChild> {
|
||||
self.children.iter().map(Box::as_ref)
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> &[StructField] {
|
||||
&self.fields
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PolymorphicEnumLoopRuleBuildChild {
|
||||
UseCurrent(PolymorphicEnumLoopChildUseCurrent),
|
||||
OnEach(PolymorphicEnumLoopRuleChildOnEach),
|
||||
Special(SpecialChild),
|
||||
}
|
||||
|
||||
pub struct PolymorphicEnumLoopChildUseCurrent {
|
||||
@ -110,7 +129,7 @@ impl PolymorphicEnumLoopChildUseCurrent {
|
||||
kind: kind.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
@ -136,7 +155,7 @@ impl PolymorphicEnumLoopRuleChildOnEach {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
|
||||
pub fn rule(&self) -> &str {
|
||||
&self.rule
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use crate::spec::{SpecialChild, StructField};
|
||||
|
||||
pub struct StructSpec {
|
||||
build: String,
|
||||
children: Vec<Box<StructChild>>,
|
||||
@ -246,72 +248,3 @@ impl BooleanMemberBuild {
|
||||
pub enum BooleanMemberBuildOn {
|
||||
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,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 quote::{format_ident, quote};
|
||||
|
||||
pub fn make_polymorphic_enum_loop_type(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream {
|
||||
let type_ident = format_ident!("{}", spec.name());
|
||||
|
||||
let build = spec.rules()
|
||||
.find(|rule| {
|
||||
match rule {
|
||||
PolymorphicEnumLoopRule::Build(_) => true,
|
||||
_ => false
|
||||
}
|
||||
|
||||
let build = spec
|
||||
.rules()
|
||||
.find(|rule| match rule {
|
||||
PolymorphicEnumLoopRule::Build(_) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|rule| {
|
||||
match rule {
|
||||
PolymorphicEnumLoopRule::Build(build) => build,
|
||||
_ => unreachable!()
|
||||
}
|
||||
.map(|rule| match rule {
|
||||
PolymorphicEnumLoopRule::Build(build) => build,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.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| {
|
||||
match child {
|
||||
let (child_ident, child_type_ident) = 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>
|
||||
}
|
||||
(child_ident, quote! { #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>
|
||||
}
|
||||
(child_ident, quote! { #child_type_ident })
|
||||
}
|
||||
}
|
||||
})
|
||||
.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())
|
||||
}
|
||||
}
|
||||
})
|
||||
.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()))
|
||||
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> }
|
||||
}
|
||||
};
|
||||
(child_ident, child_type_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! {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
pub struct #type_ident {
|
||||
#(#annotated_members),*
|
||||
#(#annotated_members,)*
|
||||
#(#annotated_fields,)*
|
||||
}
|
||||
|
||||
impl #type_ident {
|
||||
pub fn new(#(#annotated_members),*) -> Self {
|
||||
Self {
|
||||
#(#member_names),*
|
||||
#(#member_names,)*
|
||||
#(#field_initializers,)*
|
||||
}
|
||||
}
|
||||
|
||||
#(#accessors)*
|
||||
|
||||
#(#field_accessors)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::spec::struct_spec::{
|
||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField,
|
||||
StructFieldWrap, StructSpec, VecChild, VecChildBuild,
|
||||
MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild,
|
||||
};
|
||||
use crate::spec::{SpecialChild, SpecialChildKind, StructField, StructFieldWrap};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
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
|
||||
@ -30,14 +30,16 @@ pub mod node {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Expression {
|
||||
pub fn analyzed_kind(&self) -> Kind {
|
||||
match self {
|
||||
Expression::Ternary(ternary_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Or(or_expression) => {todo!()}
|
||||
Expression::Or(or_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::And(and_expression) => {
|
||||
todo!()
|
||||
}
|
||||
@ -47,9 +49,10 @@ pub mod node {
|
||||
Expression::Shift(shift_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive_expression) => additive_expression
|
||||
.analyzed_kind()
|
||||
.expect("AdditiveExpression's analyzed_kind not set.")
|
||||
.clone(),
|
||||
Expression::Multiplicative(multiplicative_expression) => {
|
||||
todo!()
|
||||
}
|
||||
@ -59,12 +62,11 @@ pub mod node {
|
||||
Expression::Suffix(suffix_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Literal(literal) => {
|
||||
literal.analyzed_kind()
|
||||
}
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.analyzed_kind().expect("IdentifierExpression's analyzed_kind not set.").clone()
|
||||
}
|
||||
Expression::Literal(literal) => literal.analyzed_kind(),
|
||||
Expression::Identifier(identifier) => identifier
|
||||
.analyzed_kind()
|
||||
.expect("IdentifierExpression's analyzed_kind not set.")
|
||||
.clone(),
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!()
|
||||
}
|
||||
@ -77,31 +79,21 @@ pub mod node {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Literal {
|
||||
pub fn analyzed_kind(&self) -> Kind {
|
||||
match self {
|
||||
Literal::IntLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Int.into())
|
||||
}
|
||||
Literal::LongLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Long.into())
|
||||
}
|
||||
Literal::DoubleLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Double.into())
|
||||
}
|
||||
Literal::SingleQuoteString(_) => {
|
||||
Kind::Primitive(PrimitiveKind::String.into())
|
||||
}
|
||||
Literal::IntLiteral(_) => Kind::Primitive(PrimitiveKind::Int.into()),
|
||||
Literal::LongLiteral(_) => Kind::Primitive(PrimitiveKind::Long.into()),
|
||||
Literal::DoubleLiteral(_) => Kind::Primitive(PrimitiveKind::Double.into()),
|
||||
Literal::SingleQuoteString(_) => Kind::Primitive(PrimitiveKind::String.into()),
|
||||
Literal::DString(_) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::BacktickString(_) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::BooleanLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Boolean.into())
|
||||
}
|
||||
Literal::BooleanLiteral(_) => 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::ast::build::build_ast;
|
||||
use deimos::ast::node::CompilationUnit;
|
||||
use deimos::ir::lower_ast::lower_compilation_unit;
|
||||
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 pest::Parser;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
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(
|
||||
paths: &[PathBuf],
|
||||
) -> 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);
|
||||
|
||||
if !type_diagnostics.is_empty() {
|
||||
eprintln!("There were type diagnostics")
|
||||
|
||||
if type_diagnostics.is_empty() {
|
||||
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 {
|
||||
|
||||
@ -1057,6 +1057,15 @@ AdditiveExpression:
|
||||
- rhs:
|
||||
on_each:
|
||||
rule: AdditiveRhs
|
||||
- file_id:
|
||||
special:
|
||||
kind: file_id
|
||||
- range:
|
||||
special:
|
||||
kind: range
|
||||
fields:
|
||||
- analyzed_kind:
|
||||
kind: Kind
|
||||
AdditiveRhs:
|
||||
struct:
|
||||
children:
|
||||
|
||||
@ -10,6 +10,7 @@ use crate::name_analysis::symbol::ExpressibleSymbol;
|
||||
use crate::type_analysis::kinds::class_kind::ClassKind;
|
||||
use crate::type_analysis::kinds::function_kind::FunctionKind;
|
||||
use crate::type_analysis::kinds::Kind;
|
||||
use codespan_reporting::diagnostic::Label;
|
||||
use codespan_reporting::files::Files;
|
||||
|
||||
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();
|
||||
|
||||
if left_kind != right_kind {
|
||||
diagnostics.push(DmDiagnostic::error().with_message(&format!(
|
||||
"Incompatible types for additive expression: {} vs. {}",
|
||||
left_kind, right_kind
|
||||
)));
|
||||
todo!("Error file_id and range; set Error type on additive expression")
|
||||
} else {
|
||||
todo!("set analyzed type for additive expression")
|
||||
diagnostics.push(
|
||||
DmDiagnostic::error()
|
||||
.with_message(&format!(
|
||||
"Incompatible types for additive expression: {} vs. {}",
|
||||
left_kind, right_kind
|
||||
))
|
||||
.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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user