Sciences, Technologies et Jeux



Avant-propos

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.

Historique

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.

Concepts de base

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.

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)

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:

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.

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 ";".

FORTH sur votre machine

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.

Premières commandes

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:

L'appui sur une touche quelconque interrompt momentanément l'exécution de WORDS. Un nouvel appui sur une touche relance le défilement, excepté l'appui sur la touche qui l'interrompt définitivement. Les mots que vous voyez défiler à l'exécution de la commande WORDS appartiennent au dictionnaire du langage FORTH. Le dictionnaire est partagé en plusieurs vocabulaires, le vocabulaire principal étant le vocabulaire FORTH. TURBO-Forth est équipé de nombreux vocabulaires.

Avec TURBO-Forth, vous pouvez taper les mots contenant des caractères alphabétiques en caractères minuscules ou majuscules:

Un autre mot, DARK, provoque l'effacement de l'écran vidéo.
Le mot BYE vous fait quitter TURBO-Forth et vous renvoie sous DOS.
On peut taper plusieurs mots sur une même ligne FORTH, dans la limite de 255 caractères et en respectant la syntaxe du langage. Un mot FORTH est constitué des seuls caractères ASCII compris entre 33 et 127 inclus et la taille des mots valides est comprise entre 1 et 31 caractères maximum, espaces de séparation et retour chariot non inclus.

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:

Lors de la frappe d'une ligne de commandes depuis le clavier, les mots FORTH et leurs paramètres sont séparés par au moins un espace. Rappelez-vous bien de cette simple et seule règle lexicale FORTH: les mots sont séparés par des espaces. S'il y a plus d'un caractère espace entre deux mots, seul le premier caractère espace sera pris en compte par l'interpréteur.

Si vous tapez un mot ne figurant pas dans le dictionnaire de TURBO-Forth, un message d'erreur s'affiche:

Le mot inconnu est mis en valeur par affichage en mode "vidéo inverse".

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:

La ligne d'entrée des commandes a une capacité de 255 caractères. Ce mode de fonctionnement est appelé INTERPRETATION car toute commande est immédiatement exécutée. Plusieurs commandes peuvent être tapées dans la même ligne: effacera l'écran et affichera le vidage hexadécimal de la zone mémoire intra-segment commençant à l'adresse décimale 256 de 64 octets de longueur.

Première compilation

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.

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.

C'est bien pratique, un langage que l'on peut franciser aussi facilement! Presque du langage naturel! Dans cet exemple, les mots SOIT et ET sont censés ne rien faire, ce qu'ils font très bien... Retenez cet exemple et épatez vos amis programmeurs qui s'échinent encore sur leurs programmes en BASIC.
Tous les mots ainsi compilés sont ajoutés au dictionnaire et font maintenant partie du langage FORTH au même titre que n'importe quelle primitive déjà définie.

Maintenant, il se peut que vous ne souhaitiez pas conserver le fruit de vos premières expériences. Il y a plusieurs solutions:

Le mot FORGET doit être suivi du mot à supprimer du dictionnaire. Tous les mots définis après sa création seront également supprimés: Je ne vous infligerai pas le résultat de l'exécution de la séquence MOT1 MOT2 MOT3 dont la haute teneur intellectuelle dépasse bien des oeuvres autour desquelles on fait beaucoup plus de publicité... Abrégeons sommairement en opérant une déchirante révision littéraire par la commande: et, oh stupeur, MOT2 et MOT3 ont bel et bien disparu du dictionnaire. Vous étiez pourtant prévenus. Tout mot détruit ne peut être reconstitué à moins de le retaper depuis le clavier ou en le compilant depuis un fichier.

Manipulation des piles

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:

Le mot DUP duplique le contenu du sommet de la pile de données:

Le mot OVER duplique le second élément de la pile de données:

Le mot SWAP inverse les deux éléments du sommet de la pile de données:

Le mot ROT effectue une rotation sur les trois éléments situés au sommet de la pile de données:

Le mot -ROT effectue une rotation inverse sur trois éléments. Son comportement est similaire à l'exécution de deux ROT successifs.

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.

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:

Voici quelques exemples d'utilisation de ces manipulateurs de pile de données:

