Un vrai FORTH 32 bits avec ESP32Forth
publication: 16 juillet 2022 / mis à jour 17 juillet 2022
Introduction
ESP32Forth est un vrai FORTH 32 bits. Qu'est-ce que ça signifie?
Le langage FORTH privilégie la manipulation de valeurs entières. Ces valeurs peuvent être des valeurs littérales, des adresses mémoires, des contenus de registres...
Les valeurs sur la pile de données
Au démarrage de ESP32Forth, l'interpréteur FORTH est disponible. Si vous entrez n'importe quel nombre, il sera déposé sur la pile sous sa forme d'entier 32 bits:
35
Si on empile une autre valeur, elle sera également empilée. La valeur précédente sera repoussée vers le bas d'une position:
45
Pour faire la somme de ces deux valeurs, on utiolise un mot, ici +
:
+
Nos deux valeurs entières 32 bits sont additionnées et le résultat est déposé sur la pile.
Pour afficher ce résultat, on utilisera le mot .
:
. \ display 80
En langage FORTH, on peut concentrer toutes ces opérations en une seule ligne:
35 45 + . \ display 80
Contrairement au langage C, on ne définit pas de type int8 ou int16 ou int32.
Avec ESP32Forth, un caractère ASCII sera désigné par un entier 32 bits, mais dont la valeur sera bornée [32..256[. Exemple:
67 emit \ display C
Les valeurs en mémoire
ESP32Forth permet de définir des constantes, des variables. Leur contenu sera toujours au format 32 bits. Mais il est des situations où ça ne nous arrange pas forcément. Prenons un exemple simple, définir un alphabet morse. Nous n'avons besoin que de quelques octets:
- un pour définir le nombre de signes du code morse
- un ou plusieurs octets pour chaque lettre du code morse
create mA ( -- addr ) 2 c, char . c, char - c, create mB ( -- addr ) 4 c, char - c, char . c, char . c, char . c, create mC ( -- addr ) 4 c, char - c, char . c, char - c, char . c,
Ici, nous définissons seulement 3 mots, mA
, mB
et mC
.
Dans chaque mot, on stocke plusieurs octets. La question est: comment va-t-on récupérer
les informations dans ces mots?
L'exécution d'un de ces mots dépose une valeur 32 bits, valeur qui correspond à l'adresse mémoire
où on a stocké nos informations morse. C'est le mot c@
qui va nous servir à extraire
le code morse de chaque lettre:
mA c@ . \ display 2 mB c@ . \ display 4
Le premier octet extrait ainsi va nous servir à gérer une boucle pour afficher le code morse d'une lettre:
: .morse ( addr -- ) dup 1+ swap c@ 0 do dup i + c@ emit loop drop ; mA .morse \ display .- mB .morse \ display -... mC .morse \ display -.-.
Il existe plein d'exemple certainement plus élégants. Ici, c'est pour montrer comment on manipule des valeurs 8 bits, nos octets, alors qu'on exploite ces octets sur une pile 32 bits.
Traitement par mots selon taille ou type des données
Dans tous les autres langages, on a un mot générique, genre echo
(en PHP) qui affiche n'importe quel
type de donnée. Que ce soit entier, réel, chaîne de caractères, on utilise toujors le même mot. Exemple:
$bread = "Baked bread"; $price = 2.30; echo $bread . " : " . $price; // display Baked bread: 2.30
Pour tous les programmeurs, cette manière de faire est LA NORME! Alors comment ferait FORTH pour cet exemple en PHP?
: bread s" Baked bread" ;
: price s" 2.30" ;
bread type s" : " type price type
\ display Baked bread: 2.30
Ici, le mot type
nous indique qu'on vient de traiter une chaîne de caractères.
Là où PHP (ou n'importe quel autre langage) a une fonction générique et un analyseur syntaxique, FORTH compense avec un type de donnée unique, mais des méthodes de traitement adaptées qui nous informent sur la nature des données traitées.
Voici un cas obsolument trivial pour FORTH, afficher un nombre de secondes au format HH:MM:SS:
: :## # 6 base ! # decimal [char] : hold ; : .hms ( n -- ) <# :## :## # # #> type ; 4225 .hms \ display: 01:10:25
J'adore cet exemple, car, à ce jour, AUCUN AUTRE LANGAGE DE PROGRAMMATION n'est capable de réaliser cette conversion HH:MM:SS de manière aussi élégante et concise.
Vous l'avez compris, le secret de FORTH est dans son vocabulaire.
Conclusion
FORTH n'a pas de typage de données. Toutes les données transitent par une pile de données. Chaque position dans la pile est TOUJOURS un entier 32 bits!
C'est tout ce qu'il y a à savoir.
Les puristes de langages hyper structurés et verbeux, tels C ou Java, crieront certainement à l'hérésie.
Et là, je me permettrai de leur répondre: pourquoi avez-vous besoin de typer vos données?
Car, c'est dans cette simplicité que réside la puissance de FORTH: une seule pile de données avec un format non typé et des opérations très simples.
Et je vais vous montrer ce que bien d'autres langages de programmation ne savent pas faire, définir de nouveaux mots de définition:
: morse: ( comp: c -- | exec -- ) create c, does> dup 1+ swap c@ 0 do dup i + c@ emit loop drop space ; 2 morse: mA char . c, char - c, 4 morse: mB char - c, char . c, char . c, char . c, 4 morse: mC char - c, char . c, char - c, char . c, mA mB mC \ display .- -... -.-.
Ici, le mot morse:
est devenu un mot de définition, au même titre
que constant
ou variable
...
Car FORTH est plus qu'un langage de programmation. C'est un méta-langage, c'est à dire un langage pour construire votre propre langage de programmation....
Legal: site web personnel sans commerce / personal site without seling