Token Trees in Macros (Processing Argument Lists)

Currently, the only way to add extension methods to a type in another module (even if that module is in a submodule) is to define a new trait and implement it for the type. This is very cumbersome, however, as the number of methods gets large:

trait Ops {
    fn parse_list_item(&self, current_item: ListItemInfo) 
        -> ParseResult<(Document, ListItemInfo)>;
    fn parse_list_item_content(&self) -> ParseResult<Document>;
}

impl<'a> Ops for MarkdownParser<'a> {
    fn parse_list_item(&self, current_item: ListItemInfo) 
            -> ParseResult<(Document, ListItemInfo)> {
        // ...
    }

    fn parse_list_item_content(&self) -> ParseResult<Document> {
        // ...
    }
}

      

You must write the method signature twice. If it changes, you also need to update it in several places. It also adds a lot of noise.

I though these macros would help, but I don't know how to write the correct template macro_rules!

for argument lists in functions. Here's what I have so far:

#![feature(macro_rules)]

struct Foo;

macro_rules! ops (
    ($(fn $name:ident($($args:tt)*) -> $ret:ty $body:block)+) => (
        trait Ops {
            $(fn $name($($args)*) -> $ret;)+
        }

        impl Ops for Foo {
            $(fn $name($($args)*) -> $ret $body)+
        }
    )
)

mod ops {
    ops! {
        fn method1(&self) -> int {
            10
        }

        fn method2(&self, i: int) -> () {
            println!("{}", i + self.method1());
        }
    }

    pub fn run_test() {
        Foo.method2(22);
    }
}

fn main() {
    ops::run_test();
}

      

It fails with a rather nasty message:

/tmp/rs/ops/src/main.rs:8:27: 8:31 error: expected type, found token INTERPOLATED(NtTT(ptr::P<ast::TokenTree>{ptr: box TTTok(codemap::Span{lo: codemap::BytePos(337u32), hi: codemap::BytePos(338u32), expn_id: codemap::ExpnId(4294967295u32)}, BINOP(AND))}))
/tmp/rs/ops/src/main.rs:8             $(fn $name($($args)*) -> $ret;)+
                                                    ^~~~

      

It probably deserves a bug report as the error message is quite intimidating, however I see no other way to pass the arguments as is. It seems to be related to this issue , however I hope there is a workaround, for example in this case .

Any suggestions?

+3


source to share





All Articles