The FORTH compiler

published: 21 May 2025 / updated 21 May 2025

Lire cette page en français

 

Le compilateur FORTH

article: 15 mai 2019 / mis à jour 24 mai 2019


Le compilateur FORTH travaille en une seule passe et sans gérer de table de référence. Son rôle est d'accroître les fonctions disponibles dans le dictionnaire.

Compilation d'une définition

La compilation d'une définition ordinaire débute par le mot : (deux-points) et s'achève par le mot ; (point- virgule). Le mot : est suivi du libellé du mot à définir. Tout ce qui se trouve entre ce mot et le mot ; fait partie de la définition du mot et sera ensuite exécuté, soit directement depuis l'interpréteur, soit depuis une autre définition de mot FORTH. Pour exemple, compilons une définition que l'on nommera AFFICHE-BINAIRE et dont le rôle sera d'afficher en binaire un nombre préalablement déposé au sommet de la pile de données:

: AFFICHE-BINAIRE  ( n --- ) 
    2 BASE ! . DECIMAL ; 

Le mot : (deux-points) ouvre une séquence de compilation et est suivi du libellé du mot à définir. Le nom peut être composé de tous les caractères ASCII dont le code est compris entre 33 et 126, donc à l'exclusion de tout espace ou caractère de contrôle.

La longueur d'un mot est comprise entre 1 et 31 caractères maximum.

Le nom est suivi de la définition:

    2 BASE !   \ passage en base numérique binaire  
    .          \ affichage du nombre précédemment empilé 
    DECIMAL    \ restitution de la base numérique décimale 

La fin de la séquence de compilation est marquée par le mot ; (point-virgule). Forth revient en mode interprétation. Cette définition peut être tapée depuis le clavier ou faire partie d'un fichier ASCII.

Tout mot compilé dans le dictionnaire FORTH peut être intégré à une nouvelle définition. En FORTH, un mot peut être considéré comme programme principal ou comme procédure d'un programme plus général.

Lors de la compilation d'une nouvelle définition tapée au clavier, vous pouvez taper sur <RET> à peu près n'importe quand:

: AFBIN 2 BASE ! . DECIMAL ; puis <RET>
Cette définition peut être tapée depuis le clavier en plusieurs fois de la manière suivante:
: AFBIN <RET>
2 BASE <RET>
! . <RET>
DECIMAL <RET>
; <RET>

La disposition des mots, le nombre d'espaces entre les mots, ainsi que la frappe en majuscule ou minuscule importe peu:

:     afbin 2 BaSe !         .     DecimaL         ; 

sera également accepté pourvu que le format des nombres soit cohérent et que les mots utilisés soient définis dans le dictionnaire.

ATTENTION: sur certaines versions FORTH disponibles sur micto-contrôleurs, il est nécessaire de respecter la casse des caractères constituant les mots du dictionnaire. C'est le cas pourFalshForth sur Arduino.

A ce jour, le langage FORTH est le seul langage connu acceptant de compiler du code source tapé directement depuis le clavier de manière aussi interactive. Cette dualité interpréteur/compilateur est également exploitable lorsque l'on veut compiler le contenu d'un fichier.

Mots définis plusieurs fois

Si deux mots portent le même nom, seul le dernier mot défini sera exécutable en interprétation:
: TEST1 ." Premier test " CR ; 
: TEST1 ." Second test " CR ; 

Ne tenez pas compte du message TEST1 "existe déjà" (ou équivalent):

TEST1 \ affiche SECOND TEST

L'interpréteur accède au contenu du dictionnaire à partir du dernier mot défini et exécute la définition la plus récemment définie parmi deux ou plusieurs définitions de même nom. Si une définition utilise la première version de TEST1, la création d'un nouveau mot portant également le nom TEST1 ne modifie pas le comportement de cette définition:

: TEST1 ." Premier test " CR ; 
: REGARDE TEST1 ; 
: TEST1 ." Second test " CR ; 
REGARDE \ affiche Premier test 

Pour modifier REGARDE et lui faire utiliser la nouvelle version de TEST, il faut également recompiler REGARDE:

: TEST1 ." Premier test " CR ; 
: REGARDE TEST1 ; 
: TEST1 ." Second test " CR ; 
: REGARDE TEST1 ; 
REGARDE \ affiche Second test 

