LE COMPILATEUR
A. Primitives de définition.
Mot général de création d'un nouveau mot dans le dictionnaire. Le mot CREATE
prend dans le flot d'entrée un mot qu'il compile en nouvel en-tête dans le
vocabulaire courant. Les champs de vue, de lien et de nom sont ajustés selon
HEADER.
Le code exécutif (cfa) est initialisé de manière à déposer sur la pile
l'adresse du champ de paramètres (pfa) du nouveau mot, ceci comme pour une
variable.
Toutefois, il n'y a encore aucune compilation d'un champ de paramètres, si
bien que CREATE se doit d'être complété par des mots spécifiques de
compilation.Le mot CREATE s'utilise aussi bien en exécution pour créer un
mot d'une structure particulière, qu'en compilation pour définir un mot de
définition. Bien souvent, le code exécutif proposé par CREATE est redéfini
par un ou plusieurs "mot-codifiant" d'exécution, si bien que CREATE est
fréquemment retrouvé dans les structures suivantes:
CREATE ( <nom> si exécution ) création d'un en-tête
<<..mots de compilation..>> du type C, , ALLOT [
<mot-codifiant> du type DOES> ;CODE ;USES
<<..mots d'exécution..>> en haut ou bas niveau
Les exemples sont innombrables, aussi bien dans FORTH lui-même, de CONSTANT
à : en passant par DEFER, VOCABULARY ou la table CC1, que dans les
possibilités de nouvelles structures. Nous choisirons volontairement un
exemple très simple: soit à définir des variables du type FIG-FORTH; en FIG,
une variable est définie avec une valeur initiale n VARIABLE <nom>, alors que
le FORTH 83-Standard adopte l forme VARIABLE <nom> avec toute valeur
initialisée à zéro. La différence ne dépasse guère une affaire de goùt dans
la mesure où une variable est faite pour varier.
Si nous avons besoin d'une seule variable de ce type, nous pourrions utiliser
CREATE en exécution:
CREATE NOMBRE-DE-CARTES 54 ,
NOMBRES-DE-CARTES ? affiche 54
S'il nous faut plusieurs variables de ce type, nous créerons un mot de
définition:
: FIG-VAR CREATE , DOES> ;
28 FIG-VAR DOMINOS
64 FIG-VAR CASES
DOMINOS ? affiche 28
CASES ? affiche 64
A noter que pour cet exemple, la partie exécution des mots définis est
réduite au minimum.
Mot d'exécution immédiate utilisé dans une définition de type 'deux-points'
d'un mot de définition. Le mot DOES> marque le début de la partie exécution,
définie en langage de haut niveau, des mots ultérieurement définis dans une
définition du type:
: NOMDEF ... CREATE ... DOES> ... ;
La séquence faisant suite à DOES> doit partir du principe que l'exécution
d'un mot défini par NOMDEF débute par le dépôt sur la pile de données de
l'adresse de son champ paramétrique (pfa). Exemple, soit à définir des mots
affichant des messages:
1ère étape: définition du mot générique
: MESSAGE CREATE ," DOES> COUNT TYPE ;
- entre CREATE et DOES> est écrite la partie compilation (ici compilation
d'une chaîne implicite).
- après DOES> est écrite la partie exécution (ici affichage de la chaîne
compilée.
2ème étape: définitions des mots de seconde génération
MESSAGE TEST Ceci est un test "
MESSAGE TRUC y a comme un truc "
3ème étape: exécution des mots de seconde génération
TEST affiche 'Ceci est un test '
TRUC affiche 'y a comme un truc '
Mot d'exécution immédiate terminant la définition "deux-points" d'un mot de
définition de haut niveau avec le passage direct en bas niveau de la
procédure d'exécution des mots de la deuxième génération. Le mot ;CODE s'utilise selon un schéma en deux étapes commun aux mots de
définition.
Première génération, création d'un mot de définition:
: NOMDEF nomex1 .. nomexn ;CODE code-machine
Entre : NOMDEF et ;CODE, la partie de définition des futurs mots est
compilée, notamment la constitution de leurs corps de paramètres (pfa).
Après ;CODE, la partie exécution de ces futurs mots est compilée, c'est à
dire leur code exécutif (cfa). A la différence des mots de définition
utilisant DOES> (voir ce mot), la partie exécution est ici définie en code
machine et se termine ordinairement par une procédure de retour de bas niveau
(NEXT ou assimilé).
Seconde génération, création des mots dérivés:
NOMDEF NOM
L'exécution de NOM renvoie au code qui suit immédiatement le ;CODE de NOMDEF.
Tout comme ; le mot ;CODE vérifie la profondeur de pile, valide la
définition en cours, compile une fin de définition rompant la séquence NEST,
à savoir le mot (;CODE) qui définira les cfa de seconde génération, et fait
passer le système en mode exécution. De plus, le vocabulaire ASSEMBLER
devient vocabulaire de recherche.
Exemple volontairement simpliste; soit à définir des mots servant de
pointeurs dans un vocabulaire, gardant un numéro d'ordre mais n'ayant aucune
action particulière. La première génération se définira:
: POINTEUR ( n ---)
CREATE ,
;CODE NEXT JMP
Et la seconde génération sera de la forme:
1 POINTEUR BIDON
2 POINTEUR QUE-SAIS-JE
etc...
Les mots BIDON et QUE-SAIS-JE ne font rien lors de leur exécution. On peut
toutefois récupérer leur numéro d'ordre compilé dans leur pfa:
' QUE-SAIS-JE >BODY ? affiche 2
Une séquence réalisée depuis ;CODE est achevée par ;C.
Mot d'exécution immédiate terminant la définition "deux-points" d'un mot de
définition de haut niveau, avec passage indirect en bas niveau de la
procédure d'exécution des mots de seconde génération. Le mot ;USES s'utilise
comme ;CODE (voir ce mot) à la différence qu'il est suivi non pas d'un code
exécutif, mais de l'adresse où se situe ce code.
Son action est identique à celle de ;CODE sauf qu'il compile sa primitive
(;USES). Là encore, le vocabulaire ASSEMBLER devient vocabulaire de
recherche. Il s'utilise dans une séquence du type:
: NOMDEF nomex1 ... nomexn ;USES adr ,
(notez la virgule qui compile l'adresse du code exécutif des mots que
définira NOMDEF). Exemple, le mot POINTEUR de l'exemple de ;CODE peut aussi s'écrire:
: POINTEUR CREATE , ;USES NEXT ,
Le mot ;USES remplace ;CODE quand le code exécutif est déjà défini.
B. Mots de définition.
Mot de définition d'une constante 32 bits. Est utilisé sous la forme:
3.14159 2CONSTANT PI
A l'exécution, le mot <nom> empile la valeur d qui lui a été attribuée lors
de sa définition:
PI D. affiche 314159
Mot de définition d'une variable 32 bits. Est utilisé sous la forme:
2VARIABLE ESSAI
Le contenu de la variable ainsi définie est nul. L'exécution de <nom> dépose
sur la pile l'adresse de son champ paramétrique. Exemple:
123.456 ESSAI 2!
ESSAI 2@ D. affiche 123456
2VARIABLE COUPLE
2 3 COUPLE 2! (utilisée pour 2 valeurs 16 bits)
COUPLE 2@ . . affiche 3 2
Mot de création le plus utilisé en FORTH. Il définit un mot <nom> dit mot
"deux-points" sous la forme:
: NOM nomex1 nomex2 ... nomexn ;
L'exécution ultérieure de NOM réalise l'enchainement d'exécution des mots
compilés dans sa définition "deux-points". Le processus de chaînage est
réalisé par la routine système NEST (ne pas confondre avec NEXT) à laquelle
renverra le code exécutif (cfa) de NOM.
Après : NOM, l'interpréteur entre en mode compilation. Tous les mots non
immédiats sont compilés dans la définition, les nombres sont compilés sous
forme litérale. Seuls les mots immédiats ou placés entre crochets (mots [ et
]) sont exécutés pendant la compilation pour permettre de contrôler celle-ci.
Une définition "deux-points" reste invalide, c'est à dire non inscrite dans
le vocabulaire courant, tant que l'interpréteur n'a pas exécuté ; ou ;CODE
ou ;USES
Lors d'une définition "deux-points", le vocabulaire pointé par le contenu de
CURRENT recevant les définiions en cours devient également le premier
vocabulaire, pointé par le contenu de CONTEXT, de recherche.
L'ouverture d'une définition "deux-points" s'accompagne d'une sauvegarde de
la profondeur de la pile dans la variable CSP pour permettre un contrôle des
structures de compilation en fin de définition. Le mot : n'est pas immédiat
en F83.
Compile et réexécute un code FORTH sans nom puis l'oublie.
Mot d'exécution immédiate terminant habituellement la compilation d'une
définition "deux-points". Un contrôle de la compilation est effectué et un
message d'erreur est renvoyé si la profondeur de la pile, sauvegardée dans
CSP, n'est pas identique à celle obtenue en fin de compilation.
Si la compilation est incorrecte, le mot est achevé par compilation de la
routine UNNEST dont le rôle est de suspendre le chaînage par NEST des mots
compilés. Dans le cas contraire, la définition est ensuite validée dans le
vocabulaire pointé par CURRENT et le système sort du mode compilation pour
revenir en mode exécution.
Mot de définition créant un vecteur à choix multiple. Le mot CASE: est précédé du nombre de mots inclus dans la définition <nom>. Lexécution de nom précédé du rang du mot à exécuter lance le mot de rang n, le premier mot exécutable étant de rang nul.L'exécution de <nom> avec un paramètre sityé en dehors de l'intervalle utilisé pour la définition de <nom> provoque une erreur d'exécution. Exemple d'utilisation:
80 STRING a$(0)
" je suis la première chaîne" a$(0) $!
80 STRING a$(1)
" je suis la chaîne 02" a$(1) $!
80 STRING a$(10)
" Je suis la dernière chaîne" a$(10) $!
11 CASE: chaine
a$(0) a$(1) ... a$(10) ;
3 chaine TYPE
affiche je suis la troisième chaîne
Mot de définition d'un mot de bas niveau. S'utilise sous la forme:
CODE <nom> ... code machine ... END-CODE
Code crée un en-tête <nom> dans le dictionnaire dont le code exécutif (cfa)
pointe directement son champ paramétrique (pfa) où est compilé le code
machine d'exécution de <nom>. Ce code se termine habituellement par une
procédure de retour de bas niveau (NEXT ou assimilé). Le mot CODE sauve
temporairement le vocabulaire de contexte qui est remplacé par ASSEMBLER.
Une définition créée par CODE doit être validée par END-CODE qui rétablit le
vocabulaire de contexte. Exemple:
CODE BDOS ( n fonction --- paramètre retour facultatif)
H POP D POP B PUSH L C MOV 5 CALL
0 H MVI A L MOV B POP HPUSH JMP END-CODE
Mot de définition d'une constante seize bits. A l'exécution, <nom> dépose
sur la pile de données la valeur attribuée lors de sa définition. Exemple:
365 CONSTANT JOURS/AN
JOURS/AN . affiche 365
Mot de définition de mot d'exécution vectorisée. Un mot d'exécution
vectorisée permet l'exécution de plusieurs définitions différentes par appel
d'un même nom, le code d'exécution de chaque définition devant être au
préalable attribuée en tant que vecteur au mot d'exécution vectorisée. S'utilise sous la forme:
DEFER <nom-vecteur>
A l'exécution, <nom-vecteur> exécute le mot dont le cfa est rangé dans la
cellule 16 bits du champ paramètre de <nom-vecteur>. La vectorisation de
<nom-vecteur> est réalisée en exécution par le mot IS:
' <nomex> IS <nom-vecteur>
ou
: .... ['] <nomex> IS <nom-vecteur> ... ;
Tant que <nom-vecteur> n'est pas activé par un IS, son exécution ré-
initialise le système avec un message d'erreur (voir CRASH).
Le concept de mots d'exécution vectorisé introduit dans le FORTH 83-Standard
est d'une importance théorique considérable. Les mots "diférés" facilitent
l'adaptation et la portabilité du système à son environnement, notamment dans
la gestion des entrées-sorties.
Mais les mots d'exécution vectorisée ouvrent de plus vastes perspectives
encore: algorithmique descendante (du global vers l'élémentaire) contre
algorithmique ascendante habituelle, modularité, réentrance et références
croisées, auto-compilation, méta-compilation... nous en oublions
certainement.
Exemple, soit un mot convivial AIDE destiné à porter secours à un utilisaeur
fatigué de tripoter son manuel; nous envisagerons qu'AIDE puisse être exécuté
à tout moment par appui sur une touche de fonction. Ne lésinons pas, la
touche sera scrutée en multi-tfche et l'écran d'aide placé dans une fenêtre
temporaire, qu'en dites-vous?
Il est évident qu'AIDE sera différent, donc "différé" (defered), selon le
programme ou la partie de programme en cours. Le problème est simple:
DEFER AIDE
AIDE sera vectorisé tour à tour à des mots du type:
: HELP ." les mots disponibles sont: " CR WORDS ;
: ASSISTE ." répondez par O ou N " ;
: .REGLES-DU-JEU 1 LIST ;
: FINI ." le programme est terminé! " ['] HELP IS AIDE ;
etc...
' ASSISTE IS AIDE
AIDE affiche 'répondez par O ou N '
' FINI IS AIDE
exécutez deux fois AIDE ...
--- <mot>
Définit un mot à partir duquel les définitions seront oubliées. Ce mot a
l'avantage de permettre la réinitialisation du dictionnaire à un état
pré-défini aussi bien en interprétation qu'a partir de l'exécution d'une
définition. Exemple:
MARK REVIENS HERE FENCE !
L'exécution de REVIENS supprime tous les mots définis après REVIENS, que ce
mot soit utilisé directement ou dans une définition compilée ultérieurement.
Crée une variable alphanumérique en réservant un espace mémoire de n
caractères pour recevoir une chaîne de caractères. A l'exécution, le mot
<mot$> dépose sur la pile de données l'adresse et la longueur de la chaîne
alphanumérique qui lui a été affectée par $!. Exemple:
80 STRING A$ crée une variable alphanumérique A$
" Bonjour " A$ $! affecte une chaîne à A$
A$ TYPE affiche le contenu de A$: "Bonjour"
Crée un en-tête dans le dictionnaire. L'exécution du mot ainsi défini dépose
sur la pile de données l'adresse de son champ paramétrique. Le contenu d'une
variable est initialisé à zéro lors de sa définition. Exemple:
VARIABLE SCORE 10 SCORE !
SCORE ? affiche 10
5 SCORE +! SCORE ? affiche 15
Mot de définition d'un nouveau vocabulaire. En 83-STANDARD, les vocabulaires
ne sont plus déclarés d'exécution immédiate. La déclaration d'un vocabulaire
est de la forme:
VOCABULARY FPACK
La définition des mots appartenants à ce nouveau vocabulaire doit être
sélectionnée en tapant:
FPACK DEFINITIONS
Les vocabulaires sont liés dans un ordre précis, celui de leur définition.
Normalement, on ne peut faire appel à une définition d'un autre vocabulaire
sans une manipulation hasardeuse. C'est pourquoi, en 83-Standard, on peut
modifier l'ordre de recherche dans les différents vocabulaires et le
vocabulaire FORTH. Ainsi, la sélection de l'ordre de recherche est réalisée
à l'aide des mots ONLY et ALSO. ONLY réduit l'ordre de recherche au minimum.
La déclaration des vocabulaires de recherche se fait ensuite dans l'ordre
désiré. Enfin, le mot ALSO précise le premier vocabulaire de recherche
et de définition. Exemple:
ONLY FORTH EDITOR ALSO FPACK DEFINITIONS
sélectionne une recherche de mot dans le vocabulaire FPACK puis FORTH et
EDITOR.
ONLY FORTH ALSO FPACK DEFINITIONS
réduit cet ordre de recherche aux vocabulaires FPACK et FORTH. Les nouvelles
définitions sont rajoutées au vocabulaire FPACK.
ONLY FORTH ALSO DEFINITIONS
réduit l'ordre de recherche au seul vocabulaire FORTH et les nouvelles
définitions sont rajoutées au vocabulaire FORTH. Le fait que les noms de
vocabulaires ne soient plus immédiats permet d'intégrer les précédentes
séquences au sein de définitions. Exemple:
: SETUP ONLY FORTH ALSO FPACK DEFINITIONS ;
L'ordre de recherche peut être consulté à tout moment à l'aide du mot ORDER.
C. Contrôle de compilation.
Force la compilation d'un mot immédiat dans une définition en cours de
compilation. Le mot à compiler est situé après ce mot. Exemple:
: MOTIMM ." Je suis immediat" CR ; IMMEDIATE
: UTILISE CR [COMPILE] MOTIMM ;
UTILISE affiche Je suis immediat
De nombreux mots du système FORTH sont immédiats, en particulier tous les
mots utilisés pour les structures de contrôle, tels IF, ELSE, THEN, BEGIN
etc...
Compile dans le dictionnaire le cfa du mot qui le suit. S'utilise dans des
mots d'exécution immédiate. Pour exemple, reportez-vous aux définitions des
mots tels IF, THEN, UNTIL, .", etc...
Marque le mot le plus récemment défini comme mot d'exécution immédiate,
lequel, lors d'une séquence de compilation, sera exécuté et non compilé.
Exemple:
: OUILLE ." OUILLE " ; IMMEDIATE
: AIE ." AIE " ;
: BOBO OUILLE AIE ; affiche OUILLE en compilation
BOBO affiche AIE ( et pas OUILLE, dur non ?)
Au travers d'exemples apparement futiles, les mots IMMEDIATE COMPILE ET [COMPILE] constituent la clé de voûte du compilateur FORTH. !voici un cas très concret. Soit à définir un mot APPEL", utilisable indifférement en interprétation oi en comilation, qui est chargé de déclenché un numéro téléphonique sur un Minitel M10 M12 ou M2:
HEX
: (APPEL") ( str ---)
57 PRO1 \ raccrochage de la ligne
53 PRO1 \ prise de la ligne
2000 MS \ attente 2 secondes
61 5C 53 PRO3 \ aiguillage module téléphonique
5000 MS \ attente 5 secondes
CONNEXION ;
: APPEL"
STATE @
IF COMPILE (") ," \ compiler la chaîne
COMPILE (APPEL")
ELSE ASCII " PARSE
(APPEL")
THEN ; IMMEDIATE
Le mot APPEL" a deux modes de fonctionnemnt, contrôlés par l'état de STATE (vrai=compilation, faux=interprétation). En interprétation, APPEL" est utilisable directement
APPEL" 3614"
décroche la ligne et appelle le 3614, puis passe en connexion télématique.
: TELETEL2
APPEL " 3614" ;
comile une chaîne. La décompilation de TELETEL2 affiche:
: T2
(") 3614
(APPEL") ;
Le mot APPEL" est remplacé par un compilation de chaîne et le mot (APPEL").
Définition de PRO1 PRO2 et PRO3 et CONNEXION:
HEX
: PRO1 1B EMIT 39 EMIT EMIT ;
: PRO2 1B EMIT 3A EMIT SWAP EMIT EMIT ;
: PRO3 1B EMIT 3B EMIT >R SWAP SWAP EMIT EMIT R> EMIT ;
: CONNEXION
68 PRO1 ;
: (APPEL")
57 PRO1
53 PRO1 1000 MS
61 5C 53 PRO3 TYPE 5000 MS CONNEXION ;
DECIMAL
-- hautdepage -- sommaire
-- page d'accueil --