Le mot AU-CARRE élève un nombre entier quelconque au carré: Le mot AU-CUBE élève un nombre entier quelconque au cube:

Passage de paramètres par la pile de retour

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.

Le mot R> transfère un nombre entier de la pile de retour vers la pile de données.

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.

Ici, les mots >R et R> ont servi à mémoriser la valeur initiale déposée sur la pile de données. Nota: si vous essayez cet exemple, ne tapez pas les commentaires qui suivent le caractère \, FORTH ne les compilant pas.

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:

Mais ceci n'a réellement d'intérêt que si vous devenez un barbu de la programmation en FORTH et que vous cherchez à comprendre les mécanismes subtils qui animent ce langage.

Affichage des nombres entiers

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
    3 10 .R affiche 3 (3 précédé de 9 espaces)
    101 10 .R affiche 101 (101 précédé de 7 espaces)
Et dont voici une application très pratique:
    : C>F ( øC --- øF) \ Conversion Celsius en Fahrenheit
    9 5 */ 32 +
    ;

    : .TREMPE ( øC ---) \ Affiche øC et øF formatés
    DUP 6 .R ." øC "
    C>F 6 .R ." øF"
    ;

    : TREMPE-ACIER ( ---) \ Table des températures de trempe
    CR ." COULEURS DE TREMPE DE L'ACIER:" CR
    CR ." rouge foncé " 680 .TREMPE
    CR ." rouge cerise foncé" 740 .TREMPE
    CR ." rouge cerise " 770 .TREMPE
    CR ." rouge cerise clair" 800 .TREMPE
    CR ." rouge clair " 850 .TREMPE
    CR ." rouge très clair " 900 .TREMPE
    CR ." rouge jaune " 950 .TREMPE
    CR ." jaune " 1000 .TREMPE
    CR ." jaune clair " 1100 .TREMPE
    CR ." jaune blanc " 1200 .TREMPE
    CR ." blanc " 1300 .TREMPE CR CR
    ;

Le mot U.R procède de la même manière que .R, mais affiche le nombre entier non signé:

    Exemple
    1 10 U.R affiche 1
    -1 10 .R affiche 65535
    Soit à afficher une suite d'adresses en hexadécimal et l'équivalent en décimal entre parenthèses:

    : .H(D) ( n ---)
    BASE @ >R \ sauvegarde base numérique courante
    DUP HEX 4 U.R \ affichage en hexadécimal dans un champ de 4 car.
    SPACE ." (" \ affichage d'un espace et parenthèse ouverte
    DECIMAL 5 U.R \ affichage en décimal dans un champ de 5 caractères
    ." )" \ affichage de la parenthèse fermée
    R> BASE ! \ restauration base numérique courante
    ;

    DECIMAL
    CR 256 .H(D) affiche 100 ( 256)
    CR 65535 .H(D) affiche FFFF (65535)
    HEX
    CR FF .H(D) affiche FF ( 255)
    CR FFFF .H(D) affiche FFFF (65535)

Les nombres double précision

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
    135246. D. affiche 135246
    135246, D. affiche 135246
Le point, la virgule ou la barre de fraction peuvent être placés ailleurs qu'à l'extrémité du nombre:
    135,246 D. affiche 135246

Les opérations élémentaires exécutables sur les nombres 32 bits sont l'addition et la soustraction:

    Exemple
    3. 5. D+ correspond à 3 + 5
    3. 5. D- correspond à 3 - 5

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
    5. D. affiche 5
    -1. UD. affiche 4294967295
    10. 12 D.R affiche 10
    35.3 12 UD.R affiche 353

Un nombre entier 16 bits signé peut être transformé en nombre 32 bits signé en exécutant le mot S>D.

    Exemple
    10 S>D D. affiche 10
    -5 S>D D. affiche -5

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
    10 0 D. affiche 10
    -5 0 D. affiche 65531
L'opération inverse est possible si la valeur 32 bits est comprise entre 0 et 65535:
    10. DROP . affiche 10

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
    : ?S>D ( d ou n --- d)
    DPL @ 0<
    IF
      S>D
    THEN
    ;

    10 ?S>D D. affiche 10
    10. ?S>D D. affiche 10
