La boucle, pour de vrai !
Jusqu'à présent, la boucle principale du programme en Forth était basée sur un hack. Ce hack consistait à réinitialiser l'IP (Instruction Pointer) à la fin du traitement. C'est un peu comme si à chaque fois qu'on avait fini le traitement, on relançait le programme depuis le début.
Il est temps d'implémenter un nouveau mot Forth : BRANCH. Ce mot, suivi dans le PFA par un offset, opère un saut inconditionnel en additionnant cet offset à l'IP courant. En choisissant un offset négatif, l'exécution va revenir en arrière et donc créer une boucle infinie.
Le pseudo code est le suivant :
(IP) -> X lit l'offset pointé par l'Instruction Pointer
L'IP ayant été positionné sur l'emplacement après le mot BRANCH
par NEXT.
IP + X -> IP ajoute l'offset à l'IP
NEXT appelle NEXT pour continuer l'exécution
Du fait du traitement de mots en 16 bits, cela donne un code assez long en 6502. Mais je crois que ce sera le cas pour toute cette aventure. Le 6502 est un processeur foncièrement 8 bits. Encore une fois, modulo ma méconnaissance de ce CPU. Je reviendrai peut-être dessus plus tard en le maîtrisant mieux. Ou on me signalera des optimisations.
Avec le mot BRANCH implémenté, la liste de mots de ma boucle principale devient :
loop_words:
.word main_loop_cfa
.word branch_cfa
.word $fffc ; -4 in little-endian to create an infinite loop
Plus besoin de reset_code dont je retire le label et le pseudo PFA. Le hack est enlevé et j'ai enfin ma boucle complète en Forth. Puisque loop_words est maintenant un (pseudo-)mot Forth complet, je lui ajoute un CFA et le bootstrap change en initialisant le registre W avec ce CFA et en appelant DOCOL.
C'est un peu plus élégant je trouve... mais cela fait perdre une place dans la pile de retour, puisque la première valeur de IP (même pas initialisée) y sera poussée par DOCOL. À voir lequel du bootstrap par IP + NEXT ou par W + DOCOL est le plus intéressant.
Moving Forth, épisode 4
C'est un tout petit article que cette quatrième partie de la série Moving Forth, tout comme ma partie d'implémentation ci-dessus.
Cette partie pose la question : comment est-ce qu'on démarre l'implémentation d'un Forth ? Cool ! Mais j'ai déjà commencé. En vrai, j'ai déjà lu plusieurs fois cette série d'articles, il n'y a donc pas de surprise et cette partie entre autres m'a guidé dans mes choix initiaux.
L'article commence par mettre sur la table deux choix d'implémentation : une implémentation en assembleur en direct sur la machine hôte, ou une implémentation par méta-compilateur, c'est-à-dire un autre Forth qui génère le code machine du Forth cible. Pas de surprise si vous avez suivi jusque-là, c'est la version assembleur que j'ai choisie. L'auteur lui, après avoir indiqué que la voie du méta-compilateur est plus complexe, préfère néanmoins celle-ci, plus portable et plus moderne (même pour 1993).
J'avais l'idée éventuellement d'avoir aussi un méta-compilateur avec lequel des programmes pourraient être écrits en Forth pour la machine cible, ici la Famicom. Mais je ne suis pas certain de l'intérêt. Ma démarche est celle d'offrir à la Famicom un parallèle Forth au Family BASIC, avec un interpréteur interactif sur la machine et son clavier. Pour créer des jeux modernes sur Famicom, il y a déjà des outils je pense plus adaptés.
Donc : Forth en assembleur ! Tout du moins son noyau.
Même si un méta-compilateur serait intéressant pour développer les mots au-delà du noyau... mmmhhhh... Bon on verra.
L'article continue en parlant de Forth en C comme d'une question qui ne peut pas ne pas se poser. Peut-être parce qu'en 1993, le C est le langage sérieux pour le développement système ? C'est un chemin que j'avais pris il y a quelques années quand je m'étais intéressé au Forth. Mais rapidement, j'étais arrivé à la conclusion que ce sont deux langages aux philosophies (et modèles) très différents, et l'implémentation faisait un peu gymnastique de contorsion.
Au final, pourquoi pas, en implémentant une machine virtuelle Forth en C, avec quelques commandes de base du noyau. Ça fait partie des choses sur lesquelles je voudrais revenir maintenant que je maîtrise mieux le Forth. Vous le sentez venir le rabbit hole ? Allez, sur la pile !
Prochain épisode
Un article très court donc. Le suivant sera plus intéressant pour la suite de l'implémentation car il traitera de ce qui forme un noyau Forth : les mots de base, les primitives, sur lequel le reste est construit.
Et je pense qu'il sera temps de faire un détour vers le passage à des mots Forth complets, avec leur entête et leur chaînage.