Mam następujący kod makra, który próbuję debugować. Zrobiłem to z Rust Book w dziale "Głęboki koniec". Zmieniono nazwy zmiennych w makrze, aby dokładniej śledzić wpis this.Jak mogę debugować makra?
Moim celem jest, aby program wydrukował każdą linię programu BCT. Mam świadomość, że jest to bardzo ciężki kompilator.
Jedyny błąd rustc daje mi to:
[email protected]:~/rust/macros$ rustc --pretty expanded src/main.rs -Z unstable-options > src/main.precomp.rs
src/main.rs:151:34: 151:35 error: no rules expected the token `0`
src/main.rs:151 bct!(0, 1, 1, 1, 0, 0, 0; 1, 0);
Jakie kroki mogę podjąć, aby dowiedzieć gdzie w makro problem jest pochodzących z?
Oto mój kod:
fn main() {
{
// "Bitwise Cyclic Tag" automation through macros
macro_rules! bct {
// cmd 0: 0 ... => ...
(0, $($program:tt),* ; $_head:tt)
=> (bct_p!($($program),*, 0 ;));
(0, $($program:tt),* ; $_head:tt, $($tail:tt),*)
=> (bct_p!($($program),*, 0 ; $($tail),*));
// cmd 1x: 1 ... => 1 ... x
(1, $x:tt, $($program:tt),* ; 1)
=> (bct_p!($($program),*, 1, $x ; 1, $x));
(1, $x:tt, $($program:tt),* ; 1, $($tail:tt),*)
=> (bct_p!($($program),*, 1, $x ; 1, $($tail),*, $x));
// cmd 1x: 0 ... => 0 ...
(1, $x:tt, $($program:tt),* ; $($tail:tt),*)
=> (bct_p!($($program),*, 1, $x ; $($tail),*));
// halt on empty data string
($($program:tt),* ;)
=> (());
}
macro_rules! print_bct {
($x:tt ;)
=> (print!("{}", stringify!($x)));
(; $d:tt)
=> (print!("{}", stringify!($d)));
($x:tt, $($program:tt),* ;)
=> {
print!("{}", stringify!($x));
print_bct!($program ;);
};
($x:tt, $($program:tt),* ; $($data:tt),*)
=> {
print!("{}", stringify!($x));
print_bct!($program ; $data);
};
(; $d:tt, $($data:tt),*)
=> {
print!("{}", stringify!($d));
print_bct!(; $data);
};
}
macro_rules! bct_p {
($($program:tt),* ;)
=> {
print_bct!($($program:tt),* ;);
println!("");
bct!($($program),* ;);
};
($($program:tt),* ; $(data:tt),*)
=> {
print_bct!($($program),* ; $($data),*);
println!("");
bct!($($program),* ; $($data),*);
};
}
// the compiler is going to hate me...
bct!(0, 1, 1, 1, 0, 0, 0; 1, 0);
}
Dlaczego krok kompilacji makr nie narzeka na '$ (not_al_variable), *'? W jakich sytuacjach byłoby to ważne samo? Nie zapomnij o rozszerzeniu, higieny, która jest przydatna, gdy zmienna znajdująca się poza makrem ma taką samą nazwę jak zmienna wewnątrz makra (przynajmniej tak mi to wyjaśniono). – Nashenas
Może być sens spożywać wiele kopii dokładnej rzeczy, np. można zerwać końcowe zera za pomocą '$ (0), *' które będzie pasowało tylko '0, 0, 0' (itd.). To powiedziawszy, wydaje się stosunkowo rzadkie, że byłoby to bardzo przydatne. – huon