Il est intéressant de comparer les valeurs de DPL pour différentes positions du point décimal lors du traitement d'un nombre 32 bits:
    3314. DPL @ . affiche 0
    331.4 DPL @ . affiche 1
    33.14 DPL @ . affiche 2
    3.1.4 DPL @ . affiche 1
    (seule la position du second point est conservée dans DPL)

Les opérations de multiplication et de division 32 bits ne sont pas définies à l'exception des mots D2* et D2/:

    Exemple
    10. D2* D. affiche 20
    10. D2/ D. affiche 5
Mais avec les primitives de FORTH, il n'y a aucun problème pour définir des mots permettant de multiplier un nombre 32 bits par trois, quatre, cinq ou plus le cas échéant:
    : D3* ( d --- d*3)
    2DUP 2DUP D+ D+
    ;

    : D4* ( d --- d*3)
    D2* D2*
    ;

    : D5* ( d --- d*5)
    2DUP D2* 2SWAP D3* D+
    ;

    etc...

Opérations mixtes 16/32 bits

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
    11. 2 MU/MOD D. . affiche 5 1

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
    -12. 2 M/MOD . . affiche -6 0

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
    10 30 U*D D. affiche 300

Le mot *D multiplie deux nombres 16 bits signés et laisse sur la pile le résultat au format 32 bits signé.

    Exemple
    -10 30 *D D. affiche -300

Changement de base numérique

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
    255 HEX . DECIMAL affiche FF

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:

    2 BASE !
et de taper DECIMAL pour revenir à la base numérique décimale.

TURBO-Forth dispose de trois mots pré-définis permettant de sélectionner différentes bases numériques:

  • DECIMAL pour sélectionnner la base numérique décimale. C'est la base numérique prise par défaut au démarrage de TURBO-Forth.
  • HEX pour sélectionner la base numérique hexadécimale.
  • OCTAL pour sélectionner la base numérique octale.
Dès sélection d'une de ces bases numériques, les nombres litéraux seront interprétés, affichés ou traités dans cette base. Tout nombre entré précédemment dans une base numérique différente de la base numérique courante est automatiquement converti dans la base numérique actuelle.
    Exemple
    DECIMAL 255 HEX 1+ . affiche 100

On peut définir sa propre base numérique en définissant le mot approprié ou en stockant cette base dans BASE.

    Exemple
    : BINARY ( ---) \ sélectionne la base numérique binaire
    2 BASE !
    ;

    DECIMAL 255 BINARY . affiche 11111111

Définition de nouveaux formats d'affichage

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:

  • <# débute une séquence de définition de format
  • # insère un digit dans une séquence de définition de format
  • #S équivaut à une succession de #
  • HOLD insère un caractère dans une définition de format
  • #> achève une définition de format et laisse sur la pile l'adresse et la longueur de la chaîne contenant le nombre à afficher.
Ces mots ne sont utilisables qu'au sein d'une définition.
    Exemple
    soit à afficher un nombre exprimant un montant libellé en francs avec la virgule comme séparateur décimal:

    : FRANCS ( ud ---)
    <# # # ASCII , HOLD #S #>
    TYPE ." Fr "
    ;

    0.35 FRANCS affiche 0,35 Fr
    35.75 FRANCS affiche 35,75 Fr
    10.15 35.75 D+ FRANCS affiche 45,90 Fr
La définition de FRANCS ne prend pas en compte le signe du résultat, ni la position de la virgule.

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
    : :00 ( ---)
    DECIMAL # 6 BASE ! # ASCII : HOLD DECIMAL
    ;

    : HMS ( ud ---)
    <# :00 :00 #S #> TYPE SPACE
    ;

    59. HMS affiche 0:00:59
    60. HMS affiche 0:01:00
    4500. HMS affiche 1:15:00
Explication: le système d'affichage des secondes et des minutes est appelé système sexagésimal. Les 'unités' sont exprimées dans la base numérique décimale, les 'dizaines' sont exprimées dans la base six. Le mot :00 défini précédemment gère la conversion des 'unités' et des 'dizaines' dans ces deux bases pour la mise au format des digits correspondants aux secondes et aux minutes. Pour les heures, les digits sont tous décimaux.

