diff --git a/macro/src/dialect.rs b/macro/src/dialect.rs index 21571b43c8..5f5c7e83bb 100644 --- a/macro/src/dialect.rs +++ b/macro/src/dialect.rs @@ -54,12 +54,13 @@ fn generate_dialect_module( dialect: Record, record_keeper: &RecordKeeper, ) -> Result { + let dialect_name = dialect.name()?; let operations = record_keeper .all_derived_definitions("Op") .map(Operation::from_definition) .collect::, _>>()? .into_iter() - .filter(|operation| operation.dialect_name() == dialect.name()) + .filter(|operation| operation.dialect_name() == dialect_name) .collect::>(); let doc = format!( diff --git a/macro/src/dialect/operation.rs b/macro/src/dialect/operation.rs index 9b1c6f0303..e3958ce5e3 100644 --- a/macro/src/dialect/operation.rs +++ b/macro/src/dialect/operation.rs @@ -1,190 +1,20 @@ mod accessors; mod builder; - -use self::builder::OperationBuilder; -use super::utility::{sanitize_documentation, sanitize_snake_case_name}; +mod element_kind; +mod field_kind; +mod operation_field; + +use self::element_kind::ElementKind; +use self::operation_field::OperationField; +use self::{builder::OperationBuilder, field_kind::FieldKind}; +use super::utility::sanitize_documentation; use crate::dialect::{ error::{Error, OdsError}, types::{AttributeConstraint, RegionConstraint, SuccessorConstraint, Trait, TypeConstraint}, }; -use proc_macro2::{Ident, TokenStream}; +use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens, TokenStreamExt}; -use syn::{parse_quote, Type}; -use tblgen::{ - error::{SourceError, TableGenError, WithLocation}, - record::Record, -}; - -#[derive(Debug, Clone, Copy)] -pub enum ElementKind { - Operand, - Result, -} - -impl ElementKind { - pub fn as_str(&self) -> &'static str { - match self { - Self::Operand => "operand", - Self::Result => "result", - } - } -} - -#[derive(Debug, Clone)] -pub enum FieldKind<'a> { - Element { - kind: ElementKind, - constraint: TypeConstraint<'a>, - sequence_info: SequenceInfo, - variadic_kind: VariadicKind, - }, - Attribute { - constraint: AttributeConstraint<'a>, - }, - Successor { - constraint: SuccessorConstraint<'a>, - sequence_info: SequenceInfo, - }, - Region { - constraint: RegionConstraint<'a>, - sequence_info: SequenceInfo, - }, -} - -impl<'a> FieldKind<'a> { - pub fn as_str(&self) -> &'static str { - match self { - Self::Element { kind, .. } => kind.as_str(), - Self::Attribute { .. } => "attribute", - Self::Successor { .. } => "successor", - Self::Region { .. } => "region", - } - } - - pub fn is_optional(&self) -> Result { - Ok(match self { - Self::Element { constraint, .. } => constraint.is_optional(), - Self::Attribute { constraint, .. } => { - constraint.is_optional()? || constraint.has_default_value()? - } - Self::Successor { .. } | Self::Region { .. } => false, - }) - } - - pub fn is_result(&self) -> bool { - matches!( - self, - Self::Element { - kind: ElementKind::Result, - .. - } - ) - } - - pub fn parameter_type(&self) -> Result { - Ok(match self { - Self::Element { - kind, constraint, .. - } => { - let base_type: Type = match kind { - ElementKind::Operand => { - parse_quote!(::melior::ir::Value<'c, '_>) - } - ElementKind::Result => { - parse_quote!(::melior::ir::Type<'c>) - } - }; - if constraint.is_variadic() { - parse_quote! { &[#base_type] } - } else { - base_type - } - } - Self::Attribute { constraint } => { - if constraint.is_unit()? { - parse_quote!(bool) - } else { - let r#type: Type = syn::parse_str(constraint.storage_type()?)?; - parse_quote!(#r#type<'c>) - } - } - Self::Successor { constraint, .. } => { - let r#type: Type = parse_quote!(&::melior::ir::Block<'c>); - if constraint.is_variadic() { - parse_quote!(&[#r#type]) - } else { - r#type - } - } - Self::Region { constraint, .. } => { - let r#type: Type = parse_quote!(::melior::ir::Region<'c>); - if constraint.is_variadic() { - parse_quote!(Vec<#r#type>) - } else { - r#type - } - } - }) - } - - fn create_result_type(r#type: Type) -> Type { - parse_quote!(Result<#r#type, ::melior::Error>) - } - - fn create_iterator_type(r#type: Type) -> Type { - parse_quote!(impl Iterator) - } - - pub fn return_type(&self) -> Result { - Ok(match self { - Self::Element { - kind, - constraint, - variadic_kind, - .. - } => { - let base_type: Type = match kind { - ElementKind::Operand => { - parse_quote!(::melior::ir::Value<'c, '_>) - } - ElementKind::Result => { - parse_quote!(::melior::ir::operation::OperationResult<'c, '_>) - } - }; - if !constraint.is_variadic() { - Self::create_result_type(base_type) - } else if let VariadicKind::AttrSized {} = variadic_kind { - Self::create_result_type(Self::create_iterator_type(base_type)) - } else { - Self::create_iterator_type(base_type) - } - } - Self::Attribute { constraint } => { - if constraint.is_unit()? { - parse_quote!(bool) - } else { - Self::create_result_type(self.parameter_type()?) - } - } - Self::Successor { constraint, .. } => { - let r#type: Type = parse_quote!(::melior::ir::BlockRef<'c, '_>); - if constraint.is_variadic() { - Self::create_iterator_type(r#type) - } else { - Self::create_result_type(r#type) - } - } - Self::Region { constraint, .. } => { - let r#type: Type = parse_quote!(::melior::ir::RegionRef<'c, '_>); - if constraint.is_variadic() { - Self::create_iterator_type(r#type) - } else { - Self::create_result_type(r#type) - } - } - }) - } -} +use tblgen::{error::WithLocation, record::Record}; #[derive(Debug, Clone)] pub struct SequenceInfo { @@ -225,76 +55,9 @@ impl VariadicKind { } } -#[derive(Debug, Clone)] -pub struct OperationField<'a> { - pub(crate) name: &'a str, - pub(crate) sanitized_name: Ident, - pub(crate) kind: FieldKind<'a>, -} - -impl<'a> OperationField<'a> { - fn new(name: &'a str, kind: FieldKind<'a>) -> Result { - Ok(Self { - name, - sanitized_name: sanitize_snake_case_name(name)?, - kind, - }) - } - - fn new_attribute(name: &'a str, constraint: AttributeConstraint<'a>) -> Result { - Self::new(name, FieldKind::Attribute { constraint }) - } - - fn new_region( - name: &'a str, - constraint: RegionConstraint<'a>, - sequence_info: SequenceInfo, - ) -> Result { - Self::new( - name, - FieldKind::Region { - constraint, - sequence_info, - }, - ) - } - - fn new_successor( - name: &'a str, - constraint: SuccessorConstraint<'a>, - sequence_info: SequenceInfo, - ) -> Result { - Self::new( - name, - FieldKind::Successor { - constraint, - sequence_info, - }, - ) - } - - fn new_element( - name: &'a str, - constraint: TypeConstraint<'a>, - kind: ElementKind, - sequence_info: SequenceInfo, - variadic_kind: VariadicKind, - ) -> Result { - Self::new( - name, - FieldKind::Element { - kind, - constraint, - sequence_info, - variadic_kind, - }, - ) - } -} - #[derive(Debug, Clone)] pub struct Operation<'a> { - dialect: Record<'a>, + dialect_name: &'a str, short_name: &'a str, full_name: String, class_name: &'a str, @@ -310,8 +73,8 @@ pub struct Operation<'a> { } impl<'a> Operation<'a> { - pub fn dialect_name(&self) -> Result<&str, SourceError> { - self.dialect.name() + pub fn dialect_name(&self) -> &str { + &self.dialect_name } pub fn fields(&self) -> impl Iterator> + Clone { @@ -553,7 +316,7 @@ impl<'a> Operation<'a> { let short_name = definition.str_value("opName")?; Ok(Self { - dialect, + dialect_name: dialect.name()?.into(), short_name, full_name: { let dialect_name = dialect.string_value("name")?; diff --git a/macro/src/dialect/operation/element_kind.rs b/macro/src/dialect/operation/element_kind.rs new file mode 100644 index 0000000000..6f1de942ef --- /dev/null +++ b/macro/src/dialect/operation/element_kind.rs @@ -0,0 +1,14 @@ +#[derive(Debug, Clone, Copy)] +pub enum ElementKind { + Operand, + Result, +} + +impl ElementKind { + pub fn as_str(&self) -> &'static str { + match self { + Self::Operand => "operand", + Self::Result => "result", + } + } +} diff --git a/macro/src/dialect/operation/field_kind.rs b/macro/src/dialect/operation/field_kind.rs new file mode 100644 index 0000000000..39c8323b86 --- /dev/null +++ b/macro/src/dialect/operation/field_kind.rs @@ -0,0 +1,163 @@ +use super::{element_kind::ElementKind, SequenceInfo, VariadicKind}; +use crate::dialect::{ + error::Error, + types::{AttributeConstraint, RegionConstraint, SuccessorConstraint, TypeConstraint}, +}; +use syn::parse_quote; +use syn::Type; + +#[derive(Debug, Clone)] +pub enum FieldKind<'a> { + Element { + kind: ElementKind, + constraint: TypeConstraint<'a>, + sequence_info: SequenceInfo, + variadic_kind: VariadicKind, + }, + Attribute { + constraint: AttributeConstraint<'a>, + }, + Successor { + constraint: SuccessorConstraint<'a>, + sequence_info: SequenceInfo, + }, + Region { + constraint: RegionConstraint<'a>, + sequence_info: SequenceInfo, + }, +} + +impl<'a> FieldKind<'a> { + pub fn as_str(&self) -> &'static str { + match self { + Self::Element { kind, .. } => kind.as_str(), + Self::Attribute { .. } => "attribute", + Self::Successor { .. } => "successor", + Self::Region { .. } => "region", + } + } + + pub fn is_optional(&self) -> Result { + Ok(match self { + Self::Element { constraint, .. } => constraint.is_optional(), + Self::Attribute { constraint, .. } => { + constraint.is_optional()? || constraint.has_default_value()? + } + Self::Successor { .. } | Self::Region { .. } => false, + }) + } + + pub fn is_result(&self) -> bool { + matches!( + self, + Self::Element { + kind: ElementKind::Result, + .. + } + ) + } + + pub fn parameter_type(&self) -> Result { + Ok(match self { + Self::Element { + kind, constraint, .. + } => { + let base_type: Type = match kind { + ElementKind::Operand => { + parse_quote!(::melior::ir::Value<'c, '_>) + } + ElementKind::Result => { + parse_quote!(::melior::ir::Type<'c>) + } + }; + if constraint.is_variadic() { + parse_quote! { &[#base_type] } + } else { + base_type + } + } + Self::Attribute { constraint } => { + if constraint.is_unit()? { + parse_quote!(bool) + } else { + let r#type: Type = syn::parse_str(constraint.storage_type()?)?; + parse_quote!(#r#type<'c>) + } + } + Self::Successor { constraint, .. } => { + let r#type: Type = parse_quote!(&::melior::ir::Block<'c>); + if constraint.is_variadic() { + parse_quote!(&[#r#type]) + } else { + r#type + } + } + Self::Region { constraint, .. } => { + let r#type: Type = parse_quote!(::melior::ir::Region<'c>); + if constraint.is_variadic() { + parse_quote!(Vec<#r#type>) + } else { + r#type + } + } + }) + } + + fn create_result_type(r#type: Type) -> Type { + parse_quote!(Result<#r#type, ::melior::Error>) + } + + fn create_iterator_type(r#type: Type) -> Type { + parse_quote!(impl Iterator) + } + + pub fn return_type(&self) -> Result { + Ok(match self { + Self::Element { + kind, + constraint, + variadic_kind, + .. + } => { + let base_type: Type = match kind { + ElementKind::Operand => { + parse_quote!(::melior::ir::Value<'c, '_>) + } + ElementKind::Result => { + parse_quote!(::melior::ir::operation::OperationResult<'c, '_>) + } + }; + if !constraint.is_variadic() { + Self::create_result_type(base_type) + } else if let VariadicKind::AttrSized {} = variadic_kind { + Self::create_result_type(Self::create_iterator_type(base_type)) + } else { + Self::create_iterator_type(base_type) + } + } + Self::Attribute { constraint } => { + if constraint.is_unit()? { + parse_quote!(bool) + } else { + Self::create_result_type(self.parameter_type()?) + } + } + Self::Successor { constraint, .. } => { + let r#type: Type = parse_quote!(::melior::ir::BlockRef<'c, '_>); + if constraint.is_variadic() { + Self::create_iterator_type(r#type) + } else { + Self::create_result_type(r#type) + } + } + Self::Region { constraint, .. } => { + let r#type: Type = parse_quote!(::melior::ir::RegionRef<'c, '_>); + if constraint.is_variadic() { + Self::create_iterator_type(r#type) + } else { + Self::create_result_type(r#type) + } + } + }) + } +} diff --git a/macro/src/dialect/operation/operation_field.rs b/macro/src/dialect/operation/operation_field.rs new file mode 100644 index 0000000000..1977823b79 --- /dev/null +++ b/macro/src/dialect/operation/operation_field.rs @@ -0,0 +1,77 @@ +use super::{element_kind::ElementKind, field_kind::FieldKind, SequenceInfo, VariadicKind}; +use crate::dialect::{ + error::Error, + types::{AttributeConstraint, RegionConstraint, SuccessorConstraint, TypeConstraint}, + utility::sanitize_snake_case_name, +}; +use proc_macro2::Ident; + +#[derive(Debug, Clone)] +pub struct OperationField<'a> { + pub(crate) name: &'a str, + pub(crate) sanitized_name: Ident, + pub(crate) kind: FieldKind<'a>, +} + +impl<'a> OperationField<'a> { + fn new(name: &'a str, kind: FieldKind<'a>) -> Result { + Ok(Self { + name, + sanitized_name: sanitize_snake_case_name(name)?, + kind, + }) + } + + pub fn new_attribute( + name: &'a str, + constraint: AttributeConstraint<'a>, + ) -> Result { + Self::new(name, FieldKind::Attribute { constraint }) + } + + pub fn new_region( + name: &'a str, + constraint: RegionConstraint<'a>, + sequence_info: SequenceInfo, + ) -> Result { + Self::new( + name, + FieldKind::Region { + constraint, + sequence_info, + }, + ) + } + + pub fn new_successor( + name: &'a str, + constraint: SuccessorConstraint<'a>, + sequence_info: SequenceInfo, + ) -> Result { + Self::new( + name, + FieldKind::Successor { + constraint, + sequence_info, + }, + ) + } + + pub fn new_element( + name: &'a str, + constraint: TypeConstraint<'a>, + kind: ElementKind, + sequence_info: SequenceInfo, + variadic_kind: VariadicKind, + ) -> Result { + Self::new( + name, + FieldKind::Element { + kind, + constraint, + sequence_info, + variadic_kind, + }, + ) + } +}