Skip to main content

pliron_derive/
lib.rs

1mod derive_attr;
2mod derive_entity;
3mod derive_format;
4mod derive_op;
5mod derive_type;
6mod interfaces;
7mod irfmt;
8mod verify_succ;
9
10use proc_macro::TokenStream;
11use syn::parse_quote;
12
13use derive_format::DeriveIRObject;
14
15/// `#[def_attribute(...)]`: Annotate a Rust struct as a new IR attribute.
16///
17/// *Note*: It is suggested to use the [pliron_attr] macro instead of using this macro directly.
18///         The documention here is useful though, because [pliron_attr]'s `name` field expands
19///         to this macro.
20///
21/// The argument to the macro is the fully qualified name of the attribute in the form of
22/// `"dialect.attribute_name"`.
23///
24/// The macro will leave the struct definition unchanged, but it will generate an implementation of
25/// the pliron::Attribute trait and implements other internal traits and types resources required
26/// to use the IR attribute.
27///
28/// **Note**: pre-requisite traits for `Attribute` must already be implemented.
29///         Additionaly, [Eq] and [Hash](core::hash::Hash) must be implemented by the type.
30///
31/// Usage:
32///
33/// ```
34/// use pliron::derive::{def_attribute, format_attribute, verify_succ};
35///
36/// #[verify_succ]
37/// #[def_attribute("my_dialect.attribute")]
38/// #[format_attribute]
39/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
40/// pub struct StringAttr(String);
41/// # use pliron::{printable::{State, Printable}, context::Context};
42/// ```
43#[proc_macro_attribute]
44pub fn def_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
45    to_token_stream(derive_attr::def_attribute(args, input))
46}
47
48/// `#[def_type(...)]`: Annotate a Rust struct as a new IR type.
49///
50/// *Note*: It is suggested to use the [pliron_type] macro instead of using this macro directly.
51///         The documention here is useful though, because [pliron_type]'s `name` field expands
52///         to this macro.
53///
54/// The argument to the macro is the fully qualified name of the type in the form of
55/// `"dialect.type_name"`.
56///
57/// The macro will leave the struct definition unchanged, but it will generate an implementation of
58/// the pliron::Type trait and implements other internal traits and types resources required
59/// to use the IR type.
60///
61/// **Note**: pre-requisite traits for `Type` must already be implemented.
62///         Additionaly, [Hash](core::hash::Hash) and [Eq] must be implemented by the rust type.
63///
64/// Usage:
65///
66/// ```
67/// use pliron::derive::{def_type, format_type, verify_succ};
68/// #[verify_succ]
69/// #[def_type("my_dialect.unit")]
70/// #[format_type]
71/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
72/// pub struct UnitType;
73/// ```
74#[proc_macro_attribute]
75pub fn def_type(args: TokenStream, input: TokenStream) -> TokenStream {
76    to_token_stream(derive_type::def_type(args, input))
77}
78
79/// Derive get methods for types that retrieve interned types.
80///
81/// *Note*: It is suggested to use the [pliron_type] macro instead of using this macro directly.
82///         The documention here is useful though, because [pliron_type]'s `generate_get` field
83///         expands to this macro.
84///
85/// This macro generates appropriate get methods based on the struct's fields:
86/// - For unit structs: generates a singleton `get(ctx: &Context)` method
87/// - For structs with fields (named or tuple): generates a `get(ctx: &mut Context, ...)` method
88///
89/// ## Examples
90///
91/// ### Named fields struct:
92/// ```
93/// use pliron::derive::{def_type, derive_type_get, format_type, verify_succ};
94/// use pliron::context::Context;
95///
96/// #[verify_succ]
97/// #[def_type("my_dialect.vector_type")]
98/// #[format_type]
99/// #[derive_type_get]  // Auto-generates get method
100/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
101/// pub struct VectorType {
102///     elem_ty: u32,
103///     num_elems: u32,
104/// }
105///
106/// // Usage of the auto-generated get method:
107/// # fn example(ctx: &mut Context) {
108/// let vector_type = VectorType::get(ctx, 42, 8); // get(ctx, elem_ty, num_elems)
109/// # }
110/// ```
111///
112/// ### Tuple struct:
113/// ```
114/// use pliron::derive::{def_type, derive_type_get, format_type, verify_succ};
115/// use pliron::context::Context;
116///
117/// #[verify_succ]
118/// #[def_type("my_dialect.tuple_type")]
119/// #[format_type]
120/// #[derive_type_get]  // Auto-generates get method
121/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
122/// pub struct TupleType(u32, String, bool);
123///
124/// // Usage of the auto-generated get method:
125/// # fn example(ctx: &mut Context) {
126/// let tuple_type = TupleType::get(ctx, 42, "hello".to_string(), true); // get(ctx, field_0, field_1, field_2)
127/// # }
128/// ```
129///
130/// ### Unit struct:
131/// ```
132/// use pliron::derive::{def_type, derive_type_get, format_type, verify_succ};
133/// use pliron::context::Context;
134///
135/// #[verify_succ]
136/// #[def_type("my_dialect.unit_type")]
137/// #[format_type]
138/// #[derive_type_get]  // Auto-generates singleton get method
139/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
140/// pub struct UnitType;
141///
142/// // Usage of the auto-generated singleton get method:
143/// # fn example(ctx: &Context) {
144/// let unit_type = UnitType::get(ctx); // get(ctx) - no additional parameters
145/// # }
146/// ```
147#[proc_macro_attribute]
148pub fn derive_type_get(args: TokenStream, input: TokenStream) -> TokenStream {
149    to_token_stream(derive_type::derive_type_get(args, input))
150}
151
152/// `#[verify_succ]`: Implement [Verify](../pliron/common_traits/trait.Verify.html)
153/// for a Rust struct or enum with a verifier that always succeeds.
154///
155/// This leaves the original item unchanged and adds:
156/// `impl Verify for T { fn verify(...) -> Result<()> { Ok(()) } }`.
157///
158/// Usage:
159///
160/// ```
161/// use pliron::derive::verify_succ;
162/// use pliron::{common_traits::Verify, context::Context};
163///
164/// #[verify_succ]
165/// struct AlwaysValid;
166///
167/// let ctx = Context::new();
168/// assert!(AlwaysValid.verify(&ctx).is_ok());
169/// ```
170#[proc_macro_attribute]
171pub fn verify_succ(args: TokenStream, input: TokenStream) -> TokenStream {
172    to_token_stream(verify_succ::verify_succ_impl(args.into(), input.into()))
173}
174
175/// `#[def_op(...)]`: Create a new IR operation.
176///
177/// *Note*: It is suggested to use the [pliron_op] macro instead of using this macro directly.
178///         The documention here is useful though, because [pliron_op]'s `name` field expands
179///         to this macro.
180///
181/// The argument to the macro is the fully qualified name of the operation in the form of
182/// `"dialect.op_name"`.
183///
184/// The macro assumes an empty struct and will add the `op: Ptr<Operation>` field used to access
185/// the underlying Operation in the context.
186///
187/// The macro will automatically derive the `Clone`, `Copy`, `Hash`, `PartialEq` and `Eq` traits
188/// for the new struct definition.
189///
190/// **Note**: pre-requisite traits for `Op` (Printable, Verify etc) must already be implemented
191///
192/// Usage:
193///
194/// ```
195/// use pliron::derive::{def_op, format_op, verify_succ};
196///
197/// #[verify_succ]
198/// #[def_op("my_dialect.op")]
199/// #[format_op]
200/// pub struct MyOp;
201/// ```
202/// The example will create a struct definition equivalent to:
203///
204/// ```
205/// #[derive(Clone, Copy, PartialEq, Eq, Hash)]
206/// pub struct MyOp {
207///   op: Ptr<Operation>,
208/// }
209/// # use pliron::{context::Ptr, operation::Operation};
210/// ```
211#[proc_macro_attribute]
212pub fn def_op(args: TokenStream, input: TokenStream) -> TokenStream {
213    to_token_stream(derive_op::def_op(args, input))
214}
215
216/// Derive getter and setters for operation attributes listed as arguments.
217///
218/// *Note*: It is suggested to use the [pliron_op] macro instead of using this macro directly.
219///         The documention here is useful though, because [pliron_op]'s `attributes` field
220///         expands to this macro.
221///
222/// The arguments are a comma separated list of attribute names
223/// (which must be an [Identifier](../pliron/identifier/struct.Identifier.html)),
224/// each of which may have an optional concrete Rust type specified,
225/// denoting the [Attribute](../pliron/attribute/trait.Attribute.html)'s concrete type.
226///
227/// ```
228/// # use pliron::derive::{def_op, derive_attr_get_set, format_op, verify_succ};
229/// // A test for the `derive_attr_get_set` macro.
230/// #[verify_succ]
231/// #[def_op("llvm.with_attrs")]
232/// #[format_op]
233/// #[derive_attr_get_set(name1_any_attr, name2_ty_attr : pliron::builtin::attributes::TypeAttr)]
234/// pub struct WithAttrsOp {}
235/// ```
236///
237/// This expands to add the following getter / setter items:
238/// ```Rust
239/// # use pliron::derive::{def_op, format_op, derive_attr_get_set};
240/// # use std::cell::Ref;
241/// # use pliron::dict_key;
242/// # use pliron::{attribute::AttrObj, context::Context};
243/// # use pliron::{builtin::attributes::TypeAttr};
244/// # use pliron::derive::verify_succ;
245/// # #[verify_succ]
246/// #[format_op]
247/// #[def_op("llvm.with_attrs")]
248/// pub struct WithAttrsOp {}
249/// dict_key!(ATTR_KEY_NAME1_ANY_ATTR, "name1_any_attr");
250/// dict_key!(ATTR_KEY_NAME2_TY_ATTR, "name2_ty_attr");
251/// impl WithAttrsOp {
252///   pub fn get_attr_name1_any_attr<'a>
253///     (&self, ctx: &'a Context)-> Option<Ref<'a, AttrObj>> { todo!() }
254///   pub fn set_attr_name1_any_attr(&self, ctx: &Context, value: AttrObj) { todo!() }
255///   pub fn get_attr_name2_ty_attr<'a>
256///     (&self, ctx: &'a Context) -> Option<Ref<'a, TypeAttr>> { todo!() }
257///   pub fn set_attr_name2_ty_attr(&self, ctx: &Context, value: TypeAttr) { todo!() }
258/// }
259/// ```
260#[proc_macro_attribute]
261pub fn derive_attr_get_set(args: TokenStream, input: TokenStream) -> TokenStream {
262    to_token_stream(derive_op::derive_attr_get_set(args, input))
263}
264
265/// Derive [Printable](../pliron/printable/trait.Printable.html) and
266/// [Parsable](../pliron/parsable/trait.Parsable.html) for Rust types.
267/// Use this is for types other than `Op`, `Type` and `Attribute`s.
268///   1. A named variable `$name` specifies a named struct field.
269///   2. An unnamed variable `$i` specifies the i'th field of a tuple struct.
270///
271/// Struct (or tuple) fields that are either [Option] or [Vec] (or an array) must to be specified
272/// using the `opt` and `vec` directives respectively. The `opt` directive takes one argument,
273/// a variable specifying the field name with type `Option`. The `vec` directive takes two
274/// arguments, the first is a variable specifying the field name with type `Vec` (or array)
275/// and the second is another directive to specify a
276/// [ListSeparator](../pliron/printable/enum.ListSeparator.html).
277///
278/// The following directives are supported:
279///   1. `NewLine`: takes no argument, and specifies a newline to be used as list separator.
280///   2. ``CharNewline(`c`)``: takes a single character argument that will be followed by a newline.
281///   3. ``Char(`c`)``: takes a single character argument that will be used as separator.
282///   4. ``CharSpace(`c`)``: takes a single character argument that will be followed by a space.
283///
284/// Generic structs and enums are supported. The macro preserves generic parameters on the
285/// generated `Printable` and `Parsable` impls, but it does not synthesize trait bounds.
286/// Any generic field that is parsed or printed through the format must therefore carry explicit
287/// bounds on the type itself. In practice, this usually means a bound like
288/// `T: Printable + Parsable<Arg = (), Parsed = T>`.
289///
290/// Examples:
291/// 1. Derive for a struct, with no format string (default format):
292///    (Note that the field u64 has both `Printable` and `Parsable` implemented).
293/// ```
294/// use pliron::derive::format;
295/// #[format]
296/// struct IntWrapper {
297///    inner: u64,
298/// }
299/// ```
300/// 2. An example with a custom format string:
301/// ```
302/// use pliron::derive::format;
303/// #[format("`BubbleWrap` `[` $inner `]`")]
304/// struct IntWrapperCustom {
305///   inner: u64,
306/// }
307/// ```
308/// 3. An example for an enum (custom format strings are allowed for the variants only).
309/// ```
310/// use pliron::derive::format;
311/// use pliron::{builtin::types::IntegerType, r#type::TypePtr};
312/// #[format]
313/// enum Enum {
314///     A(TypePtr<IntegerType>),
315///     B {
316///         one: TypePtr<IntegerType>,
317///         two: u64,
318///     },
319///     C,
320///     #[format("`<` $upper `/` $lower `>`")]
321///     Op {
322///         upper: u64,
323///         lower: u64,
324///     },
325/// }
326/// ```
327/// 4. An example with `Option` and `Vec` fields
328/// ```
329/// use pliron::derive::format;
330/// #[format("`<` opt($a) `;` vec($b, Char(`,`)) `>`")]
331/// struct OptAndVec {
332///    a: Option<u64>,
333///    b: Vec<u64>,
334///}
335/// ```
336/// 5. An example with a generic field and explicit bounds:
337/// ```
338/// use pliron::derive::format;
339/// use pliron::{parsable::Parsable, printable::Printable};
340///
341/// #[format]
342/// struct Wrapper<T>
343/// where
344///     T: Printable + Parsable<Arg = (), Parsed = T>,
345/// {
346///     value: T,
347/// }
348/// ```
349#[proc_macro_attribute]
350pub fn format(args: TokenStream, input: TokenStream) -> TokenStream {
351    to_token_stream(derive_format::derive(
352        args,
353        input,
354        DeriveIRObject::AnyOtherRustType,
355    ))
356}
357
358/// Derive [Printable](../pliron/printable/trait.Printable.html) and
359/// [Parsable](../pliron/parsable/trait.Parsable.html) for [Op](../pliron/op/trait.Op.html)s
360///
361/// *Note*: It is suggested to use the [pliron_op] macro instead of using this macro directly.
362///         The documention here is useful though, because [pliron_op]'s `format` field
363///         expands to this macro.
364///
365/// This derive only supports a syntax in which results appear before the opid:
366///   `res1, ... = opid ...`
367/// The format string specifies what comes after the opid.
368///   1. A named variable `$name` specifies a named attribute of the operation.
369///      This cannot be combined with the [attr_dict](#attr_dict) directive.
370///   2. An unnamed variable `$i` specifies `operands[i]`, except when inside some directives.
371///      This cannot be combined with the "operands" directive.
372///   3. The "type" directive specifies that a type must be parsed. It takes one argument,
373///      which is an unnamed variable `$i` with `i` specifying `result[i]`. This cannot be
374///      combined with the "types" directive.
375///   4. The "region" directive specifies that a region must be parsed. It takes one argument,
376///      which is an unnamed variable `$i` with `i` specifying `region[i]`. This cannot be
377///      combined with the "regions" directive.
378///   5. The <a name="attr"></a> "attr" directive can be used to specify attribute on an `Op` when
379///      the attribute's rust type is fixed at compile time. It takes two mandatory and two optional
380///      arguments.
381///
382///      1. The first operand is a named variable `$name` which is used as a key into the
383///         operation's attribute dictionary
384///      2. The second is the concrete rust type of the attribute. This second argument can be a
385///         named variable `$name` (with `name` being in scope) or a literal string denoting the path
386///         to a rust type (e.g. `` `::pliron::builtin::attributes::IntegerAttr` ``).
387///      3. Two additional optional arguments can be specified:
388///         * The "label" directive, with one argument, a named variable `$label`, which
389///           specifies the label to be used while printing / parsing the attribute.
390///         * The "delimiters" directive, which takes two literal arguments,
391///           specifying the opening and closing delimiters to be used while printing / parsing.
392///
393///      The advantage over specifying an attribute using the [attr](#attr) directive (as against
394///      just using a named variable) is that the attribute-id is not a part of the syntax
395///      here (because the type is statically known, allowing us to be able to parse it),
396///      thus allowing it to be more succinct. This cannot be combined with the [attr_dict](#attr_dict)
397///      directive.
398///   6. The "succ" directive specifies an operation's successor. It takes one argument,
399///      which is an unnamed variable `$i` with `i` specifying `successor[i]`.
400///   7. The "operands" directive specifies all the operands of an operation. It takes one argument
401///      which is a directive specifying the separator between operands.
402///      The following directives are supported:
403///        1. `NewLine`: takes no argument, and specifies a newline to be used as list separator.
404///        2. ``CharNewline(`c`)``: takes a single character argument that will be followed by a newline.
405///        3. ``Char(`c`)``: takes a single character argument that will be used as separator.
406///        4. ``CharSpace(`c`)``: takes a single character argument that will be followed by a space.
407///   8. The "successors" directive specifies all the successors of an operation. It takes one argument
408///      which is a directive specifying the separator between successors. The separator directive is
409///      same as that for "operands" above. This cannot be combined with the "succ" directive.
410///   9. The "regions" directive specifies all the regions of an operation. It takes one argument
411///      which is a directive specifying the separator between regions. The separator directive is same
412///      as that for "operands" above. This cannot be combined with the "region" directive.
413///  10. The <a name="attr_dict"></a> "attr_dict" directive specifies an
414///      [AttributeDict](../pliron/attribute/struct.AttributeDict.html).
415///      It cannot be combined with any of [attr](#attr), [opt_attr](#opt_attr) directives or
416///      a named variable (`$name`).
417///  11. The "types" directive specifies all the result types of an operation. It takes one argument
418///      which is a directive specifying the separator between result types. The separator directive is
419///      same as that for "operands" above. This cannot be combined with the "type" directive.
420///  12. The <a name="opt_attr"></a> "opt_attr" directive specifies an optional attribute on an `Op`.
421///      It takes two or more arguments, which are same as those of the [attr](#attr) directive.
422///      This cannot be combined with the [attr_dict](#attr_dict) directive.
423///
424/// Examples:
425/// 1. Derive for a struct, with no format string (default format):
426/// ```
427/// use pliron::derive::{def_op, format_op, verify_succ};
428/// #[verify_succ]
429/// #[format_op]
430/// #[def_op("test.myop")]
431/// struct MyOp;
432/// ```
433/// 2. An example with a custom format string:
434/// ```
435/// use pliron::derive::{def_op, derive_op_interface_impl, format_op, verify_succ};
436/// use pliron::{op::Op, builtin::op_interfaces::
437///     {OneOpdInterface, OneResultInterface, NOpdsInterface, NResultsInterface}};
438/// #[verify_succ]
439/// #[format_op("$0 `<` $attr `>` `:` type($0)")]
440/// #[def_op("test.one_result_one_operand")]
441/// #[derive_op_interface_impl
442///     (OneOpdInterface, OneResultInterface, NOpdsInterface<1>, NResultsInterface<1>)]
443/// struct OneResultOneOperandOp;
444/// ```
445/// More examples can be seen in the tests for this macro in `pliron-derive/tests/format_op.rs`.
446#[proc_macro_attribute]
447pub fn format_op(args: TokenStream, input: TokenStream) -> TokenStream {
448    to_token_stream(derive_format::derive(args, input, DeriveIRObject::Op))
449}
450
451/// Derive [Printable](../pliron/printable/trait.Printable.html) and
452/// [Parsable](../pliron/parsable/trait.Parsable.html) for
453/// [Attribute](../pliron/attribute/trait.Attribute.html)s
454///
455/// *Note*: It is suggested to use the [pliron_attr] macro instead of using this macro directly.
456///
457/// Refer to [macro@format] for the syntax specification and examples.
458#[proc_macro_attribute]
459pub fn format_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
460    to_token_stream(derive_format::derive(
461        args,
462        input,
463        DeriveIRObject::Attribute,
464    ))
465}
466
467/// Derive [Printable](../pliron/printable/trait.Printable.html) and
468/// [Parsable](../pliron/parsable/trait.Parsable.html) for
469/// [Type](../pliron/type/trait.Type.html)s
470///
471/// *Note*: It is suggested to use the [pliron_type] macro instead of using this macro directly.
472///
473/// Refer to [macro@format] for the syntax specification and examples.
474#[proc_macro_attribute]
475pub fn format_type(args: TokenStream, input: TokenStream) -> TokenStream {
476    to_token_stream(derive_format::derive(args, input, DeriveIRObject::Type))
477}
478
479pub(crate) fn to_token_stream(res: syn::Result<proc_macro2::TokenStream>) -> TokenStream {
480    let tokens = match res {
481        Ok(tokens) => tokens,
482        Err(error) => {
483            let error = error.to_compile_error();
484            quote::quote!(
485                #error
486            )
487        }
488    };
489    TokenStream::from(tokens)
490}
491
492/// Declare an [Op](../pliron/op/trait.Op.html) interface, which can be implemented
493/// by any `Op`.
494///
495/// If the interface requires any other interface to be already implemented,
496/// they can be specified super-traits.
497///
498/// When an `Op` is verified, its interfaces are also automatically verified,
499/// with guarantee that a super-interface is verified before an interface itself is.
500///
501/// Example: Here `SameOperandsAndResultType` and `SymbolOpInterface` are super interfaces
502/// for the new interface `MyOpIntr`.
503/// ```
504/// # use pliron::builtin::op_interfaces::{SameOperandsAndResultType, SymbolOpInterface};
505/// # use pliron::derive::{op_interface};
506/// # use pliron::{op::Op, context::Context, result::Result};
507///   /// MyOpIntr is my first op interface.
508///   #[op_interface]
509///   trait MyOpIntr: SameOperandsAndResultType + SymbolOpInterface {
510///       fn verify(_op: &dyn Op, _ctx: &Context) -> Result<()>
511///       where Self: Sized,
512///       {
513///           Ok(())
514///       }
515///   }
516/// ```
517#[proc_macro_attribute]
518pub fn op_interface(_attr: TokenStream, item: TokenStream) -> TokenStream {
519    let supertrait = parse_quote! { ::pliron::op::Op };
520    let verifier_type = parse_quote! { ::pliron::op::OpInterfaceVerifier };
521    let target_marker_trait = parse_quote! { ::pliron::op::OpInterfaceMarker };
522
523    to_token_stream(interfaces::interface_define(
524        item,
525        supertrait,
526        verifier_type,
527        true,
528        target_marker_trait,
529    ))
530}
531
532/// Implement [Op](../pliron/op/trait.Op.html) Interface for an Op. The interface trait must define
533/// a `verify` function with type [OpInterfaceVerifier](../pliron/op/type.OpInterfaceVerifier.html)
534///
535/// Usage:
536/// ```
537/// # use pliron::derive::{def_op, format_op, op_interface, op_interface_impl, verify_succ};
538///
539/// #[verify_succ]
540/// #[def_op("dialect.name")]
541/// #[format_op]
542/// struct MyOp;
543///
544/// #[op_interface]
545/// pub trait MyOpInterface {
546///     fn gubbi(&self);
547///     fn verify(op: &dyn Op, ctx: &Context) -> Result<()>
548///     where Self: Sized,
549///     {
550///         Ok(())
551///     }
552/// }
553///
554/// #[op_interface_impl]
555/// impl MyOpInterface for MyOp {
556///     fn gubbi(&self) { println!("gubbi"); }
557/// }
558/// # use pliron::{
559/// #     op::Op, context::Context, result::Result, common_traits::Verify
560/// # };
561/// ```
562#[proc_macro_attribute]
563pub fn op_interface_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
564    let interface_verifiers_slice = parse_quote! { ::pliron::op::OP_INTERFACE_VERIFIERS };
565    let all_verifiers_fn_type = parse_quote! { ::pliron::op::OpInterfaceAllVerifiers };
566    to_token_stream(interfaces::interface_impl(
567        item,
568        interface_verifiers_slice,
569        all_verifiers_fn_type,
570    ))
571}
572
573/// `#[pliron_type(...)]`: Unified macro for defining IR types.
574///
575/// This macro provides a simplified, unified syntax for defining IR types by expanding
576/// into the existing type definition macros. It supports the following configuration options:
577///
578/// - `name = "dialect.type_name"`: The fully qualified name of the type (required).\
579///   Expands to [def_type].
580/// - `format = "format_string"`: Custom format string for printing/parsing (optional).\
581///   Expands to [format_type].
582/// - `verifier = "succ"`: Verifier implementation, currently only "succ" is supported (optional).\
583///   Expands to [macro@verify_succ].
584/// - `generate_get = true/false`: Whether to generate a get method for the type (optional, default: false).\
585///   Expands to [derive_type_get].
586///
587/// ## Examples
588///
589/// ### Basic type definition:
590/// ```
591/// use pliron::derive::pliron_type;
592///
593/// #[pliron_type(name = "test.unit_type", format, verifier = "succ")]
594/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
595/// pub struct UnitType;
596/// ```
597///
598/// ### Type with custom format:
599/// ```
600/// use pliron::derive::pliron_type;
601///
602/// #[pliron_type(
603///     name = "test.flags_type",
604///     format = "`type` `{` $flags `}`",
605///     verifier = "succ"
606/// )]
607/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
608/// struct FlagsType {
609///     flags: u32,
610/// }
611/// ```
612///
613/// ### Type with get method generation:
614/// ```
615/// use pliron::derive::pliron_type;
616///
617/// #[pliron_type(
618///     name = "test.vector_type",
619///     generate_get = true,
620///     format,
621///     verifier = "succ"
622/// )]
623/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
624/// struct VectorType {
625///     elem_ty: u32,
626///     num_elems: u32,
627/// }
628/// ```
629#[proc_macro_attribute]
630pub fn pliron_type(args: TokenStream, input: TokenStream) -> TokenStream {
631    to_token_stream(derive_entity::pliron_type(args, input))
632}
633
634/// `#[pliron_attr(...)]`: Unified macro for defining IR attributes.
635///
636/// This macro provides a simplified, unified syntax for defining IR attributes by expanding
637/// into the existing attribute definition macros. It supports the following configuration options:
638///
639/// - `name = "dialect.attribute_name"`: The fully qualified name of the attribute (required).\
640///   Expands to [def_attribute].
641/// - `format = "format_string"`: Custom format string for printing/parsing (optional).\
642///   Expands to [format_attribute].
643/// - `verifier = "succ"`: Verifier implementation, currently only "succ" is supported (optional).\
644///   Expands to [macro@verify_succ].
645///
646/// ## Examples
647///
648/// ### Basic attribute definition:
649/// ```
650/// use pliron::derive::pliron_attr;
651///
652/// #[pliron_attr(name = "test.string_attr", format, verifier = "succ")]
653/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
654/// struct StringAttr {
655///     value: String,
656/// }
657/// ```
658///
659/// ### Attribute with custom format:
660/// ```
661/// use pliron::derive::pliron_attr;
662///
663/// #[pliron_attr(
664///     name = "test.string_attr",
665///     format = "`attr` `(` $value `)`",
666///     verifier = "succ"
667/// )]
668/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
669/// struct StringAttr {
670///     value: String,
671/// }
672/// ```
673#[proc_macro_attribute]
674pub fn pliron_attr(args: TokenStream, input: TokenStream) -> TokenStream {
675    to_token_stream(derive_entity::pliron_attr(args, input))
676}
677
678/// `#[pliron_op(...)]`: Unified macro for defining IR operations.
679///
680/// This macro provides a simplified, unified syntax for defining IR operations by expanding
681/// into the existing operation definition macros. It supports the following configuration options:
682///
683/// - `name = "dialect.op_name"`: The fully qualified name of the operation (required).\
684///   Expands to [def_op].
685/// - `format = "format_string"`: Custom format string for printing/parsing (optional).\
686///   Expands to [format_op].
687/// - `interfaces = [Interface1, Interface2, ...]`: List of interfaces to implement (optional).\
688///   Expands to [derive_op_interface_impl].
689/// - `attributes = (attr_name: AttrType, ...)`: List of attributes with their types (optional).\
690///   Expands to [derive_attr_get_set], generating getter and setter methods.
691/// - `verifier = "succ"`: Verifier implementation, currently only "succ" is supported (optional).\
692///   Expands to [macro@verify_succ].
693///
694/// ## Examples
695///
696/// ### Basic operation definition:
697/// ```
698/// use pliron::derive::pliron_op;
699///
700/// #[pliron_op(name = "test.my_op", format, verifier = "succ")]
701/// struct MyOp;
702/// ```
703///
704/// ### Operation with custom format and interfaces:
705/// ```
706/// use pliron::derive::pliron_op;
707/// use pliron::builtin::op_interfaces::NRegionsInterface;
708///
709/// #[pliron_op(
710///     name = "test.if_op",
711///     format = "`(`$0`)` region($0)",
712///     interfaces = [ NRegionsInterface<1> ],
713///     verifier = "succ"
714/// )]
715/// struct IfOp;
716/// ```
717///
718/// ### Operation with attributes:
719/// ```
720/// use pliron::derive::pliron_op;
721/// use pliron::builtin::attributes::{UnitAttr, IntegerAttr};
722///
723/// #[pliron_op(
724///     name = "dialect.test",
725///     format,
726///     attributes = (attr1: UnitAttr, attr2: IntegerAttr),
727///     verifier = "succ"
728/// )]
729/// struct CallOp;
730/// ```
731///
732/// The `attributes` parameter generates getter and setter methods for each attribute,
733/// equivalent to using `#[derive_attr_get_set(...)]`.
734#[proc_macro_attribute]
735pub fn pliron_op(args: TokenStream, input: TokenStream) -> TokenStream {
736    to_token_stream(derive_entity::pliron_op(args, input))
737}
738
739/// Derive implementation of an [Op](../pliron/op/trait.Op.html) Interface for an Op.
740/// Note that an impl can be derived only for those interfaces that do not require any
741/// methods to be defined during the impl.
742///
743/// *Note*: It is suggested to use the [pliron_op] macro instead of using this macro directly.
744///         The documention here is useful though, because [pliron_op]'s `interfaces` field
745///         expands to this macro.
746///
747/// Usage:
748/// ```
749/// # use pliron::derive::{derive_op_interface_impl, format_op, op_interface, verify_succ};
750///
751/// #[verify_succ]
752/// #[def_op("dialect.name")]
753/// #[format_op]
754/// #[derive_op_interface_impl(MyOpInterface)]
755/// struct MyOp;
756///
757/// #[op_interface]
758/// pub trait MyOpInterface {
759///     fn gubbi(&self) { println!("gubbi"); }
760///     fn verify(op: &dyn Op, ctx: &Context) -> Result<()>
761///     where Self: Sized,
762///     {
763///         Ok(())
764///     }
765/// }
766/// # use pliron::derive::def_op;
767/// # use pliron::{
768/// #     op::Op, context::Context, result::Result,
769/// #     common_traits::Verify
770/// # };
771/// ```
772#[proc_macro_attribute]
773pub fn derive_op_interface_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
774    to_token_stream(interfaces::derive_op_interface_impl(attr, item))
775}
776
777/// Declare an [Attribute](../pliron/attribute/trait.Attribute.html) interface,
778/// which can be implemented by any `Attribute`.
779///
780/// If the interface requires any other interface to be already implemented,
781/// they can be specified super-traits.
782///
783/// When an `Attribute` is verified, its interfaces are also automatically verified,
784/// with guarantee that a super-interface is verified before an interface itself is.
785///
786/// Example: Here `Super1` and `Super2` are super interfaces for the interface `MyAttrIntr`.
787/// ```
788/// # use pliron::{attribute::Attribute, context::Context, result::Result};
789/// use pliron::derive::attr_interface;
790///
791/// #[attr_interface]
792/// trait Super1 {
793///     fn verify(_attr: &dyn Attribute, _ctx: &Context) -> Result<()>
794///     where
795///         Self: Sized,
796///     {
797///         Ok(())
798///     }
799/// }
800///
801/// #[attr_interface]
802/// trait Super2 {
803///     fn verify(_attr: &dyn Attribute, _ctx: &Context) -> Result<()>
804///     where
805///         Self: Sized,
806///     {
807///         Ok(())
808///     }
809/// }
810///
811/// // MyAttrIntr is my best attribute interface.
812/// #[attr_interface]
813/// trait MyAttrIntr: Super1 + Super2 {
814///     fn verify(_attr: &dyn Attribute, _ctx: &Context) -> Result<()>
815///     where
816///         Self: Sized,
817///     {
818///         Ok(())
819///     }
820/// }
821/// ```
822#[proc_macro_attribute]
823pub fn attr_interface(_attr: TokenStream, item: TokenStream) -> TokenStream {
824    let supertrait = parse_quote! { ::pliron::attribute::Attribute };
825    let verifier_type = parse_quote! { ::pliron::attribute::AttrInterfaceVerifier };
826    let target_marker_trait = parse_quote! { ::pliron::attribute::AttrInterfaceMarker };
827
828    to_token_stream(interfaces::interface_define(
829        item,
830        supertrait,
831        verifier_type,
832        true,
833        target_marker_trait,
834    ))
835}
836
837/// Implement [Attribute](../pliron/attribute/trait.Attribute.html) Interface for an Attribute.
838/// The interface trait must define a `verify` function with type
839/// [AttrInterfaceVerifier](../pliron/attribute/type.AttrInterfaceVerifier.html).
840///
841/// Usage:
842/// ```
843/// use pliron::derive::{attr_interface, attr_interface_impl, def_attribute, format_attribute, verify_succ};
844///
845/// #[verify_succ]
846/// #[def_attribute("dialect.name")]
847/// #[format_attribute]
848/// #[derive(PartialEq, Eq, Clone, Debug, Hash)]
849/// struct MyAttr { }
850///
851///     /// My first attribute interface.
852/// #[attr_interface]
853/// trait MyAttrInterface {
854///     fn monu(&self);
855///     fn verify(attr: &dyn Attribute, ctx: &Context) -> Result<()>
856///     where Self: Sized,
857///     {
858///          Ok(())
859///     }
860/// }
861///
862/// #[attr_interface_impl]
863/// impl MyAttrInterface for MyAttr
864/// {
865///     fn monu(&self) { println!("monu"); }
866/// }
867/// # use pliron::{
868/// #     printable::{self, Printable},
869/// #     context::Context, result::Result, common_traits::Verify,
870/// #     attribute::Attribute
871/// # };
872#[proc_macro_attribute]
873pub fn attr_interface_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
874    let interface_verifiers_slice = parse_quote! { ::pliron::attribute::ATTR_INTERFACE_VERIFIERS };
875    let all_verifiers_fn_type = parse_quote! { ::pliron::attribute::AttrInterfaceAllVerifiers };
876    to_token_stream(interfaces::interface_impl(
877        item,
878        interface_verifiers_slice,
879        all_verifiers_fn_type,
880    ))
881}
882
883/// Declare a [Type](../pliron/type/trait.Type.html) interface,
884/// which can be implemented by any `Type`.
885///
886/// If the interface requires any other interface to be already implemented,
887/// they can be specified super-traits.
888///
889/// When an `Attribute` is verified, its interfaces are also automatically verified,
890/// with guarantee that a super-interface is verified before an interface itself is.
891///
892/// Example: Here `Super1` and `Super2` are super interfaces for the interface `MyTypeIntr`.
893/// ```
894/// use pliron::derive::type_interface;
895/// # use pliron::{r#type::Type, context::Context, result::Result};
896/// #[type_interface]
897/// trait Super1 {
898///     fn verify(_type: &dyn Type, _ctx: &Context) -> Result<()>
899///     where
900///         Self: Sized,
901///     {
902///         Ok(())
903///     }
904/// }
905///
906/// #[type_interface]
907/// trait Super2 {
908///     fn verify(_type: &dyn Type, _ctx: &Context) -> Result<()>
909///     where
910///         Self: Sized,
911///     {
912///         Ok(())
913///     }
914/// }
915///
916/// #[type_interface]
917/// // MyTypeIntr is my best type interface.
918/// trait MyTypeIntr: Super1 + Super2 {
919///     fn verify(_type: &dyn Type, _ctx: &Context) -> Result<()>
920///     where
921///         Self: Sized,
922///     {
923///         Ok(())
924///     }
925/// }
926/// ```
927#[proc_macro_attribute]
928pub fn type_interface(_attr: TokenStream, item: TokenStream) -> TokenStream {
929    let supertrait = parse_quote! { ::pliron::r#type::Type };
930    let verifier_type = parse_quote! { ::pliron::r#type::TypeInterfaceVerifier };
931    let target_marker_trait = parse_quote! { ::pliron::r#type::TypeInterfaceMarker };
932
933    to_token_stream(interfaces::interface_define(
934        item,
935        supertrait,
936        verifier_type,
937        false,
938        target_marker_trait,
939    ))
940}
941
942/// Implement [Type](../pliron/type/trait.Type.html) Interface for a Type.
943/// The interface trait must define a `verify` function with type
944/// [TypeInterfaceVerifier](../pliron/type/type.TypeInterfaceVerifier.html).
945///
946/// Usage:
947/// ```
948/// use pliron::derive::{def_type, format_type, type_interface, type_interface_impl, verify_succ};
949///
950/// #[verify_succ]
951/// #[def_type("dialect.name")]
952/// #[format_type]
953/// #[derive(PartialEq, Eq, Clone, Debug, Hash)]
954/// struct MyType { }
955///
956/// #[type_interface]
957/// /// My first type interface.
958/// trait MyTypeInterface {
959///     fn monu(&self);
960///     fn verify(r#type: &dyn Type, ctx: &Context) -> Result<()>
961///     where Self: Sized,
962///     {
963///          Ok(())
964///     }
965/// }
966///
967/// #[type_interface_impl]
968/// impl MyTypeInterface for MyType
969/// {
970///     fn monu(&self) { println!("monu"); }
971/// }
972/// # use pliron::{
973/// #     printable::{self, Printable},
974/// #     context::Context, result::Result, common_traits::Verify,
975/// #     r#type::Type
976/// # };
977#[proc_macro_attribute]
978pub fn type_interface_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
979    let interface_verifiers_slice = parse_quote! { ::pliron::r#type::TYPE_INTERFACE_VERIFIERS };
980    let all_verifiers_fn_type = parse_quote! { ::pliron::r#type::TypeInterfaceAllVerifiers };
981    to_token_stream(interfaces::interface_impl(
982        item,
983        interface_verifiers_slice,
984        all_verifiers_fn_type,
985    ))
986}