Les chaines de caractères

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é:

  • sur 7 bits, les codes des caractères sont compris entre 0 et 127. La norme la plus utilisée est celle définie dans le standard ASCII.
  • sur 8 bits, les codes des caractères sont compris entre 0 et 255. Sur les systèmes IBM PC/XT/AT et compatibles, les codes compris entre 128 et 255 correspondent aux caractères accentués de divers pays, symboles monétaires et mathématiques, caractères semi-graphiques.

Le mot EMIT affiche un caractère à partir de son codeASCII.

    Exemple
    65 EMIT affiche 'A'

Certains codes n'affichent pas directement un caractère à l'écran, mais déclenchent une action:

    Exemple
    7 EMIT provoque l'émission d'un bip sonore

Pour visualiser tous les codes disponibles, vous pouvez essayer la définition suivante:

    : AFFICHE-CARS ( ---)
    256 32
    DO
      I EMIT
    LOOP
    ;

Pour connaître le code d'un caractère associé à une touche, essayez cette définition:

    : .TOUCHE ( ---)
    CR ." Appuyez sur une touche: " KEY
    CR ." Vous avez appuyé sur : " EMIT CR
    ;

Représentation en mémoire d'une chaine de caractères

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
    : TITRE ( --- str)
    " MENU GENERAL "
    ;

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:

    "MENU GENERAL"
provoque une erreur en interprétation ou en compilation, FORTH ne reconnaissant pas le mot "MENU à moins que vous ne l'ayez préalablement défini.

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
    TITRE TYPE affiche MENU GENERAL
Attention, TYPE affiche le contenu d'une zone mémoire de taille quelconque à partir de n'importe quelle adresse de base sans faire de discernement entre caractères affichables et caractères exécutables. Une plaisanterie du genre 0 25000 TYPE risque d'avoir un effet assez psychédélique sur votre écran vidéo...

Les chaînes de caractères peuvent être définies de plusieurs façons:

  • en tant que constantes alphanumériques, par l'utilisation du mot ".
  • traitement de variables alphanumériques définies dans le dictionnaire par exécution du mot de définition STRING.
  • par traitement de chaînes du type concaténation, fractionnement, de constantes ou variables alphanumériques, extraction de zones mémoires contenant du texte ASCII, lecture de fichier, etc...

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
    10 STRING A$
définit une variable alphanumérique pouvant recevoir dix caractères ou moins. Ensuite, l'exécution d'un mot défini par STRING dépose sur la pile l'adresse et la longueur de la chaîne contenue dans sa zone mémoire. Si la variable chaîne n'a pas encore été affectée, cette longueur sera nulle:
    A$ dépose son adresse et la valeur 0 sur la pile de données.

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
    " TEST" A$ $!
Le mot $! peut être exploité en interprétation ou dans une définition compilée.
    A$ TYPE affiche TEST
    : SALUT ( ---)
    ." BONJOUR " A$ TYPE
    ;

    " MONSIEUR" A$ $!
    SALUT affiche BONJOUR MONSIEUR
    " MADAME" A$ $!
    SALUT affiche BONJOUR MADAME

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
    " MADEMOISELLE" A$ $!
    SALUT affiche BONJOUR MADEMOISEL

On peut aussi affecter depuis le clavier une chaîne alphanumérique à une variable alphanumérique en utilisant le mot INPUT$:

    Exemple
    A$ INPUT$
attend qu'une suite de caractères soit tapée depuis le clavier et la range dans la zone mémoire réservée de la variable alphanumérique dont les paramètres adresse et longueur figurent au sommet de la pile de données.

Compilation/Interprétation

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:

  • l'interpréteur externe avec lequel vous avez déjà fait connaissance en exécutant les manipulations précédemment décrites.
  • l'interpréteur d'exécution pas à pas qui opère sur une définition et permet la mise au point des routines délicates.
  • l'interpréteur d'adresse interne.
Les deux premiers sont écrits en FORTH, le dernier est écrit en langage machine.

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:

    INCLUDE fichier
où "fichier" est le nom du fichier contenant le texte à compiler. Les fichiers compilables par TURBO-Forth ont l'extension FTH par défaut, pour toute autre extension, la préciser.

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
    Quand vous tapez:
    VARIABLE TEST
    Turbo-FORTH créé la structure suivante dans le vocabulaire courant:

