Un vrai FORTH 32 bits avec ESP32Forth

publication: 16 juillet 2022 / mis à jour 17 juillet 2022

Read this page in english

 


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:

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