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. So 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. 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
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 à 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. 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.
A titre d'exercice, éditez un fichier que vous nommerez BINAIRE.FTH, tapez la petite définition donnée en exemple, sauvegardez votre fichier et revenez sous TURBO, puis tapez INCLUDE BINAIRE.
Maintenant la nouvelle définition fait partie du dictionnaire FORTH, comme on peut le constater en tapant WORDS. Pour essayer le fonctionnement du mot qui vient d'être créé, il suffit de taper:
14 AFFICHE-BINAIRE affiche 1110 756
AFFICHE-BINAIRE affiche 1011110100
Si vous trouvez qu'AFFICHE-BINAIRE est trop long, réécrivez votre définition en l'appelant AFBIN ou mieux en définissant AFBIN comme suit: :
: AFBIN AFFICHE-BINAIRE ;
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.
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:
CAPS ON : truc ; WORDS
affiche en tête de dictionnaire le mot TRUCCAPS OFF : truc ; WORDS
affiche en tête de 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.
Pour charger le contenu d'un fichier source, il faut utiliser le mot INCLUDE suivi du nom du fichier à traiter. L'extension du fichier est par défaut FTH et peut être omise. Dans le cas contraire, préciser l'extension. Le fichier peut provenir d'un lecteur disque ou d'un répertoire différent du lecteur courant ou répertoire courant:
INCLUDE TEST.TXT traite TEST.TXT INCLUDE b:BINAIRE traite BINAIRE.FTH INCLUDE c:\TF83\F-PACK traite F-PACK.FTH contenu dans C:\TF83
Si vous ne savez plus où se trouve le fichier à traiter, il faut utiliser DIR avec les mêmes options que la commande DIR sous MSDOS:
DIR *.* affiche directory lecteur courant
DIR b:*.* affiche directory lecteur b:
DIR C:\TF83\*.FTH affiche les fichiers d'extension FTH de c:\TF83
Pour visualiser le contenu d'un fichier avant chargement et compilation, le mot LIST suivi du nom du fichier à lister affiche son contenu. Un appui sur une touche quelconque autre que la touche <RET> interrompt provisoirement le défilement, un nouvel appui relance le défilement. Deux appuis successifs sur <RET> interrompent définitivement le défilement.
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.
Reprenez le contenu du fichier BINAIRE.FTH que vous avez créé pour tester le précédent exemple et rajoutez après AFBIN les lignes suivantes:
CR 1 AFBIN
CR 8 AFBIN
CR 25 AFBIN
sauvegardez à nouveau BINAIRE.FTH et recompilez son contenu depuis TURBO-Forth par INCLUDE BINAIRE. TURBO-Forth compilera le contenu du fichier BINAIRE.FTH et exécutera les trois lignes qui ont été rajoutées.
Cette dualité interprétation/compilation est très utile, car elle permet de modifier le contexte FORTH en cours de compilation:
HEX
C0 EMIT 10 C4 REPLICATE D9 EMIT CR
DECIMAL
Ce programme sera parfaitement exécuté. 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.
Lorsqu'un fichier est en cours de compilation ou d'interprétation, on peut suivre la compilation en positionnant la variable ECHO avec un flag booléen vrai:
ECHO ON
INCLUDE BINAIRE
affiche le programme au fur et à mesure de la compilation/interprétation du programme.
La séquence ECHO OFF supprime l'affichage du fichier en cours de compilation. Les directives ECHO ON et ECHO OFF peuvent être utilisées au sein d'un fichier aussi souvent que vous le souhaitez.
Si vous envisagez de développer une application de taille conséquente, il est souhaitable dans un premier temps, de la fractionner en plusieurs fichiers de petite taille. Eventuellement, une partie de programme peut être réutilisée par un autre programme et dans ce cas, le morcellement devient nécessaire. Exemple, supposons que nous ayons créé un programme dont le source est réparti sur trois fichiers PART1.FTH, PART2.FTH et PART3.FTH:
-on peut le compiler en tapant INCLUDE PART1 INCLUDE PART2 INCLUDE PART3 depuis le clavier.
-on peut créer un autre fichier, nommé GENERAL par exemple contenant les lignes suivantes:
INCLUDE PART1
INCLUDE PART2
INCLUDE PART3
puis compiler toute l'application en tapant INCLUDE GENERAL.
TURBO-Forth accepte jusqu'à huit niveaux d'imbrications de fichiers. Un même ficher peut appeler une infinité de sous-fichiers:
INCLUDE PART1
INCLUDE PART2
...etc...
INCLUDE PART1000
Tout fichier dont la compilation est achevée fait remonter les imbrications de fichiers d'un niveau dans la hiérarchie des imbrications.
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.
Exemple:
: .NBR ( n ---)
BASE @ >R
\ sauvegarde valeur initiale de BASE
DUP CR DECIMAL ." Dec: " 5 .R
\ affiche n en décimal
DUP CR HEX ." Hex: " 5 .R
\ puis en hexadéimal
CR OCTAL ." Oct: " 5 .R
\ et enfin en octal
R> BASE ! ;
\ restaure valeur initiale de BASE ( fin de définition )
EOF
Le mot .NBR affiche un nombre entier 16 bits signé sur trois lignes séparées en décimal, hexadécimal et octal, ceci quelque soit la base numérique initiale. Ex:2 BASE !
1010 .NBR affiche
Dec: 10
Hex: A
Oct: 12
Lors de la compilation de ce programme, les parties de définitions situées entre parentèses, celles comprises entre \ et la fin de ligne et celles écrites après EOF seront ignorées.
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. Le dernier mot défini est le premier de la liste affichée par l'exécution de WORDS. Exemple:
: MOT1 ;
: MOT2 ;
: MOT3 ;
WORDS affichera MOT3 MOT2 MOT1 ...suite du dictionnaire..
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:
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.
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à:)
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 levre les ambiguités entre homonymes.
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 affiche REGARDE MOT1 ...etc...
Pour oublier tous les mots définis depuis le lancement de TURBO-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
INCLUDE <fichier> \ ici donner nom de votre application
Si le contenu de 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 ; 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.
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:
1988 CONSTANT ANNEE Les variables sont définies à l'aide du mot VARIABLE:
VARIABLE 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:
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.
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 @:
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 !:
15 JOURS ! En fait, les mots @ et ! agissent sur n'importe quelle adresse
mémoire. Si vous tapez:
256 @ . FORTH affichera le contenu 16 bits des adresses 256 et 257 selon
le mécanisme suivant:
L'inversion des valeurs a et b est valable pour les versions
F83 tournant sur des systèmes équipés de microprocesseur Z80, 8080 ou 8086 (octet
de poids faible d'abord). Sur les autres systèmes, le mécanisme peut différer,
mais le résultat figurant au sommet de la pile de données sera identique.
Le mot ? combine l'action de @ et . et s'utilise comme suit:
16 JOURS ! Le mot +! incrémente le contenu d'une variable:
2 JOURS +! Pour décrémenter le contenu d'une variable, il suffit de l'incrémenter
avec une valeur négative:
-10 JOURS +! Si cette incrémentation ou décrémentation est d'une seule unité,
on utilisera de préférence les mots 1+! et 1-!:
JOURS 1+! JOURS ? affiche 9 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:
VARIABLE VIVANT Pour traiter sans équivoque les valeurs booléennes, on restreindra
les valeurs affectables à une variable 16 bits, considérée comme flag booléen,
les seules valeurs 0 ou -1.
Pour augmenter la lisibilité des programmes FORTH, deux constantes
pré-définies, TRUE et FALSE reprennent ces valeurs:
TRUE . affiche -1 Les affectations booléennes ont été simplifiées et peuvent être
exécutées par ON et OFF:
VIVANT ON .HERITAGE Le mot OFF peut aussi servir à remettre à zéro n'importe quelle
variable 16 bits ou emplacement mémoire 16 bits. Exemple:
VARIABLE SCRORE 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:
150000. 2CONSTANT JACKPOT Une variable double précision est définie par le mot 2VARIABLE:
2VARIABLE SCORE Une valeur double précision est affectée à une variable double
précision par le mot 2!:
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@:
SCORE 2@ D. affiche 120000 Il n'y a pas d'équivalent à +!, 1+!, 1-!, ON et OFF en 32 bits,
mais il est aisé de les définir soi-même:
: D+! ( d adr ---) 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:
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 $! comme suit:
" 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$.
A$ TYPE affiche TEST Le contenu d'une variable chaîne peut être modifié:
" CECI EST UN AUTRE TEST" A$ $! Pour concaténer une chaîne à une variable chaîne, utiliser APPEND$
comme suit:
" DE CONCATENATION" A$ APPEND$ Les mots $! et APPEND$ n'autorisent pas l'affectation d'un nombre
de caractères supérieur à la capacité maximale de la variable alphanumérique
définie par STRING.(Pour toutes les autres manipulations de chaînes, reportez-vour
au chapitres "caractères de chaînes")
Les mots d'exécution vectorisée sont définis par le mot de définition
DEFER. Pour en comprendre les mécanismes et l'intérêt à exploiter ce type de
mot, voyons plus en détail le fonctionnement de l'interpréteur interne du langage
FORTH.
Toute définition compilée par : (deux-points) contient une suite
d'adresses codées sur seize bits correspondant aux champs de code des mots précédemment
compilés. Au coeur du système FORTH, le mot EXECUTE admet comme paramètre ces
adresses de champ de code, adresses que nous abrégerons par cfa pour Code Field
Address. Tout mot FORTH a un cfa et cette adresse est exploitée par l'interpréteur
interne de FORTH:
' <mot> dépose le cfa de <mot> sur la pile de données.
Exemple:
' WORDS empile le cfa de WORDS. A partir de ce cfa, connu comme seule valeur littérale, l'exécution
du mot est provoquée par EXECUTE:
' WORDS EXECUTE exécute WORDS. Bien entendu, il aurait été plus simple de taper
directement WORDS. A partir du moment où un cfa est disponible comme
seule valeur littérale, il peut être manipulé et notamment stocké dans une variable:
VARIABLE VECTEUR affiche le cfa de WORDS stocké dans la variable VECTEUR
VECTEUR @ EXECUTE lance l'exécution du mot dont le cfa a été stocké dans la variable
VECTEUR puis remis sur la pile avant utilisation par EXECUTE.
C'est un mécanisme similaire qui est exploité par la partie
exécution du mot de définition DEFER. Pour simplifier, DEFER crée un en-tête
dans le dictionnaire, à la manière de VARIABLE ou CONSTANT, mais au lieu de
déposer simplement une adresse ou une valeur sur la pile, il lance l'exécution
du mot dont le cfa a été stocké dans la zone paramétrique du mot défini par
DEFER.
L'intialisation d'un mot défini par DEFER est réalisée par IS:
DEFER VECTEUR L'exécution de VECTEUR provoque l'exécution du mot dont le cfa
a été précédemment affecté:
VECTEUR exécute WORDS Un mot créé par DEFER sert à exécuter un autre mot sans faire
appel explicitement à ce mot. Le principal intérêt de ce type de mot réside
surtout dans la possibilité de modifier le mot à exécuter:
' DARK IS VECTEUR VECTEUR exécute maintenant DARK et non plus WORDS.
On utilise essentiellement les mots définis par DEFER dans deux
situations:
-définition d'une référence avant; Dans le premier cas, la définition d'une référence avant permet de surmonter
les contraintes de la sacro- sainte précédence des définitions. Dans le second cas, la définition d'un mot dépendant du contexte
d'exploitation permet de résoudre la plupart des problèmes d'interfaçage avec
un environnement logiciel évolutif, de conserver la portabilité des applications,
d'adapter le comportement d'un programme à des situations contrôlées par divers
paramètres sans nuire aux performances logicielles.
Contrairement à d'autres compilateurs, FORTH n'autorise pas la
compilation d'un mot dans une définition avant qu'il ne soit défini. C'est le
principe de la précédence des définitions:
: MOT1 ( ---) ... MOT2 ... ; génère une erreur à la compilation de MOT1, car MOT2 n'est pas
encore défini.
DEFER MOT2 Cette fois-ci, MOT1 a été compilé sans erreur. Il n'est pas nécessaire
d'affecter un cfa au mot d'exécution vectorisée MOT2. Ce n'est qu'après la définition
de (MOT2) que la zone paramétrique du MOT2 est mise à jour. Après affectation
du mot d'exécution vectorisée MOT2, MOT1 pourra exécuter sans erreur le contenu
de sa définition. L'exploitation des mots créés par DEFER dans cette situation
doit rester exceptionnel.
Les systèmes IBM et compatibles de type PC, XT, AT et PS peuvent
être interfacés avec toute sorte de terminaux ou cartes d'extension. Un des
interfaces les plus simples et les plus répandus est l'interface de liaison
série sur lequel on peut notamment connecter un MINITEL.
Techniquement, la liaison est réalisée en reliant le MINITEL
au PC via un cfble équipé coté MINITEL d'une fiche DIN 5 broches, coté PC d'une
fiche CANON 9 ou 25 roches. L'interfaçage logiciel FORTH entre le PC et le MINITEL
permettant d'exploiter cette liaison série, dépend de la primitive (RSEMIT)
à définir:
HEX Cette primitive envoie au port série le code ASCII correspondant
au paramètre empilé. On initialise le port COM1 ou COM2 en tapant la commande
suivante:
" COM1:1200" PASS PROGRAM MODE.COM pour le port série COM1: " COM2:1200"
PASS PROGRAM MODE.COM pour le port série COM2: Le programme MODE.COM est fourni avec votre disquette système
MSDOS. Si MODE.COM n'est pas dans le répertoire courant, indiquez le chemin
o- il est accessible:
" COM1:1200" PASS PROGRAM C:\DOS\MODE.COM Après initialisation du port série COM1: ou COM2:, on envoie
un caractère vers le port série comme suit:
ASCII A (RSEMIT) Si le MINITEL est raccordé au port série de votre PC et allumé,
vous devez voir apparaître la lettre A sur l'écran du minitel. Le mot EMIT du
langage FORTH est un mot d'exécution vectorisée, c'est à dire que l'on peut
mofifier le contenu de sa zone paramétrique:
' (RSEMIT) IS EMIT Tous les caractères normalement affichés sur l'écran du PC sont
envoyés vers le port série et visualisés sur l'écran du MINITEL.Mais les caractéristiques
de la transmission série ne permettent pas de traiter les codes ASCII à la même
cadence que sur le terminal vidéo du PC. Il y aura saturation de la transmission
si le débit des caractères est trop important. On y remédie en temporisant l'action
de (RSEMIT):
HEX DECIMAL Maintenant, l'écran du MINITEL reproduit exactement les caractères
ASCII du PC dont le code est situé dans l'intervalle 32..127. On peut définir
une nouvelle primitive qui affichera les caractères simultanément sur le PC
et le MINITEL:
HEX On peut poursuivre en faisant traduire les caractères du PC situés
dans l'intervalle 128..255 par des caractères approchants quand c'est possible,
dont voici la première ébauche:
HEX Les caractères accentués, exprimés par un code ASCII spécifique
sur PC, sont traduits en une séquence de trois codes vers le MINITEL. Après
achèvement de l'interfaçage logiciel, il reste à créer les définitions activant
et désactivant cet interfaçage:
: RS-ON ( ---) \ activation de la liaison série Avec un interfaçage complet en entrée et en sortie, il est possible
de développer une application tournant indifférement sur site PC ou à partir
d'un terminal relié au site central via le port série. La modification d'un
mot d'exécution vectorisée, EMIT dans notre exemple, peut s'appliquer à un programme
déjà compilé.
Si vous avez été, ou êtes encore, un pratiquant assidu du langage
BASIC, peut-être qu'une structure de la forme:
ON n GOSUB xxx1,xxx2,xxx3, etc... vous manque. FORTH permet de définir un mot à l'aide de CASE:
et dont le mécanisme est similaire. Alors que DEFER ne permet de définir qu'un
seul mot avec un seul vecteur associé, CASE: définit un mot auquel on associe
plusieurs vecteurs:
: MOT0 ... ; Les indices admis par MOTS sont situés dans l'intervalle [0..3[
(0 inclus à 3 exclus).
0 MOTS exécute MOT0 La sélection puis l'exécution d'un mot est réalisée par le paramètre
empilé avant exécution du vecteur à choix multiple défini par CASE:. Si le paramètre
est ors intervalle, un message d'erreur s'affiche lors de l'exécution du mot
défini par CASE:. En principe, les mots compilés dans un vecteur à choix multiple
ne peuvent être remplacés par d'autres mots.
On utilisera CASE: en remplacement de CASE.. OF.. ENDOF.. ENDCASE
chaque fois que cette structure comporte un trop grand nombre de choix et que
chaque choix peut être réduit à une définition séparée.
Comme on a pu le constater, Forth dispose de nombreux mots de
définition.A chaque mot de définition correspond un type d'action:
action deux-pooints, constante, variable, chaîne, etc...
Si la définition de procédures permet d'élaborer
un code exéccutable exteêmement compact, Forth va plus loin en
permettant aussi de définir de nouveaux mots de définition.Exemple:
: PAVE-GRIS ( ---)
Dans cest deux définition, la seule différence
réside dans le paramêtre empilé avant l'action EMIT. Ec
créant un nouveau mot de définition, PAVE par exemple, on pourra
réduite le code exécutable:
le mot de définition PAVE fonctionne comme le mot CONSTANT:
il prend le paramètre préalablement empilé et l'affecte
à la zone paramétrique du mot dont l'entête est créé
par CREATE. Une fois le mot créé, la partie de définition
sityée ente DOES> et ; définit l'action à exécuter
par le mot PAVE-GRIS ou PAVE-BLANC/ PAVE-GRIS affiche un caractère semi-graphique grisé. l'actiojn de création paut être plus complexe, de
même que l'action à exécuter. En reprenant l'exemple ci-dessus,
on s'interdit de compiler un mot dont le code à affecter ne coresspondrait
pas à un caractère semi-graphique: Le mot de définition PAVE dispose maintenant d'une sécurité
à la compilation. ll refuse de créer un mot si le paramètre
qui doit lui être accecté dans sa zone paramétrique ne fait
pas partie des valeurs contenues dans le tableau GRAPHISMES. Pour compléter PAVE, on peut ausi rajouter une sécurité
à l'exécution. On peut par exemple interdire l'affichage du pavé
grisé sur les trous premières lignes de l'écran vidéo: Lorsque le mot créé par un mot de définition est exécuté,
il dépose sur la pile l'adresse de sa zone paramétrique. Cette
action est similaire à celle exécutée par une variable
définie par VARIABLE. Dans le cas des mots définis par PAVE, l'action
définie après DOES> récupère la donnée
stockée à cette adresse et affiche le caractère correspondant. ------------------------------------ Pour les petits futés..... un test de mise au point. Donc le premier qui donne le programme ci dessous fonctionnel
aura son nom dans le générique du site.
DEFER .P \ définition du vecteur .P Pour ceusses qui veulent en savoir un peu plus sur le morse -- hautdepage -- page
d'accueil --
: REGARDE TEST1 ;
HERE FENCE !
FORGET TEST1 affiche Partie dictionnaire
protégée D. Constantes et variables simple précision
JOURS @ . affiche 15
JOURS ? affiche 16
JOURS ? affiche 18
JOURS ? affiche 8
JOURS 1-! JOURS ? affiche 8
: .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
FALSE . affiche 0
TRUE VIVANT !
.HERITAGE affiche Attendez encore pour hériter
affiche Attendez encore pour hériter
VIVANT OFF .HERITAGE affiche Maintenant, courrez chez le notaire
10 SCORE +! SCORE ? affiche 10
SCORE OFF SCORE ? affiche 0 E. Constantes et variables double précision
DUP >R \ duplique et sauvegarde adresse de variable
2@ \ empile valeur 32 bits contenue à adresse adr
D+ \ fait la somme 32 bits
R> 2! ; \ range résultat 32 bits à l'adresse adr
: D1+! ( adr ---)
>R 1. R> D+! ;
: D1-! ( adr ---)
>R -1. R> D+! ;
: D-ON ( adr ---)
>R TRUE S>D R> 2! ;
: D-OFF ( adr ---)
>R FALSE S>D R> 2! ; F. Définition de variables alphanumériques
\ syntaxe: contenu contenant affectation
A$ TYPE affiche CECI EST UN AUTRE TEST
A$ TYPE affiche CECI EST UN AUTRE TEST DE CONCATENATION G. Les mots d'exécution vectorisée
1. Création et initialisation d'un vecteur
' WORDS VECTEUR !
VECTEUR ?
' WORDS IS VECTEUR
- définition d'un mot dépendant du contexte d'exploitation. 2. Définition d'une référence avant
: MOT2 ( ---) ............ ;
: MOT1 ( ---) ... MOT2 ... ;
: (MOT2) ( ---) ............ ;
' (MOT2) IS MOT2 3. Dépendance envers le contexte d'exploitation
: (RSEMIT) ( n ---)
03F8 PC! ;
\ 03F8 pour port COM1: ; 02F8 pour port COM2:
DECIMAL
: (RSEMIT) ( n ---)
03F8 PC!
\ 03F8 pour port COM1:; 02F8 pour port COM2:
100 MS ;
\ délai 100 millisecondes, ajuster éventuellement FUDJE
\ par n FUDGE !
' (RSEMIT) IS EMIT
: (RSEMIT) ( n ---)
DUP (EMIT) \ affichage sur écran vidéo PC
03F8 PC! \ 03F8 pour port COM1:; 02F8 pour port COM2:
100 MS ; \ délai 100 millisecondes, ajuster éventuellement FUDJE par n FUDGE
! DECIMAL
' (RSEMIT) IS EMIT
: (RSEMIT) ( n ---)
DUP (EMIT) \ affichage sur écran vidéo PC
CASE
ASCII é OF ... ENDOF
ASCII è OF ... ENDOF
ASCII ê OF ... ENDOF ENDCASE
03F8 PC! \ 03F8 pour port COM1:; 02F8 pour port COM2:
100 MS ; \ délai 100 millisecondes, ajuster éventuellement FUDJE par n FUDGE
! DECIMAL
' (RSEMIT) IS EMIT
['] (RSEMIT) IS EMIT ;
: RS-OFF ( ---) \ désactivation de la liaison série
['] (EMIT) IS EMIT ; H. Les vecteurs à choix multiples
: MOT1 ... ;
: MOT2 ... ;
3 CASE: MOTS ( n --- en exécution)
MOT0 MOT1 MOT2 ;
1 MOTS excéute MOT1
2 MOTS exécute MOT2
I. Définition de mots de définition
177 emit ;
: PAVE-BLANC ( ---)
219 emit ;
177 PAVE PAVE-GRIS compile PAVE-GRIS
155 PAVE PAVE-JAUNE affiche "Caractère non semi-graphique"
177 PAVE PAVE-GRIS
0 0 AT PAVE-GRIS n'affiche rien
5 5 AT PAVE-GRIS affiche un pavé gris
--------------------------------
-----------------------------
------------------------
-------------
(Bien entendu Bruno tu n'aura pas droit de poster ta réponse
le premier car tu auras le texte avant les autres.)
soit à générer une suite de traits et de points correspondants au code Morse
des caractères A..Z,0..9 et caractère espace:
DEFER .T \ définition du vecteur .T
: POINT ( ---) \ affiche un point
ASCII . EMIT ;
: TRAIT ( ---) \ affiche un trait
ASCII - EMIT ;
' POINT IS .P \ initialisation du vecteur .P
' TRAIT IS .T \ initialisation du vecteur .T
: .BLANC ( ---) \ espace en MORSE ;
...etc...
37 CASE: (.MORSE) ( n ---)
.BLANC .A .B .C .D .E .F .G .H .I .J . K .L .M .N .O .P .Q .R .S .T .U .V
.W .X .Y .Z .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 ;
http://www.multimania.com/f5tci/