Le langage FORTH a ses adeptes et ses détracteurs. Réputé difficile par ceux qui n'ont fait que le survoler, il est l'un des langages informatiques les plus performants. Les concepts qu'il manipule allient la simplicité, l'efficacité et la complexité.
Il offre une alternative intéressante aux langages traditionnels compilés et interprétés, car FORTH est à la fois compilateur et interpréteur.
Le langage FORTH n'est, contrairement aux langages classiques, pas limité par une liste finie d'instructions et de structures de données. Le programmeur FORTH a la possibilité de modeler FORTH à sa convenance, et de le spécialiser en fonction de l'application qu'il développe.
Ce site est dédié à FORTH, et vous permettra de vous y initier, si vous ne le connaissez pas encore.
Tous les exemples de cette initiation sont faits avec TURBO-FORTH.
Si vous êtes déjà un familier de FORTH, vos suggestions et conseils sont les bienvenues.
FORTH a été conçu vers la fin des années 60 par Charles H. MOORE. Celui-ci fut tellement satisfait du résultat de son oeuvre qu'il voulut l'appeler langage de quatrième génération (FOURTH). Mais la machine sur laquelle il avait développé son langage (un IBM 1130), n'acceptait que des noms de programmes de cinq lettres, ce qui lui fit choisir FORTH comme nom définitif.
En FORTH, la notion de procédure et de fonction n'existe pas. Les instructions FORTH s'appellent des MOTS. A l'instar d'une langue traditionnelle, FORTH organise les mots qui le composent en VOCABULAIRES, ensemble de mots ayants un trait communs.
Programmer en FORTH consiste à enrichir un vocabulaire existant, ou à en définir un nouveau, relatif à l'application en cours de développement.
Toute nouvelle définition d'un mot se fait à partir des mots déjà présents. Il est bien entendu possible de redéfinir un mot existant. Lorsque FORTH cherche un mot, il se référera toujours à la définition la plus récente du vocabulaire courant.
| Exemple |
Le mot BOIRE est défini avec le mot REMPLIR_VERRE.
Le mot J'AI_SOIF est défini avec le mot BOIRE.
J'AI_SOIF utilise donc indirectement le mot REMPLIR_VERRE.
FORTH utilise une structure de donnée bien connue: la PILE LIFO (Last In First Out, Dernier Entré, Premier Sorti). L'analogie la plus courante avec une pile LIFO est une pile d'assiettes, qui n'est alimentée que par le haut, et dont la première assiette déposée sera la dernière retirée, et inversement, dont la dernière assiette déposée sera la première retirée.
FORTH est construit autour de deux piles:
La Pile de données (DATA STACK)
La Pile de retour (RETURN STACK)
| Exemple |
Quand vous entrez les nombres suivants (
symbolise la touche Entrée de votre PC):
L'interpréteur FORTH analyse le flot d'entrée (en FORTH, l'espace est l'unique séparateur d'instructions reconnu), et quand il reconnait un nombre, empile celui-ci sur la pile de données. Après analyse de la ligne précédente, la pile de données a l'aspect suivant:
FORTH utilise la notation dite RPN (Reverse Polish Notation, Notation Polonaise Inversée), très utilisée par les calculatrices du type Hewlet Packard, entre autre.
Ce type de notation ne modifie pas l'ordre des opérandes, et s'exécute toujours de gauche à droite. Elle permet d'éliminer la notion de hiérarchie des opérateurs, courante dans la plupart des langages de programmation traditionnels, et qui spécifie l'ordre d'exécution de ceux-ci (* avant /, + avant -, etc...).
Cette hiérarchie peut compliquer les opérations à effectuer, si on veut qu'un opérateur d'ordre inférieur s'exécute avant un opérateur d'ordre supérieur. Il faut pour cela utiliser les parenthèses. En outre, l'analyseur syntaxique devient complexe à réaliser.
La notation RPN supprime ces inconvénients et:
en FORTH, l'application de ce principe se fait de la façon suivante:
| Exemple |
l'expression ((2+5) * (7-2)) / ((5+2) * 3)
se traduit en FORTH: 2 5 + 7 2 - * 5 2 + 3 * /
Il est à noter que les langages traditionnels travaillent de la même façon quand ils ont à évaluer une expression algébrique. En notation algébrique, les parenthèses ne servent qu'à isoler une expression sous forme de sous-expression, qui devient membre d'une expression plus générale.
| Notation algébrique | Notation inversée |
| (2+3) * 5 | 2 3 + 5 * |
| 2 + (3*5) | 2 3 5 * + ou 3 5 * 2 + |
Tous les problèmes arithmétiques peuvent êtres résolus de cette manière, ce n'est qu'une question d'habitude. Les exemples donnés ci-dessus illustrent parfaitement la rigueur dont doit faire preuve le programmeur FORTH. Cette rigueur garantit un fonctionnement sans ambiguïté des programmes, quel que soit leur niveau de complexité.
Toute définition de mot commencera par le mot ":", suivi du nom du mot que l'on définit, et se termine par le mot ";".
| Exemple |
: BOIRE
REMPLIR_VERRE
;
: J'AI_SOIF
BOIRE
;
Actuellement, FORTH existe pour à peu près toutes les machines, du ZX81 au CRAY !!!. Si vous voulez vous initier, et profiter des sources que je propose, TURBO-FORTH pour PC est un système de développement complet qui vous permettra de le faire en douceur.
Un grand choix de compilateurs FORTH est aussi disponible ici.
La première commande que vous essayerez est WORDS. Ce mot provoque l'affichage de tous les mots FORTH disponibles dans le vocabulaire courant. Tapez WORDS et appuyez sur
, vous voyez à l'affichage:
Avec TURBO-Forth, vous pouvez taper les mots contenant des caractères alphabétiques en caractères minuscules ou majuscules:
| Exemple |
* ?DUP >R # @ VOCABULARY IN-META
sont tous des mots FORTH.
Quand vous créerez vos propres définitions, des noms aussi farfelus que ceux qui suivent seront parfaitement valides, sous réserve qu'ils signifient quelque chose pour vous et soient définis:
Si vous tapez un mot ne figurant pas dans le dictionnaire de TURBO-Forth, un message d'erreur s'affiche:
De nombreux mots FORTH admettent en entrée un ou plusieurs paramètres et empilent souvent le résultat sur la pile de donnée. En ce sens, un mot FORTH est assimilable à une procédure ou une fonction. FORTH ne fait pas de distinction entre un mot défini en code machine au sein de son dictionnaire et un mot défini sous une forme plus évoluée. Pour bien vous imprégner de cette notion, abordez chaque nouveau mot comme une boite noire en tenant compte pour le moment exclusivement des paramètres qui sont éventuellement traités et rendus:
TURBO-Forth peut également compiler de nouvelles commandes. En cela, FORTH se démarque de tous les autres compilateurs tels PASCAL, C, COBOL, FORTRAN pour ne citer que les plus connus:
Une action de compilation débute par le mot : (deux-points) et s'achève par le mot ; (point-virgule). Le mot ":" est suivi par le nom de la nouvelle commande à définir.
| Exemple |
soit à définir le mot EFFACE qui aura pour action d'effacer l'écran, tapez:
: EFFACE
DARK
;
et appuyez sur
Cette fois-ci, l'écran ne s'est pas effacé, car DARK est situé dans une définition en cours de compilation. Le nouveau mot EFFACE fait maintenant partie du dictionnaire FORTH, ce que l'on peut aisément vérifier en exécutant WORDS.
Maintenant, il se peut que vous ne souhaitiez pas conserver le fruit de vos premières expériences. Il y a plusieurs solutions:
La pile de données est l'élément fondamental du langage FORTH pour le traitement de données. Son fonctionnement est identique à celui de la pile gérée par le micro-processeur. Dans certaines situations, les données traitées par les différentes définitions doivent être réordonnées ou dupliquées.
Le mot DROP supprime l'élément situé au sommet de la pile de données:
| Exemple |
Le mot DUP duplique le contenu du sommet de la pile de données:
| Exemple |
Le mot OVER duplique le second élément de la pile de données:
| Exemple |
Le mot SWAP inverse les deux éléments du sommet de la pile de données:
| Exemple |
Le mot ROT effectue une rotation sur les trois éléments situés au sommet de la pile de données:
| Exemple |
Le mot PICK dépose au sommet de la pile de données le nième élément de la pile de données, n non compris. La base de départ pour le comptage des éléments à traiter est 0 et non 1, l'élément numéro zéro étant situé immédiatement après le paramètre traité par PICK. La séquence 0 PICK est similaire à DUP, 1 PICK à OVER. Il n'y a pas de traitement d'erreur si n est supérieur au nombre d'éléments déposés sur la pile de données.
| Exemple |
Le mot ROLL effectue une rotation sur les n premiers éléments de la pile de données, n non compris. Comme pour PICK, la base de départ pour le comptage des éléments à traiter est 0:
| Exemple |
Voici quelques exemples d'utilisation de ces manipulateurs de pile de données:
A coté de la pile de paramètres, il existe dans FORTH une deuxième pile, appelée pile de retour parce qu'elle sert à l'interpréteur interne à retrouver l'adresse de retour à chaque appel d'une procédure.
Il y a parfois des cas extrêmes où l'on peut être amené à stocker un ou plusieurs paramètres ailleurs que sur la pile de données, ceci pour simplifier quelque peu certaines manipulations scabreuses. La solution la plus commode, parmi d'autres, est la pile de retour. Cette pile est accessible par les mots >R et R> moyennant quelques précautions pour ne pas compromettre le fonctionnement de cette pile interne.
Le mot >R transfère un nombre entier de la pile de données vers la pile de retour.
| Exemple |
Le mot R> transfère un nombre entier de la pile de retour vers la pile de données.
| Exemple |
Une opération >R R> est nulle. En fin de définition, il doit y avoir autant de >R que de R> sous peine de perturber quelque peu le déroulement normal de votre définition.
| Exemple |
Si aucune donnée n'a été transférée depuis la pile de données vers la pile de retour, l'utilisation du mot R> transfère l'adresse d'exécution du prochain mot à exécuter au sommet de la pile de données:
| Exemple |
En FORTH, les entiers 16 bits déposés sur la pile de données peuvent être affichés par exécution du mot . (point). Mais d'autres mots permettent d'exécuter un affichage plus présentable.
Le mot .R affiche un nombre 16 bits signé cadré à droite dans un champ de n caractères.
| Exemple |
Le mot U.R procède de la même manière que .R, mais affiche le nombre entier non signé:
| Exemple |
FORTH ne connaît pas les nombres en virgule flottante. Cependant, des routines peuvent être compilées pour exécuter des calculs sur ce type de nombres, mais ce sera au détriment de la vitesse de traitement. Si vous voulez traiter des quantités importantes, comme votre compte en banque ou le prix de votre prochaine voiture, vous pouvez utiliser les nombres double précision également nommés nombres 32 bits. Ceux-ci se distinguent des nombres entiers 16 bits en y introduisant un point, une virgule ou une barre de fraction:
| Exemple |
Les opérations élémentaires exécutables sur les nombres 32 bits sont l'addition et la soustraction:
| Exemple |
Les nombres double précision 32 bits situés au sommet de la pile peuvent être affichés par les mots suivants:
D. prononcer 'D-point'. Affiche un nombre double précision signé.
UD. prononcer 'U-D-point'. Affiche un nombre double précision non signé.
D.R prononcer 'D-point-R'. Affiche un nombre double précision signé cadré à droite dans un champ de n caractères.
UD.R prononcer 'U-D-point-R'. Affiche un nombre double précision non signé cadré à droite dans un champ de n caractères.
| Exemple |
Un nombre entier 16 bits signé peut être transformé en nombre 32 bits signé en exécutant le mot S>D.
| Exemple |
Pour transformer un nombre entier 16 bits non signé en nombre 32 bits non signé, il suffit d'empiler la valeur 16 bits 0 sur la pile après empilage du nombre entier 16 bits non signé.
| Exemple |
Quand un nombre 32 bits est déposé sur la pile de données, la variable DPL conserve la position du point décimal; si c'est un nombre 16 bits qui est déposé sur la pile de données, la variable DPL contient la valeur -1. On peut exploiter cette valeur pour définir un mot assurant une conversion conditionnelle:
| Exemple |
Les opérations de multiplication et de division 32 bits ne sont pas définies à l'exception des mots D2* et D2/:
| Exemple |
Les nombres 32 bits sont des valeurs généralement trop importantes pour qu'il soit intéressant de leur appliquer un traitement du type produit ou quotient. Toutefois, certains opérateurs arithmétiques mixtes permettent d'exécuter ces opérations.
Le mot MU/MOD divise un nombre 32 bits non signé par un nombre 16 bits signé; laisse sur la pile le quotient 32 bits non signé et le reste signé.
| Exemple |
Le mot M/MOD divise un nombre 32 bits signé par un nombre 16 bits signé; laisse sur la pile le quotient et le reste au format 16 bits signés.
| Exemple |
Le mot U*D multiplie deux nombres 16 bits non signés et laisse sur la pile le résultat au format 32 bits non signé.
| Exemple |
Le mot *D multiplie deux nombres 16 bits signés et laisse sur la pile le résultat au format 32 bits signé.
| Exemple |
Les nombres peuvent être traités dans n'importe quelle base numérique, toutes les bases numériques situées entre 2 et 36 étant valides:
| Exemple |
On peut choisir une base numérique encore plus grande, mais les symboles disponibles sortiront de l'ensemble alpha-numérique [0..9,A..Z] et risquent de devenir incohérents.
La base numérique courante est controlée par une variable nommée BASE et dont le contenu peut être modifié. Ainsi, pour passer en binaire, il suffit de stocker la valeur 2 dans BASE:
TURBO-Forth dispose de trois mots pré-définis permettant de sélectionner différentes bases numériques:
| Exemple |
On peut définir sa propre base numérique en définissant le mot approprié ou en stockant cette base dans BASE.
| Exemple |
TURBO-Forth dispose de primitives permettant d'adapter l'affichage d'un nombre à un format quelconque. Ces primitives ne traitent que des nombres double précision:
| Exemple |
Dans la définition de FRANCS, le mot <# débute la séquence de définition de format d'affichage; les deux mots # placent les chiffres des unités et des dizaines dans la chaîne de caractère; ASCII , HOLD placent le caractère , (virgule) à la suite des deux chiffres de droite; le mot #S complète le format d'affichage avec les chiffres non nuls à la suite de ,; le mot #> ferme la définition de format et dépose sur la pile l'adresse et la longueur de la chaîne contenant les digits du nombre à afficher; le mot TYPE affiche cette chaîne de caractères.
En exécution, une séquence de format d'affichage traite exclusivement des nombres entiers 32 bits signés ou non signés. La concaténation des différents éléments de la chaîne se fait de droite à gauche, c'est à dire en commençant par les chiffres les moins significatifs.
Le traitement d'un nombre par une séquence de format d'affichage est exécutée en fonction de la base numérique courante. La base numérique peut être modifiée entre deux digits.
Voici un exemple plus complexe démontrant la compacité du FORTH. Il s'agit d'écrire un programme convertissant un nombre quelconque de secondes au format HH:MM:SS:
| Exemple |
Une chaîne de caractères est un espace mémoire pointé par une adresse et une valeur indiquant le nombre de caractères pris en compte à partir de cette adresse.
Les caractères contenus dans une chaîne de caractères sont des valeurs codées sur 7 ou 8 bits selon le système utilisé:
Le mot EMIT affiche un caractère à partir de son codeASCII.
| Exemple |
Certains codes n'affichent pas directement un caractère à l'écran, mais déclenchent une action:
| Exemple |
Pour visualiser tous les codes disponibles, vous pouvez essayer la définition suivante:
Pour connaître le code d'un caractère associé à une touche, essayez cette définition:
Le premier mot permettant de définir une chaîne de caractères est le mot " (quote ou guillemet). Le texte compris dans la chaîne est délimité par un guillemet. Ce mot est utilisable en interprétation ou à l'intérieur d'une définition:
| Exemple |
L'exécution de TITRE dépose sur la pile de données les paramètres symbolisés par str correspondant à deux valeurs 16 bits, la première indiquant l'adresse mémoire où est rangé le contenu de la chaîne, la seconde indiquant le nombre de caractères à prendre en compte à partir de cette adresse. Dans notre exemple, l'adresse déposée sur la pile correspond à l'emplacement mémoire contenant la lettre M de la chaîne "MENU GENERAL", la longueur étant celle de la chaîne en question:
| Exemple |
Le mot " et le texte de la chaîne doivent être séparés par au moins un caractère espace:
Le contenu de la chaîne est affiché en exécutant le mot TYPE précédé des paramètres adresse et longueur de la chaîne:
| Exemple |
Les chaînes de caractères peuvent être définies de plusieurs façons:
Le mot STRING définit une variable de type chaîne alphanumérique. Le mot STRING est précédé d'un paramètre indiquant la taille maximale de la variable chaîne à définir:
| Exemple |
L'affectation d'une chaîne à une variable alphanumérique est réalisé par le mot $! précédé des paramètres de la chaîne origine et la chaîne de destination:
| Exemple |
Si vous tentez d'affecter une chaîne de taille supérieure à la taille maximale de la zone mémoire d'une variable chaîne définie par STRING, seuls les caractères affectables dans la limite de la zone mémoire réservée de cette variableseront pris en compte:
| Exemple |
On peut aussi affecter depuis le clavier une chaîne alphanumérique à une variable alphanumérique en utilisant le mot INPUT$:
| Exemple |
Le langage FORTH est d'un fonctionnement tout à fait original car il intègre à la fois un interpréteur, un compilateur et un assembleur. La version F83 dispose même de trois interpréteurs:
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.
L'assembleur FORTH peut traiter les branchements avant en utilisant des structures de contrôle évoluées à la place d'étiquettes ou de labels. Une séquence écrite en code machine peut être assemblée entre deux définitions compilées en FORTH avec CODE ... END-CODE, et même dans une définition en forth avec ASM[ ... ]FORTH.
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.
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 à 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.
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. Dans ce cas, sa compilation sera exécutée en tapant:
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.
Chaque mot FORTH est composé d'un en-tête, suivi du corps de sa définition.
| Exemple |
La disposition des mots, le nombre d'espaces entre les mots, ainsi que la frappe en majuscule ou minuscule importe peu.
Une restriction cependant est à signaler concernant la différence entre caractères majuscules et minuscules: elle peut être prise en compte selon l'état de la variable CAPS servant de flag booléen sur le contrôle du flux d'entrée:
| Exemple |
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.
Comme cela a déjà été expliqué brièvement, TURBO-Forth peut compiler des définitions provenant d'un fichier ASCII. Mais TURBO-Forth peut aussi interpréter une série de commandes ou d'opérations placées dans ces mêmes fichiers.
En fait, le langage FORTH ne fait pas de distinction entre le clavier et un fichier source: charger un fichier avec INCLUDE est équivalent à saisir au clavier chacune des lignes de ce fichier.
Cette dualité interprétation/compilation est très utile, car elle permet de modifier le contexte FORTH en cours de compilation.
Le contenu d'un fichier ASCII contenant des instructions FORTH est normalement compilé ou interprété depuis le début du fichier jusqu'à la fin physique du fichier. Mais on peut provoquer une fin artificielle de fichier en exécutant en mode interprété le mot EOF, c'est à dire en le plaçant en dehors d'une définition "deux-points".
Dès que le mot EOF est exécuté, la compilation ou interprétation se poursuit vers le programme appelant ou rend la main à l'utilisateur. Tout texte situé après EOF ne sera pas chargé en mémoire, donc ni interprété, ni compilé. Le mot EOF a deux utilités:
Prenez soin de toujours bien commenter vos programmes source. Il y a trois manière de commenter les programmes:
Une fois la compilation d'un nouveau mot achevée, il fait partie du dictionnaire au même titre que tous les mots déjà définis. On peut contrôler à tout instant la présence des mots définis en utilisant WORDS.
Lors de l'exécution de WORDS, les mots définis par vous ou ceux déjà pré-définis apparaissent dans l'ordre inverse de leur création, à savoir que le mot le plus récemment défini est affiché en premier.
Seuls les mots appartenant au vocabulaire courant sont affichés
| Exemple |
TURBO-Forth dispose d'un certain nombre de vocabulaires pré-définis dont vous pouvez lister les noms en exécutant VOCS. La connaissance du contenu de ces divers vocabulaire n'est pas indispensable pour le moment.
Tous les mots FORTH sont chaînés entre eux et l'entrée dans cette chaîne a toujours lieu à partir du dernier mot défini dans le vocabulaire courant.
Lorsqu'une définition d'un mot fait référence à des mots du dictionnaire, chaque adresse correspondante est exprimée en adressage absolu au sein de la nouvelle définition. Ainsi, la définition d'un mot FORTH n'est pas relogeable en mémoire sous sa forme compilée.
Les puristes affirment qu'un langage informatique est incomplet s'il ne peut traiter la récursivité. D'autres prétendent que l'on peut très bien s'en passer. FORTH va enthousiasmer les premiers, car il est équipé pour traiter ce type de situation.
Comme FORTH ne peut faire explicitement référence au mot en cours de définition, on insérera le mot RECURSE partout où l'on voudra faire appel à la définition en cours de compilation.
| Exemple |
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:
| Exemple |
| Exemple |
La constante ANNEE 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:
| Exemple |
| Exemple |
| Exemple |
Une valeur numérique 16 bits peut être stockée dans une variable par l'exécution du mot !:
| Exemple |
Le mot ? combine l'action de @ et . et s'utilise comme suit:
| Exemple |
Dans certaines situations, on peut considérer le contenu d'une variable 16 bits comme un flag booléen et non comme une valeur littérale. Dans ce cas, toute valeur non nulle sera considérée comme vraie et toute valeur nulle comme fausse:
| Exemple |
Si l'intervalle de définition d'une constante ou d'une variable définie par CONSTANT ou VARIABLE est trop restreint pour une application particulière, on peut faire appel aux constantes et aux variables double précision.
Une constante double précision est définie par le mot 2CONSTANT:
| Exemple |
| Exemple |
| Exemple |
| Exemple |
Pour définir une variable alphanumérique, il faut utiliser le mot de définition STRING précédé de la capacité maximale que peut atteindre la chaîne en cours d'utilisation. Cette taille est comprise entre 1 et 255:
| Exemple |
| Exemple |
| Exemple |
En programmation, toute séquence d'instructions peut être rompue en exécutant un branchement ou une boucle. Le langage BASIC, par exemple, utilise les instructions GOTO ou GOSUB. En FORTH, GOTO est inconnu et GOSUB est implicite. Pour rompre le déroulement linéaire d'une séquence d'instructions, on utilisera des structures de contrôle dont le rôle est de compiler des branchements. Ces branchements sont de deux sortes:
Une suite d'instructions sera réexécutée à l'aide d'une boucle. Celles-ci sont également de deux sortes:
Au cours du déroulement d'un programme, le résultat d'un test ou le contenu d'une variable peut être amené à modifier l'ordre d'exécution des instructions. Cette valeur, nommée flag booléen, est à l'état vrai si elle est non nulle, à l'état faux si elle est nulle.
Le flag booléen est utilisé par une instruction de branchement marquant le début d'une structure de contrôle:
| Exemple |
| Exemple |
Un flag booléen peut être le résultat de diverses opérations:
Avec la structure de type IF.. THEN et IF.. ELSE.. THEN, on ne peut exécuter qu'une partie de définition non répétitive. Pour réitérer une séquence de type faire..tant-que, il faut exploiter un nouveau type de structure de contrôle: la boucle répétitive indéfinie BEGIN.. UNTIL.
Dans une boucle BEGIN.. UNTIL, la partie de définition située entre ces deux mots est répétée tant que le résultat du test précédant UNTIL délivre un flag booléen faux.
| Exemple |
| Exemple |
Si le résultat du test précédant UNTIL est toujours faux, on ne peut plus sortir de la boucle BEGIN.. UNTIL. Cette situation a été prévue en FORTH et est exploitée par la boucle BEGIN.. AGAIN. L'utilisation de AGAIN équivaut à BEGIN ... 0 UNTIL.
| Exemple |
Avec une boucle BEGIN.. UNTIL ou BEGIN.. AGAIN, l'action est répétée en fin de boucle en fonction du résultat d'un test ou de manière inconditionnelle. Mais on peut exploiter un branchement avant conditionnel depuis une boucle dont la structure est BEGIN.. WHILE.. REPEAT.
Dans cette structure, le test est exécuté avant WHILE. Si le résultat est faux, l'exécution se poursuit après REPEAT. Si le résultat est vrai, la partie de définition comprise entre WHILE et REPEAT est exécutée, puis REPEAT effectue un branchement arrière inconditionnel, c'est à dire renvoie l'exécution à BEGIN.
| Exemple |
Le dernier cas de figure des diverses structures de contrôle disponibles en FORTH est la boucle DO.. LOOP. Cette structure admet comme paramètres d'entrée deux valeurs qui sont les index initiaux et terminaux contrôlant l'itération.
| Exemple |
Le mot DO, utilisable seulement en compilation, est toujours précédé de deux valeurs n1 n2, où n2 est l'index initial de la boucle, n1 la valeur terminale. La valeur terminale est en général supérieure à la valeur initiale.
| Exemple |
Pour incrémenter l'index de boucle d'une quantité différente de une unité, il faut remplacer le mot LOOP par +LOOP et le faire précéder de la valeur de l'incrément de boucle.
| Exemple |
L'incrément d'index de boucle située avant +LOOP peut être négatif. Dans ce cas, la première valeur placée avant DO est inférieure à la seconde. Rien ne nous interdit de ré-utiliser AFFICHE-TABLE dans une définition plus générale qui va nous afficher une véritable table de multiplication:
| Exemple |
| Exemple |
Pour interrompre le déroulement d'une boucle de type DO.. LOOP ou DO.. +LOOP, il faut exécuter le mot LEAVE.
| Exemple |
Dans certaines situations, on peut être amené à exécuter une action spécifique au programme en fonction d'une condition précise, parmi d'autres actions également dépendantes de cette condition. La structure de contrôle la plus fréquemment utilisée dans ce cas est la structure de type CASE.. OF.. ENDOF..ENDCASE.
La valeur à tester est placée devant le mot OF. Si la valeur figurant au sommet de la pile avant l'exécution de CASE est identique à celle-ci, la partie de définition située entre OF et ENDOF est exécutée, puis l'exécution se poursuit après ENDCASE. Dans le cas contraire, le test ou les tests suivants sont exécutés jusqu'à validité d'un test. Si aucun test n'a pu être vérifié, la partie de définition située le cas échéant entre le dernier ENDOF et ENDCASE est exécutée.
| Exemple |