L'en-tête est composé de divers champs:
  • le VFA (View Field Adress) est un champ spécifique à Turbo-FORTH, et est utilisé par l'auto-documentation (commande HELP), ainsi que par le Métacompilateur PHENIX.
  • le LFA (Link Field Adress) est le champ de lien, il contient l'adresse du LFA du mot précédent dans le vocabulaire courant. Le mot WORDS se sert de ce champ pour parcourir un vocabulaire et afficher les mots qui le compose.
  • le NFA (Name Field Adress) est le champ de nom. Les 5 premiers bits codent la longueur du nom du mot. Le bit 8 est toujours à 1. Viennent ensuite les codes ASCII du nom. Le bit 8 du dernier est mis à 1.
  • le CFA (Code Field Adress) est le champ de code. Il contient l'adresse du mot de définition du mot courant. Il est utilisé par l'interpréteur. Dans l'exemple, le CFA de TEST pointe sur le code exécutif du mot de définition VARIABLE.
  • le PFA (Parameter Field Adress) est le champ paramétrique. Il contient le corps de la définition du mot courant. Dans l'exemple, le PFA de test contiendra la valeur de la variable, initialisée à zéro à sa création.
FORTH comprend les outils permettant de retrouver ces divers champs:
  • ' "mot" --- cfa
    empile le CFA du mot donné.
  • >BODY cfa --- pfa
    empile le PFA du mot dont le CFA est donné.
  • >LINK cfa --- lfa
    empile le LFA du mot dont le CFA est donné.
  • >NAME cfa --- nfa
    empile le NFA du mot dont le CFA est donné.
  • >VIEW cfa --- vfa
    empile le VFA du mot dont le CFA est donné.
  • BODY> pfa --- cfa
    empile le CFA du mot dont le PFA est donné.
  • L>NAME lfa --- nfa
    empile le NFA du mot dont le LFA est donné.
  • LINK> lfa --- cfa
    empile le CFA du mot dont le LFA est donné.
  • N>LINK nfa --- lfa
    empile le LFA du mot dont le NFA est donné.
  • NAME> nfa --- cfa
    empile le CFA du mot dont le NFA est donné.

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
    CAPS ON
    : truc
    ...
    ;

    WORDS affiche au début du dictionnaire le mot TRUC

    CAPS OFF
    : truc
    ...
    ;

    WORDS affiche au début du dictionnaire le mot truc
Si CAPS est à l'état OFF, FORTH fera la différence entre caractères majuscules et minuscules dans le libellé d'un mot.

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:

  • placé après le source à interpréter ou compiler, il permet de commenter le programme, voire de le documenter.
  • placé n'importe où dans un fichier source en cours de mise au point, il permet de limiter la compilation et de rechercher plus facilement les erreurs de compilation.

