Mini-Forth
Nous voulons implémenter un mini-Forth avec des macros sous la forme d'un domain-specific language (ou DSL). Forth est un langage à pile basé dans notre cas sur des entiers de type i32
. Nous voulons définir une macro forth!
qui puisse exécuter des commandes séparées par des ;
, chaque commande ayant un effet sur la pile. La macro renvoie l'état de la pile sous la forme d'un vecteur, le sommet de la pile étant le dernier élément du vecteur.
Par exemple, nous voulons pouvoir écrire :
fn main() {
println!("final stack = {:?}", forth!(10; 20; add; dup; 6; mul));
}
et que cela affiche
$ cargo run
[30, 180]
Les commandes, qui ont été exécutées dans l'ordre, sont (avec l'état de la pile) :
10
ajoute l'entier 10 au sommet de la pile (vec![10]
)20
ajoute l'entier 20 au sommet de la pile (vec![10, 20]
)add
ajoute les deux éléments au sommet de la pile et les remplace par le résultat (vec![30]
)dup
duplique le sommet de la pile (vec![30, 30]
)6
ajoute l'entier 6 au sommet de la pile (vec![30, 30, 6]
)mul
multiplie les deux élément au sommet de la pile et les remplace par le résultat (vec![30, 180]
)
Les autres commandes courantes sont :
drop
efface l'élément au sommet de la pileswap
échange les deux premiers éléments au sommet de la pilesub
soustrait le deuxième élément depuis le sommet à l'élément au sommet de la pilediv
divise le sommet de la pile par le deuxième élément depuis le sommet
- Implémentez la macro
forth
et testez la.
N'oubliez pas qu'une macro peut s'appeler récursivement. Il est possible d'utiliser en interne une syntaxe spéciale pour passer en paramètre la pile sur laquelle on travaille lors d'appels récursifs de la macro.