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}