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 pile
  • swap échange les deux premiers éléments au sommet de la pile
  • sub soustrait le deuxième élément depuis le sommet à l'élément au sommet de la pile
  • div divise le sommet de la pile par le deuxième élément depuis le sommet
  1. 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.