use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::quote;
use std::error::Error;
pub fn generate_binary(dialect: &Ident, names: &[Ident]) -> Result<TokenStream, Box<dyn Error>> {
let mut stream = TokenStream::new();
for name in names {
let document = create_document(dialect, name);
let operation_name = create_operation_name(dialect, name);
stream.extend(TokenStream::from(quote! {
#[doc = #document]
pub fn #name<'c>(
lhs: crate::ir::Value<'c, '_>,
rhs: crate::ir::Value<'c, '_>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
binary_operator(#operation_name, lhs, rhs, location)
}
}));
}
stream.extend(TokenStream::from(quote! {
fn binary_operator<'c>(
name: &str,
lhs: crate::ir::Value<'c, '_>,
rhs: crate::ir::Value<'c, '_>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
crate::ir::operation::OperationBuilder::new( name, location)
.add_operands(&[lhs, rhs])
.enable_result_type_inference()
.build()
.expect("valid operation")
}
}));
Ok(stream)
}
pub fn generate_unary(dialect: &Ident, names: &[Ident]) -> Result<TokenStream, Box<dyn Error>> {
let mut stream = TokenStream::new();
for name in names {
let document = create_document(dialect, name);
let operation_name = create_operation_name(dialect, name);
stream.extend(TokenStream::from(quote! {
#[doc = #document]
pub fn #name<'c>(
value: crate::ir::Value<'c, '_>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
unary_operator(#operation_name, value, location)
}
}));
}
stream.extend(TokenStream::from(quote! {
fn unary_operator<'c>(
name: &str,
value: crate::ir::Value<'c, '_>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
crate::ir::operation::OperationBuilder::new( name, location)
.add_operands(&[value])
.enable_result_type_inference()
.build()
.expect("valid operation")
}
}));
Ok(stream)
}
pub fn generate_typed_unary(
dialect: &Ident,
names: &[Ident],
) -> Result<TokenStream, Box<dyn Error>> {
let mut stream = TokenStream::new();
for name in names {
let document = create_document(dialect, name);
let operation_name = create_operation_name(dialect, name);
stream.extend(TokenStream::from(quote! {
#[doc = #document]
pub fn #name<'c>(
value: crate::ir::Value<'c, '_>,
r#type: crate::ir::Type<'c>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
typed_unary_operator(#operation_name, value, r#type, location)
}
}));
}
stream.extend(TokenStream::from(quote! {
fn typed_unary_operator<'c>(
name: &str,
value: crate::ir::Value<'c, '_>,
r#type: crate::ir::Type<'c>,
location: crate::ir::Location<'c>,
) -> crate::ir::Operation<'c> {
crate::ir::operation::OperationBuilder::new( name, location)
.add_operands(&[value])
.add_results(&[r#type])
.build()
.expect("valid operation")
}
}));
Ok(stream)
}
fn create_document(dialect: &Ident, name: &Ident) -> String {
format!(
" Creates an `{}` operation.",
create_operation_name(dialect, name)
)
}
fn create_operation_name(dialect: &Ident, name: &Ident) -> String {
format!("{}.{}", dialect, name)
}