Skip to content

Instantly share code, notes, and snippets.

@jinschoi
Created December 18, 2024 18:16
Show Gist options
  • Save jinschoi/8eb84a95bd136e4f7119456bb0fc572a to your computer and use it in GitHub Desktop.
Save jinschoi/8eb84a95bd136e4f7119456bb0fc572a to your computer and use it in GitHub Desktop.
Rust proc macro for Advent of Code 2024 day 17
use proc_macro::TokenStream;
use std::fs;
use syn::{parse_macro_input, LitStr};
fn combo(opr: u8) -> String {
match opr {
0..=3 => opr.to_string(),
4 => "a".to_string(),
5 => "b".to_string(),
6 => "c".to_string(),
_ => unreachable!(),
}
}
#[proc_macro]
pub fn comp(input: TokenStream) -> TokenStream {
let filename = parse_macro_input!(input as LitStr);
let filename_str = filename.value();
let s = match fs::read_to_string(&filename_str) {
Ok(contents) => contents,
Err(e) => {
return syn::Error::new(
filename.span(),
format!("Failed to read file {}: {}", filename_str, e),
)
.to_compile_error()
.into()
}
};
let mut res =
"fn comp(mut a: usize, mut b: usize, mut c: usize) -> Vec<u8> {\nlet mut res = vec![];\n"
.to_string();
let prog = s
.lines()
.take(5)
.last()
.unwrap()
.split_once(": ")
.unwrap()
.1
.split(',')
.map(|s| s.parse::<u8>().unwrap())
.collect::<Vec<_>>();
// Find any jnz arguments
let jump_inds = prog
.chunks_exact(2)
.filter_map(|c| {
if c[0] == 3 {
Some(c[1] as usize / 2)
} else {
None
}
})
.collect::<Vec<_>>();
for (i, chunk) in prog.chunks_exact(2).enumerate() {
let (opc, opr) = (chunk[0], chunk[1]);
if jump_inds.contains(&i) {
res.push_str("loop {\n");
}
match opc {
0 => res.push_str(&format!("a /= (1 << {} as usize);\n", combo(opr))),
1 => res.push_str(&format!("b ^= {};\n", opr)),
2 => res.push_str(&format!("b = {} & 0x7;\n", combo(opr))),
3 => res.push_str("if a == 0 { break; }\n}\n"),
4 => res.push_str("b ^= c;\n"),
5 => res.push_str(&format!("res.push(({} & 0x7) as u8);\n", combo(opr))),
6 => res.push_str(&format!("b = a / (1 << {} as usize);\n", combo(opr))),
7 => res.push_str(&format!("c = a / (1 << {} as usize);\n", combo(opr))),
_ => unreachable!(),
}
}
res.push_str("res\n}\n");
res.parse().unwrap()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment