Forth/Conserver des données
N'importe quel programme a besoin de conserver des informations en mémoire. Un jeu vidéo, par exemple, a besoin à tout moment de pouvoir accéder à des données telles que la vie, la force ou la position d'un personnage. De telles données sont appelées des variables : les valeurs sont entreposées à un certain emplacement dans la mémoire, emplacement qu'on pourra lire (accéder à une variable) ou sur lequel on pourra écrire (modifier une variable).
En bricolant nous-mêmes
[modifier | modifier le wikicode]Manipuler la mémoire est une opération triviale en Forth. Pour l’heure, la mémoire que nous allons être ammenés à manipuler est celle du dictionnaire, c'est-à-dire l'espace où nos mots sont conservés sous forme compilée (ce n'est donc absolument pas au même endroit que la pile).
DP, @ et !
[modifier | modifier le wikicode]Un mot permet d'obtenir l'adresse du prochain emplacement libre dans le dictionnaire ; c’est à cet emplacement que nous stockerons nos données. Ce mot est HERE
(ici). Un appel à HERE
place donc une adresse sur la pile :
HERE . -1221991536 ok
Cette adresse est libre. Ça ne signifie pas qu’il n'y a rien d'écrit à cet emplacement, mais plutôt que ce qui est écrit n'a pas d'importance et n’est pas défini. Vous savez désormais que le dictionnaire se remplit au fur et à mesure qu'on y ajoute des définitions, par conséquent la valeur que nous donne HERE
est loin d’être constante : à chaque fois qu'on crée un mot ou une variable, on progresse dans la mémoire :
HERE ok : TEST ; ok HERE SWAP - . 28 ok
Que se passe-t-il ici ?
- on pose l'adresse du prochain espace libre du dictionnaire sur la pile ;
- on défini un nouveau mot, donc on repousse l'adresse du prochain espace libre ;
- on soustrait l'ancienne adresse à l'actuelle, et on s'aperçoit que
HERE
pointe 28 octets plus loin dans la mémoire : notre motTEST
a occupé 28 octets du dictionnaire.
Et si on regardait la définition de HERE
?
SEE HERE : HERE DP @ ; ok
Que peut bien signifier DP @
? C'est très simple :
DP ( -- addr )
- Empile l'adresse qui contient l'adresse du prochain emplacement libre du dictionnaire.
@ ( addr -- value )
- fetch lit la valeur « value » située à addr, et la pose sur la pile.
D'où :
HERE ( -- addr )
- Empile l'adresse du prochain espace libre du dictionnaire.
Il est maintenant important de saisir une nuance :
HERE
récupère une valeur (l'adresse du prochain espace libre) à une adresse donnée, et la pose sur la pile ;DP
donne cette adresse.
« DP » signifie Dictionnary Pointer, le « pointeur du dictionnaire », parce qu’il pointe sur un emplacement du dictionnaire.
Bien que répandu, ce mot n'est pas standard et il est tout à fait possible que DP
porte un autre nom si vous n'utilisez pas GForth. Pour le connaître, utilisez SEE
s'il est disponible ou alors référez-vous au manuel de votre système.
Nous savons désormais lire des informations grâce à @
(fetch). Étudions maintenant le mot qui nous permet d'écrire de l'information :
Rien de bien compliqué :
42 HERE ! ok HERE @ . 42 ok
Il est toutefois nécessaire d’être prudent lorsqu'on utilise !
(store), il ne vérifie parfois pas la validité de l'adresse, auquel cas vous pourriez par mégarde écraser des données importantes pour le système.
Amusons-nous à éditer DP
:
0 DP ! ok HERE . 0 ok
Voilà, DP
pointe désormais vers l'adresse 0. Comme un certain nombre de mots se basent sur HERE
pour fonctionner, cette petite fantaisie risque bien de paralyser rapidement le système Forth. Ne faites donc pas n’importe quoi avec store !
CREATE
[modifier | modifier le wikicode]Cette section est difficile à comprendre. Même si elle ne fait intervenir que des notions du niveau indiqué, il est conseillé d'avoir du recul sur les notions présentées pour bien assimiler ce qui suit.
En Forth, une variable est un mot qui pointe vers un endroit en mémoire : sa valeur. DP
est donc une variable :
- de nom DP ;
- qui vaut
DP @
, la prochaine adresse libre du dictionnaire.
Vous savez placer une information en mémoire, mais vous ne savez pas associer cet espace à un nom ; c’est le travail du mot CREATE
:
CREATE ( "<spaces>name" -- )
- Prépare le terrain pour l'affectation. Associe name au prochain emplacement libre dans la mémoire.
Un exemple pour mieux comprendre :
CREATE QUATRE ok 4 HERE ! ok HERE @ . 4 ok QUATRE @ . 4 ok
TROIS
permet donc de récupérer une adresse bien précise, celle qui suivait la sienne propre lors de sa création via CREATE
. Définissons une autre variable :
CREATE DEUX ok 2 HERE ! ok DEUX @ . 2 ok QUATRE @ . -1222577264 ok
Aïe, en définissant DEUX
(qui vient se placer sur HERE
) on a écrasé la valeur vers laquelle pointait QUATRE
; désormais QUATRE
pointe sur l'adresse de DEUX
! Afin d’éviter cela, il suffit d'avancer DP
en conséquence :
CREATE QUATRE 4 HERE ! ok CELL DP +! ok CREATE DEUX 2 HERE ! ok QUATRE ? DEUX ? 4 2 ok
Normalement, +!
(plus-store) doit vous déconcerter. Il signifie « stocker en additionnant » :
+! ( value addr -- )
- Ajoute value à la valeur contenue en addr.
C'est donc un raccourci pour TUCK @ + SWAP !
.
? ( addr -- )
- What imprime en sortie la valeur contenue en addr.
C'est donc un raccourci (non standard, mais généralement défini) pour @ .
(fetch dot) ; je l’utiliserai régulièrement.
Et si on automatisait tout cela ? Définissons le mot VAR
, qui crée une variable et l'initialise avec une valeur donnée :
: VAR ( value "<spaces>name" -- ) CREATE HERE ! CELL DP +! ;
4 VAR QUATRE ok 2 VAR DEUX ok QUATRE ? DEUX ? 4 2 ok 2 DEUX +! DEUX ? 4 ok
Pas mal, n'est-ce pas ? Mais il est clair que tout ces préparatifs sont franchement agaçants pour une opération aussi triviale que la définition d'une variable. Comparez avec un code Perl :
my ($quatre, $deux) = (4, 2);
Y'a pas photo, c’est beaucoup plus simple que de réécrire VAR
dans chacun de nos programmes. Heureusement, la norme impose aux systèmes Forth un ensemble de mots très pratiques pour créer des variables, et même plus.
En Forth standard
[modifier | modifier le wikicode]Reprenons notre définition du mot VAR
:
: VAR ( value "<spaces>name" -- ) CREATE HERE ! CELL DP +! ;
Allouer de la mémoire
[modifier | modifier le wikicode]Lorsque nous souhaitons conserver une information, nous la plaçons au premier espace libre et nous avançons de x le pointeur du dictionnaire : on dit qu'on a alloué x de mémoire.
Notre façons de faire (CELL DP +!
) est loin d’être irréprochable :
- que se passe-t-il s'il n'y a plus de mémoire disponible ?
- à suivre
Pour cela, ANS Forth défini le mot ALLOT
: