LE COMPILATEUR

A. Primitives de définition.

CREATE --- <nom>
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.

DOES> --- imm F83
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 '
;CODE --- imm F83
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.

;USES --- imm
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.

2CONSTANT d --- <nom>
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
2VARIABLE --- <nom>
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
: --- <nom> F83
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.

; --- imm F83
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.

CASE: --- <nom>
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

CODE --- <nom> F83
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
CONSTANT n --- <nom> F83
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
DEFER --- mot
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 ...

MARK ---<mot>
--- <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.

STRING n --- <mot$>
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"
VARIABLE --- <mot> F83
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
VOCABULARY --- <nom> F83
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.

[COMPILE] --- mot F83
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 --- <nomex> F83
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...

IMMEDIATE --- F83
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 --