Prenez soin de toujours bien commenter vos programmes source. Il y a trois manière de commenter les programmes:

  • le mot ( (parenthèse ouvrante) ouvre une zone commentaire qui s'achève après le premier caractère ) rencontré.
  • le mot \ déclare le reste de la ligne courante comme zone commentaire
  • le mot EOF déclare le reste du fichier courant comme zone commentaire.

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
    FORTH WORDS affiche les mots du vocabulaire FORTH
    ASSEMBLER WORDS affiche les mots du vocabulaire ASSEMBLER
    FORTH vous ramène dans le vocabulaire FORTH

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.

La récursivité

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
    : FACTORIELLE ( n --- n*n-1*n-2*...3*2*1)
    DUP 1 - DUP 1 >
    IF
      RECURSE
    THEN
    *
    ;

    2 FACTORIELLE . affiche 2
    3 FACTORIELLE . affiche 6
    4 FACTORIELLE . affiche 24
La récursivité a ses limites: la capacité des piles de données et de retour. Une récursivité mal contrôlée sature la pile de données ou de retour et bloque le système.

Constantes et Variables

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
    1988 CONSTANT ANNEE
Les variables sont définies à l'aide du mot VARIABLE:
    Exemple
    VARIABLES JOURS

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
    ANNEE . affiche 1988
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.
    Exemple
    JOURS . affiche une adresse 16 bits
Le contenu de cette adresse est déposé sur la pile de données par l'exécution du mot @:
    Exemple
    JOURS @ . affiche 0
Zéro est la valeur attribuée par défaut à une variable lors de sa création.

Une valeur numérique 16 bits peut être stockée dans une variable par l'exécution du mot !:

    Exemple
    15 JOURS ! puis
    JOURS @ . affiche 15

Le mot ? combine l'action de @ et . et s'utilise comme suit:

    Exemple
    16 JOURS ! puis
    JOURS ? affiche 16

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
    VARIABLE VIVANT
    : .HERITAGE ( ---)
    VIVANT @
    IF
      ." Attendez encore pour hériter"
    ELSE
      ." Maintenant, courrez chez le notaire"
    THEN
    ;

    0 VIVANT ! \ considère mort
    .HERITAGE affiche Maintenant, courrez chez le notaire

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
    150000. 2CONSTANT JACKPOT
Une variable double précision est définie par le mot 2VARIABLE:
    Exemple
    2VARIABLE SCORE
Une valeur double précision est affectée à une variable double précision par le mot 2!:
    Exemple
    120000. SCORE 2!
Le contenu d'une variable double précision est déposé au sommet de la pile de données par l'exécution du mot 2@:
    Exemple
    SCORE 2@ D. affiche 120000

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
    80 STRING A$
crée une variable chaîne A$ dont la capacité maximale est de 80 caractères. L'affectation d'un contenu à une chaîne, en interprétation ou compilation, est exécutée par le mot $!:
    Exemple
    " TEST" A$ $!
L'exécution du mot A$ dépose sur la pile l'adresse et la longueur de la chaîne de caractères contenue dans la zone paramétrique de A$.
    Exemple
    A$ TYPE affiche TEST

Structures de contrôle

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:

  • les branchements conditionnels
  • les branchements inconditionnels

Une suite d'instructions sera réexécutée à l'aide d'une boucle. Celles-ci sont également de deux sortes:

  • boucles itératives ou répétitives contrôlées par des index de début et de fin de boucle
  • boucles indéfinies

Branchements conditionnels vers l'avant

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:

  • IF ... THEN
  • IF ... ELSE ... THEN
Le mot IF est un mot d'exécution immédiate et compile un branchement conditionnel. Il n'est utilisable qu'en compilation.
    Exemple
    VARIABLE CHALEUR
    : METEO ( ---)
    CHALEUR @ 25 >
    IF
      CR ." Il risque d'y avoir de l'orage"
    THEN
    ;

    et en exécution:

    15 CHALEUR ! METEO n'affiche rien
    35 CHALEUR ! METEO affiche "Il risque d'y avoir de l'orage"
Le mot METEO teste le contenu de la variable CHALEUR et exécute la partie de définition comprise entre IF et THEN si cette valeur est supérieure à 25. Mais s'il fait 25 degrés ou moins, le mot METEO n'annonce rien. Pour y remédier, on peut le redéfinir:
    Exemple
    : METEO2 ( ---)
    CHALEUR @ 25 >
    IF
      CR ." Il risque d'y avoir de l'orage"
    ELSE
      CR ." Le temps se rafraîchit"
    THEN
    ;

    Maintenant:

    15 CHALEUR ! METEO2 affiche "Le temps se rafraîchit"
Si le résultat du test exécuté avant IF délivre un flag booléen faux, c'est la partie de définition située entre ELSE et THEN qui sera exécutée.

Un flag booléen peut être le résultat de diverses opérations:

  • lecture d'une adresse mémoire,
  • empilage du contenu d'un registre en sortie d'exécution d'une définition écrite en code machine,
  • résultat d'un calcul arithmétique 16 ou 32 bits, signé ou non,
  • résultat d'une opération logique (OR, AND, NOT, XOR) ou d'une combinaison d'opérations logiques,
  • paramètre empilé par l'exécution d'une définition exécutée avant IF
Le mot IF teste et consomme la valeur située au sommet de la pile de données.

Branchements conditionnels vers l'arrière

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
    : DACTYLO ( ---)
    BEGIN
      KEY DUP EMIT ASCII $ =
    UNTIL
    ;
L'exécution de DACTYLO affiche tous les caractères tapés au clavier. Seul l'appui sur la touche marquée du signe '$' peut interrompre la répétition. L'appui sur la touche renvoie en début de ligne. Pour faire passer le curseur à la ligne suivante, il faut redéfinir DACTYLO:
    Exemple
    : DACTYLO ( ---)
    BEGIN
      KEY DUP CONTROL M =
      IF
        CR
      ELSE
        DUP EMIT
      THEN
      ASCII $ =
    UNTIL
    ;
Maintenant, l'appui sur renvoie bien en début de ligne suivante. Notez l'imbrication de la structure IF..ELSE.. THEN dans la structure BEGIN..UNTIL.

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
    Si on définit DACTYLO par:

    : DACTYLO ( ---)
    BEGIN
      KEY EMIT
    AGAIN
    ;
On ne pourra plus interrompre la boucle lors de son exécution. Le seul moyen pour s'en sortir sera de taper sur CONTROL C, ou d'interrompre l'alimentation électrique du système.

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
    : DACTYLO ( ---)
    BEGIN
      KEY DUP ASCII $ <>
    WHILE
      EMIT
    REPEAT
    DROP
    ;
Par rapport à notre première définition de DACTYLO avec BEGIN.. UNTIL, cette version diffère par un détail: voyez-vous lequel?

Répétition contrôlée d'une action

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
    : BOUCLE ( ---)
    10000 0
    DO
    LOOP
    ;

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
    : CARACTERES ( ---)
    256 32
    DO
      I EMIT
    LOOP
    ;
affiche tous les caractères ASCII situés entre 32 et 255. Dans cette définition, le mot I dépose sur la pile la valeur de l'index courant de la boucle. L'index prend successivement toutes les valeurs comprises entre 32 et 256, 256 non comprise. En effet, l'incrémentation et le test de sortie de boucle sont exécutés par LOOP.

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
    VARIABLE TABLE
    : AFFICHE-TABLE
    CR 11 TABLE @ * TABLE @
    DO
      I . 3 .R TABLE @
    +LOOP
    ;

    3 TABLE ! AFFICHE-TABLE affiche 3 6 9 12 15 ... 30
    7 TABLE ! AFFICHE-TABLE affiche 7 14 21 28 .... 70

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
    : TABLE-MULTIPLICATION ( ---)
    11 1
    DO
      I TABLE ! AFFICHE-TABLE
    LOOP
    ;
Ne soyez pas étonné par la réutilisation du mot I, déjà exploité dans la définition de AFFICHE-TABLE. L'exécution de I ne fait référence qu'à la boucle dans laquelle il est défini et en cours d'exécution. Par contre, dans le cas de deux boucles imbriquées, pour accéder depuis la boucle imbriquée à l'index de la boucle extérieure, il faut utiliser le mot J.
    Exemple
    : IMBRIQ ( ---)
    6 0
    DO
      CR I 3 .R ." - "
      10 0
      DO
        I J * 4 .R
      LOOP
    LOOP
    CR
    ;

Pour interrompre le déroulement d'une boucle de type DO.. LOOP ou DO.. +LOOP, il faut exécuter le mot LEAVE.

    Exemple
    : TEMPO-ARRET
    1000 0
    DO
      100 MS ( MS mot pré-défini, génère un délai)
      ?KEY
      IF
        LEAVE
      THEN
    LOOP
    ;
Le mot TEMPO-ARRET génère un temps d'arrêt d'environ 100 secondes. Si l'utilisateur enfonce une touche du clavier avant ce délai, la boucle est interrompue et le programme poursuit son exécution.

Structure uni-conditionnelle à choix multiples

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
    : JOUR ( n --- adr long)
    7 MOD \ intervalle défini entre 0 et 6
    CASE
      0 OF " DIMANCHE " ENDOF
      1 OF " LUNDI " ENDOF
      2 OF " MARDI " ENDOF
      3 OF " MERCREDI " ENDOF
      4 OF " JEUDI " ENDOF
      5 OF " VENDREDI " ENDOF
      6 OF " SAMEDI " ENDOF
    ENDCASE
    ;

    Exemples d'exécution:
    2 JOUR TYPE affiche MARDI
    5 JOUR TYPE affiche VENDREDI
    7 JOUR TYPE affiche DIMANCHE