Как я могу использовать макрос для генерации перечислимых вариантов, которые могут содержать или не содержать связанные значения? - PullRequest
0 голосов
/ 25 августа 2018

Я пытаюсь создать макрос для определения некоторых вариантов enum, представляющих инструкции на ассемблере.

Прямо сейчас у меня есть следующее, которое отлично работает. Это довольно бесполезно, но в конце концов я собираюсь добавить некоторые автоматически производные методы, чтобы потом иметь цель:

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. Предполагая, что это правда, как я могу обойти это и быть в состоянии генерировать варианты перечисления, которые могут содержать или не содержать связанные значения?

Примечание : Я уверен, что что-то не так с добавленными мною правилами, но я бы по крайней мере хотел бы иметь возможность добраться до точки, где я могу их вызвать, чтобы я мог их получить рабочий.

Редактировать

Маккартон объяснил еще один способ сделать то, что я пытаюсь сделать, и это полезно на данный момент.

Однако я все еще хотел бы знать, как использовать макрос внутри определения enum, потому что в будущем я смогу написать макрос следующим образом:

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. Возможно ли это, а если нет, то почему?

...