use super::{OperationElement, OperationField, VariadicKind};
use crate::dialect::{
error::Error,
r#type::Type as ElementType,
utility::{generate_iterator_type, generate_result_type, sanitize_snake_case_identifier},
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{parse_quote, Ident, Type};
#[derive(Debug)]
pub struct OperationResult<'a> {
name: &'a str,
singular_identifier: Ident,
r#type: ElementType,
variadic_kind: VariadicKind,
}
impl<'a> OperationResult<'a> {
pub fn new(
name: &'a str,
r#type: ElementType,
variadic_kind: VariadicKind,
) -> Result<Self, Error> {
Ok(Self {
name,
singular_identifier: sanitize_snake_case_identifier(name)?,
r#type,
variadic_kind,
})
}
}
impl OperationField for OperationResult<'_> {
fn name(&self) -> &str {
self.name
}
fn singular_identifier(&self) -> &Ident {
&self.singular_identifier
}
fn plural_kind_identifier(&self) -> Ident {
Ident::new("results", Span::call_site())
}
fn parameter_type(&self) -> Type {
let r#type: Type = parse_quote!(::melior::ir::Type<'c>);
if self.r#type.is_variadic() {
parse_quote! { &[#r#type] }
} else {
r#type
}
}
fn return_type(&self) -> Type {
let r#type: Type = parse_quote!(::melior::ir::operation::OperationResult<'c, '_>);
if !self.r#type.is_variadic() {
generate_result_type(r#type)
} else if self.variadic_kind == VariadicKind::AttributeSized {
generate_result_type(generate_iterator_type(r#type))
} else {
generate_iterator_type(r#type)
}
}
fn is_optional(&self) -> bool {
self.r#type.is_optional()
}
fn add_arguments(&self, name: &Ident) -> TokenStream {
if self.r#type.is_unfixed() && !self.r#type.is_optional() {
quote! { #name }
} else {
quote! { &[#name] }
}
}
}
impl OperationElement for OperationResult<'_> {
fn is_variadic(&self) -> bool {
self.r#type.is_variadic()
}
fn variadic_kind(&self) -> &VariadicKind {
&self.variadic_kind
}
}