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