Cette homonymie tolérée par FORTH permet de compiler successivement plusieurs programmes comportant des définitions de même nom sans avoir à rééditer le programme source pour renommer les noms de définitions identiques.

Cependant, dans une phase de mise au point de définition, on peut être gêné par la présence d'homonymes, et il est souhaitable de supprimer les versions de certaines définitions devenues inutiles, soit pour conserver la cohérence du programme, soit pour récupérer de l'espace mémoire ou toute autre raison pratique.

Enfin, l'existence de plusieurs vocabulaires définis par le programme est une façon élégante de lever les ambiguités entre homonymes.

Supprimer un mot du dictionnaire

Pour supprimer un mot du dictionnaire, il faut exécuter le mot FORGET suivi du nom de la définition à supprimer:

FORGET MOT1

supprime du dictionnaire MOT1 et tous les mots définis après lui. Si MOT1 est défini plusieurs fois, seule la dernière version de MOT1 est supprimée. Exemple:

: TEST1 ." Premier test " CR ; 
: REGARDE TEST1 ; 
: TEST1 ." Second test " CR ; 
: REGARDE TEST1 ; 
WORDS       affiche       REGARDE MOT1 REGARDE MOT1 ...etc...
FORGET MOT1 WORDS      affiche             REGARDE MOT1 ...etc...

Pour oublier tous les mots définis depuis le lancement de FORTH, taper EMPTY.

Vous pouvez marquer le début d'une application en exécutant MARK suivi du nom de l'application. Exemple, soit à compiler les fonctions graphiques contenues dans le fichier GRAPHIC.FTH, puis à compiler un programme utilisant ces fonctions graphiques:

INCLUDE GRAPHIC 
MARK DESSIN 

Si le contenu de a été modifié et doit être recompilé, il ne sera pas nécessaire de taper EMPTY puis de tout recompiler; en tapant DESSIN, vous supprimerez du dictionnaire les seules définitions compilées après le mot DESSIN.

Si vous essayez de supprimer une primitive du dictionnaire, un message d'erreur s'affichera:

FORGET DUP       \ affiche       Partie dictionnaire protégée 

Il est possible de protéger son application contre une destruction accidentelle en tapant la séquence:

HERE FENCE ! 

Exemple:

: TEST1 ." Troisième test " CR ; 
: REGARDE TEST1 ; 
HERE FENCE ! 
FORGET TEST1    \ affiche      Partie dictionnaire protégée 

Le mot FORGET teste d'abord la valeur contenue dans la variable FENCE; si son contenu est inférieur à l'adresse de compilation du mot à supprimer, le mot est supprimé du dictionnaire; dans le cas contraire, un message d'erreur s'affiche. La séquence HERE FENCE ! réinitilialise le contenu de FENCE en lui attribuant la valeur du pointeur de dictionnaire actuelle, c'est à dire une valeur supérieure à l'adresse de compilation de TEST1, ainsi TEST1 et REGARDE deviennent des mots protégés.

Constantes et variables simple précision

Tout programme écrit en FORTH, aussi sophistiqué soit-il, ne peut pas toujours traiter des données provenant de la pile de données. Dans certains cas on fera appel à des constantes et des variables. Les constantes sont définies à l'aide du mot CONSTANT:

2019 CONSTANT ANNEE-COURANTE 

Les variables sont définies à l'aide du mot VARIABLE:

VARIABLE JOURS 

La constante ANNEE-COURANTE et la variable JOURS figurent maintenant dans le dictionnaire FORTH, c'est-à-dire qu'elles sont disponibles au même titre qu'un mot compilé par : (deux-points) ou n'importe quelle autre primitive déjà définie dans FORTH. Seule l'exécution de ces mots diffère de celle d'un mot défini par : (deux-points).

Une constante dépose au sommet de la pile de données la valeur affectée au moment de sa définition:

ANNEE-COURANTE . 2019

Une variable dépose au sommet de la pile de données l'adresse contenant la valeur qui lui a été affectée ou qui devra y être affectée.

JOURS .

affiche une adresse simple précision (ou 32 bits selon la version Forth).

Le contenu de cette adresse est déposé sur la pile de données par l'exécution du mot @:

JOURS @ .

affiche 0. Zéro est la valeur attribuée par défaut à une variable lors de sa création.

Une valeur numérique simple précision peut être stockée dans une variable par l'exécution du mot !:<:p>

15 JOURS ! 
JOURS @ .  15