2

我正在尝试制作一个宏来定义一些代表汇编指令的枚举变体。

现在,我有以下工作正常。这是非常无用的,但最终我将添加一些自动派生的方法,以便稍后有目的:

macro_rules! define_instructions {
    ($($inames:tt),+ $(,)*) => {
        #[derive(Debug)]
        pub enum Instruction {
            $($inames),*
        }
    };
}

define_instructions! {
    PsqLux,
    PsqLx,
    Twi,
}

fn main() {}

问题是我要添加的大多数(但不是全部)变体都需要有关联的值:

define_instructions! {
    PsqLux(u32, u32, u32, u32, u32),
    PsqLx(u32, u32, u32, u32, u32),
    Twi(u32, u32, u32),
    SomethingWithoutAVariant,
}

我尝试使用它来允许变体具有关联值(它实际上还不支持关联值,这只是一个开始):

macro_rules! define_instructions {
    (@define) => {};

    (@define $iname:ident) => {
        $iname,
    };

    (@define $iname:ident $($inames:tt)*) => {
        $iname,
        define_instructions! { @define $($inames)* }
    };

    ($($inames:tt),+ $(,)*) => {
        #[derive(Debug)]
        pub enum Instruction {
            define_instructions! { @define $($inames)* }
        }
    };
}

define_instructions! {
    PsqLux,
    PsqLx,
    Twi,
}

该代码给了我这个错误:

error: expected one of `(`, `,`, `=`, `{`, or `}`, found `!`
  --> src/main.rs:17:32
   |
17 |               define_instructions! { @define $($inames)* }
   |                                  ^ expected one of `(`, `,`, `=`, `{`, or `}` here
...
22 | / define_instructions! {
23 | |     PsqLux,
24 | |     PsqLx,
25 | |     Twi,
26 | | }
   | |_- in this macro invocation

好像我不能在enum定义中使用宏。假设这是真的,我该如何解决这个问题并能够生成可能包含或不包含关联值的枚举变体?

注意:我确定我添加的规则有问题,但我至少希望能够达到我可以调用它们的地步,这样我就可以让它们工作。

编辑

mcarton 解释了另一种方法来做我想做的事情,目前这很有帮助。

但是我仍然想知道如何在枚举定义中使用宏,因为将来我可以像这样编写宏:

define_instructions! {
    /// Name: Trap Word Immediate
    /// Simplified Mnemonics:
    /// twgti rA, value = twi 8, _rA, _value
    /// twllei rA, value = twi 6, _rA, _value
    twi TO, rA, SIMM;

    // and so on...  
}

// That macro would become

pub enum Instruction {
    /// Name: Trap Word Immediate
    /// Usage: twi TO, rA, SIMM
    /// Simplified Mnemonics:
    /// twi 8, rA, value = twgti rA, value
    /// twllei rA, value = twi 6, rA, value
    Twi(u32, u32, u32, u32, u32),
}

所以我有解决方法,但我仍然很好奇是否可以在enum定义中使用宏。这是可能的,如果不是,为什么不呢?

4

0 回答 0