Created
August 11, 2014 18:37
-
-
Save zokier/6669cc2236c4a56cf70d to your computer and use it in GitHub Desktop.
Rust bitlevel pattern matching
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(plugin_registrar)] | |
extern crate syntax; | |
extern crate rustc; | |
use syntax::ast; | |
use syntax::codemap::Span; | |
use syntax::ext::base; | |
use syntax::ext::base::{ExtCtxt, MacExpr}; | |
use syntax::ext::build::AstBuilder; | |
use syntax::parse::token; | |
use rustc::plugin::Registry; | |
#[plugin_registrar] | |
pub fn plugin_registrar(reg: &mut Registry) { | |
reg.register_macro("bitmatch", expand_bitmatch); | |
} | |
pub fn expand_bitmatch(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) | |
-> Box<base::MacResult> { | |
// ----- PARSE TOKEN TREE ----- | |
let p = &mut cx.new_parser_from_tts(tts); | |
let var_ident = p.parse_ident(); | |
p.expect(&token::COMMA); | |
// whats this style thing | |
let (pattern_str, _pattern_str_style) = p.parse_str(); | |
if p.token != token::EOF { | |
p.unexpected(); | |
} | |
let pattern_str = pattern_str.get(); //huh? | |
// ----- END OF TOKEN TREE PARSING ----- | |
// ----- PARSE PATTERN ----- | |
let (mut mask, mut check) = (0u8, 0u8); | |
match pattern_str.len() { | |
8 => {}, | |
len => { | |
cx.span_err(sp, format!("invalid length for bitmatch: {}", len).as_slice()); | |
return base::DummyResult::expr(sp); | |
} | |
} | |
for (i, ch) in pattern_str.chars().rev().enumerate() { | |
match ch { | |
'0' => {mask |= 1 << i;}, | |
'1' => {check |= 1 << i; mask |= 1 << i;}, | |
'x' => {}, | |
ch => { cx.span_err(sp, format!("invalid character in bitmatch: '{}' (pos: {})", ch, i).as_slice()); return base::DummyResult::expr(sp); } | |
} | |
} | |
// ----- END OF PATTERN PARSING ----- | |
// cx.span_note(sp, format!("bitmatch: mask: {:02x}, check: {:02x}", mask, check).as_slice()); | |
// ----- BUILD AST ----- | |
return MacExpr::new( | |
cx.expr_binary( | |
sp, | |
ast::BiEq, | |
cx.expr_binary( | |
sp, | |
ast::BiBitAnd, | |
cx.expr_ident( | |
sp, | |
var_ident | |
), | |
cx.expr_u8( | |
sp, | |
mask | |
) | |
), | |
cx.expr_u8( | |
sp, | |
check | |
) | |
) | |
); | |
// ----- END OF AST BUILDING ----- | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(phase)] | |
#[phase(plugin)] | |
extern crate bitmatch; | |
fn main() { | |
let x: u8 = 0xAB; | |
match x { | |
x if bitmatch!(x, "0xxxx11x") => println!("well this is embarrasing"), | |
x if bitmatch!(x, "x0x0xx11") => println!("everything is a-ok!"), | |
_ => println!("something is amiss") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment