How can I use a macro to generate enum variants th

2019-07-20 18:02发布

I'm trying to make a macro to define some enum variants that represent assembler instructions.

Right now, I have the following which works fine. This is pretty useless, but eventually I'm going to add some automatically derived methods so it'll have a purpose later on:

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

define_instructions! {
    PsqLux,
    PsqLx,
    Twi,
}

fn main() {}

The problem is that most (but not all) of the variants I'll be adding will need to have associated values:

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

I tried using this to allow for the variants to have associated values (it doesn't actually support associated values yet, it's just a start):

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,
}

That code gave me this error:

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

It's seems like I can't use macros inside of an enum definition. Assuming that's true, how could I work around this and be able to generate enum variants that may or may not contain associated values?

Note: I'm sure there's something wrong with the rules I added, but I'd at least like to be able to get to the point where I can call them, so I can get them working.

Edit

mcarton explained another way to do what I'm trying to do, and that's helpful at the moment.

However I'd still like to know how to use a macro inside a enum definition, because in the future I'd be able to like to write macros like this:

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),
}

So I have the workaround, but I'm still curious if it's possible to use macros inside of an enum definition. Is that possible, and if not why isn't it?

0条回答
登录 后发表回答