Skip to content

Instantly share code, notes, and snippets.

@cgswords
Last active July 28, 2016 23:49
Show Gist options
  • Save cgswords/e2dc7cbdc199eaee65698f47a05e8779 to your computer and use it in GitHub Desktop.
Save cgswords/e2dc7cbdc199eaee65698f47a05e8779 to your computer and use it in GitHub Desktop.
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("cond", cond);
}
fn cond<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<base::MacResult + 'cx> {
let output = cond_rec(TokenStream::from_tts(tts.clone().to_owned()));
build_emitter(cx, sp, output)
}
fn cond_rec(input: TokenStream) -> TokenStream {
if input.is_empty() { return lex("TokenStream::mk_empty()"); }
let next = input.slice(0..1);
let rest = input.slice_from(1..);
let clause : TokenStream = match next.maybe_delimited() {
Some(ts) => ts,
_ => panic!("Invalid input"),
};
if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) } // clause is ([test]) [rhs]
let test: TokenStream = clause.slice(0..1);
let rhs: TokenStream = clause.slice_from(1..);
if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
build_brace_delim(rhs)
} else {
concat(as_ts(vec![str_to_keyword("if")]),
concat(test,
concat(build_brace_delim(rhs),
concat(as_ts(vec![str_to_keyword("else")]),
build_brace_delim(concat(as_ts(vec![str_to_ident("cond"), Token::Not]),
build_paren_delim(rest)))))))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment