Previous Next Table of Contents

13. DICTIONNAIRE EXHAUSTIF KERNEL

13.1 Organisation

Les mots sont classés suivant leur ordre d'apparition dans le dictionnaire, ceci afin de bien comprendre son organisation et/ou d'effectuer une éventuelle méta-compilation. Utilisez la liste alphabétique pour retrouver la syntaxe d'un mot ou les listes thématiques pour connaître les mots dont vous disposez dans chaque famille.

Certaines définitions de mots diffèrent du fait des systèmes d'exploitation utilisés: SEDORIC pour l'ORIC ATMOS, STRATSED pour l'ORIC TELESTRAT. Dans ce cas, les deux versions sont détaillées.

13.2 Notations et conventions

Chaque mot de la version KERNEL du FORTH 83-STANDARD pour ORIC ATMOS sous SEDORIC et ORIC TELESTRAT est documenté de la manière suivante:

Les piles sont représentées conventionnellement:

La valeur au sommet de la pile étant le plus à droite.

L'état de la pile en entrant est séparé par deux tirets -- de l'état de la pile en sortant.

Seules les valeurs au sommet de la pile utiles au fonctionnement sont mentionnées.

S'il n'y a pas le même nombre de valeurs avant -- et après, c'est que le mot a consommé ou produit des valeurs sur la pile.

Pour certains mots, il peut y avoir deux configurations de retour différentes: elles sont séparées par un slash-deux-tirets.

Exemple:

( adr -- c 1 /-- 0 ) signifie que dans un cas adr est remplacé par c et 1, et dans l'autre par un 0 seulement.

Lorsque la pile de retour est utilisée, ce sont deux signes égale == qui sont employés.

Exemple:

>R ( n == | == n )

Dans le cas des mots générateurs de familles, la première transformation de pile concerne la partie construction de l'objet, la deuxième concerne son exécution.

Exemple:

CONSTANT ( n -- | == n )

Les valeurs sur la pile peuvent être de différents type:

b:

booléen (nul = faux, sinon vrai) codé sur le bit 0 d'une valeur 16 bits.

c:

octet, généralement un code ASCII sur les 7 bits de poids faible d'une valeur 16 bits.

cnt:

un octet de compte de chaîne, 5 ou 8 bits de poids faible d'une valeur 16 bits.

n:

entier signé, en complément à 2 sur 16 bits (-32768 à 32767).

u:

entier non signé sur 16 bits (0 à 65535).

adr:

une adresse 16 bits.

d:

un entier signé, en complément à 2 sur 32 bits (-2147483648 à 2147483647).

ud:

un entier non signé, sur 32 bits (0 à 4294967296).

FORTH DEFINITIONS HEX

LABEL ORIGIN

EA C, ( NOOP ) >MARK ( pfa de (COLD). )

4C C, ( JMP ) >R EA C, >MARK ( pfa+4 de (COLD). )

4C C, >R 05 C, 41 C, 4C C, 4C C,

LABEL LASTWO

>MARK ( lfa du dernier mot du dictionnaire: (TERMINAL) sur versions ATMOS, DIR sur version TELESTRAT )

0000 ,

LABEL ADRUSE

7700 , ( adresse de la zone USER. )

LABEL ADRBS0

( adresse de la base de la pile données (S0). )

( versions ATMOS: )

009D ,

( version TELESTRAT: )

00B9 ,

LABEL ADRBR0

01FF , ( adresse de la base de la pile retours (R0). )

0050 ,

LABEL WIDTH

001F , ( nombre maxi de caractères pour les noms ( WIDTH ) )

LABEL WARNIN

FFFF , ( valeur initiale de WARNING. )

LABEL FENCE

>MARK ( valeur initiale de FENCE (voir FORGET). )

LABEL DP

>MARK ( valeur initiale de DP (fin du dictionnaire). )

LABEL ADRVLI

>MARK ( valeur initiale de VOC-LINK (voir VOCABULARY). )

>R ROT R> R> R> 20 C, 20 C, 20 C, 20 C, 20 C, 20 C, 20 C, 20 C,

( versions ATMOS: )

1D C, 07 C, 08 C, 50 C, 83 C, 41 C,

( version TELESTRAT: )

4E C, 0D C, 4F C, FC C, 4E C, 63 C,

Table de démarrage. Notez l'utilisation des trois couples >R ... R> et de ROT pour croiser les références.

LIT

CODE LIT ( -- n )

IP )Y LDA, PHA, IP INC, 0= IF, IP 1+ INC, THEN, IP )Y LDA,

LABEL E001

IP INC, 0= IF, IP 1+ INC, THEN,

LABEL PUSH

DEX, DEX,

LABEL PUT

BOT 1+ STA, PLA, BOT STA,

Mot compilé par le mot d'exécution immédiate LITERAL. Ce mot précède une valeur litérale dans une définition compilée. Lors de son exécution, le contenu de l'élément seize bits situé deux octets plus loin est déposé sur la pile de données.

NEXT réalise l'opération 1 de l'automate; l'opération 2 est exécutée au moyen d'une simple instruction de saut indirect placée à l'adresse W-1.

Notons au passage que le registre Y est laissé nul par l'automate, donc sera toujours nul à l'entrée de toutes les primitives, et que W pointe toujours sur le cfa.

Dans le cas d'une primitive FORTH, le pfa contient généralement le code machine de la primitive, et le cfa pointe donc sur le pfa, juste deux adresses plus loin; toute primitive se terminera comme il se doit en sautant à NEXT.

Dans le cas d'une secondaire, appelée ainsi par opposition à "primitive", le pfa contient des instructions virtuelles, que l'automate devra exécuter en séquence; le cfa pointe alors sur du code qui fera l'équivalent d'un appel de sous-programme (voir la partie DOCOL dans CLIT):

  1. Empilage du pointeur d'instructions sur la pile de retour: -(RP) := IP;
  2. Initialisation du pointeur d'instruction pointant sur le pfa: IP := W+2;
  3. Saut à l'automate: NEXT.
La dernière instruction virtuelle d'une secondaire devra faire l'équivalent d'un retour de sous-programme:
  1. Dépilage du pointeur d'instruction en attente sur la pile de retour: IP := (RP)+;
  2. Saut à l'automate: NEXT.

LABEL NEXT

1 # LDY, IP )Y LDA, W 1+ STA, DEY, IP )Y LDA, W STA, CLC, IP LDA, 2 # ADC, IP STA, CS IF, IP 1+ INC, THEN, W 1- JMP,

LABEL POPTWO

INX, INX,

LABEL POP

INX, INX, NEXT,

LABEL PUSH0A

PHA, 0 # LDA, PUSH JMP,

LABEL SETUP

.A ASL, N 1- STA, BEGIN, BOT LDA, N ,Y STA, INX, INY, N 1- CPY, 0= UNTIL, 0 # LDY, RTS, ;C

CLIT

CODE CLIT ( -- c )

IP )Y LDA, PHA, TYA, E001 JMP,

Mot compilé par le mot d'exécution immédiate LITERAL. Ce mot précède une valeur litérale dans une définition compilée. Lors de son exécution, le contenu de l'élément huit bits situé deux octets plus loin est déposé sur la pile de données.

LABEL DODEF

( voir DEFER ) 2 # LDY, W )Y LDA, PHA, INY, W )Y LDA, 0 # LDY, W 1+ STA, PLA, W STA, W 1- JMP,

LABEL DOCOL

( voir : ) IP 1+ LDA, PHA, IP LDA, PHA, CLC, W LDA, 2 # ADC, IP STA, TYA, W 1+ ADC, IP 1+ STA, NEXT,

LABEL DOCON

( voir CONSTANT ) 2 # LDY, W )Y LDA, PHA, INY, W )Y LDA, PUSH JMP,

LABEL DOVAR

( voir VARIABLE ) CLC, W LDA, 2 # ADC, PHA, W 1+ LDA, 0 # ADC, PUSH JMP,

LABEL DOUSE

( voir USER ) CLC, 2 # LDY, W )Y LDA, UP ADC, PHA, INY, W )Y LDA, UP 1+ ADC, PUSH JMP, PLA, IP STA, PLA, IP 1+ STA, NEXT,

LABEL DODOES

( voir DOES> ) IP 1+ LDA, PHA, IP LDA, PHA, W )Y LDA, CLC, 3 # ADC, IP STA, INY, W )Y LDA, 0 # ADC, IP 1+ STA, DOVAR JMP, ;C

BRANCH

CODE BRANCH ( -- )

LABEL JUMP

( [ IP := (IP) ]: branchement absolu (plus rapide que branchement relatif). )

IP )Y LDA, PHA, INY, IP )Y LDA, IP 1+ STA, PLA, IP STA, NEXT 2+ JMP, ( car Y=1 ) ;C

Partie exécution compilée par une structure de saut inconditionnel. Pour exemple, ce mot est compilé par des mots tels que ELSE, THEN ou AGAIN. Le mot BRANCH est suivi, dans une définition compilée, d'une adresse 16 bits désignant la destination du branchement. Cette adresse est absolue (par opposition à relative) dans les systèmes FORTH 83-STANDARD pour ORIC. Les nouvelles normes préconisent ce type d'adressage. Voir aussi ?BRANCH.

?BRANCH

CODE ?BRANCH ( b -- )

( branchement si b=0 ) INX, INX, BOT 2- LDA, BOT 1- ORA, 0= IF,

LABEL NOJUMP

( [ IP := IP+2 ]: continuer en séquence sans branchement. )

CLC, IP LDA, 2 # ADC, IP STA, CS IF, IP 1+ INC, THEN, NEXT, THEN, JUMP JMP, ;C

Partie exécution compilée par une structure de saut conditionnel. Exécute une rupture de séquence à l'adresse 16 bits qui suit immédiatement ?BRANCH si le nombre 16 bits présent sur la pile est égal à zéro, sinon passe à l'exécution du mot qui suit cette adresse. L'adresse en question est absolue (par opposition à relative) dans les systèmes FORTH 83-STANDARD pour ORIC. Les nouvelles normes préconisent ce type d'adressage. Note concernant ?BRANCH et BRANCH: ces deux mots ne sont pas destinés à être utilisés directement dans une définition (ou alors à quoi sert-il de disposer d'un langage structuré?) et rares sont les situations où les structures existantes se révèlent insuffisantes.

Exemple:

Inventons un mot de pseudo-récursivité:

: ASSEZ? ( b -- ) COMPILE ?BRANCH LAST @ NAME> >BODY , ; IMMEDIATE

Le mot ASSEZ? réexécute tout le mot en cours jusqu'à ce que le booléen disponible au sommet de la pile de données soit vrai. Pourtant, le mot suivant:

: ATTENTE CR ." je m'ennuie de vous" ?KEY ASSEZ? CR ." enfin!" ;

serait compilé octet pour octet comme celui-ci:

: ATTENTE BEGIN CR ." je m'ennuie de vous" ?KEY UNTIL CR ." enfin!" ;

Pour être juste, signalons qu'on pourrait écrire IF ... ASSEZ? ... THEN alors que BEGIN ... IF ... UNTIL ... THEN ne serait pas autorisé. Rien n'est simple.

(LOOP)

CODE (LOOP) ( -- )

( [ (RP) := (RP)+1 ] ... [ si (RP+2) <= (RP) ]: [ RP := RP+6 ] sinon BRANCH. )

XSAVE STX, TSX, BOT 0101 + INC, 0= IF, BOT 0102 + INC, THEN,

LABEL E005

CLC, BOT 0103 + LDA, BOT 0101 + SBC, BOT 0104 + LDA, BOT 0102 + SBC,

LABEL SKIP

XSAVE LDX, .A ASL, CS IF, PLA, PLA, PLA, PLA, PLA, PLA, NOJUMP JMP, THEN, JUMP JMP, ;C

Mot compilé par le mot d'éxécution immédiate LOOP. Réalise un branchement arrière vers le début de la boucle s'il faut exécuter plusieurs itérations. Le compteur de boucle, situé sur la pile de retour, est incrémenté. Voir aussi DO et LOOP.

(+LOOP)

CODE (+LOOP) ( n -- )

( [ (RP) := (RP)+n ] si n<0 [ si (RP) <= (RP+2) ] sinon... )

INX, INX, XSAVE STX, BOT 1- LDA, PHA, PHA, BOT 2- LDA, TSX, INX, INX, CLC, BOT 0101 + ADC, BOT 0101 + STA, PLA, BOT 0102 + ADC, BOT 0102 + STA, PLA, 0< IF, CLC, BOT 0101 + LDA, BOT 0103 + SBC, BOT 0102 + LDA, BOT 0104 + SBC, SKIP JMP, THEN, E005 JMP, ;C

Partie exécution compilée par le mot d'exécution immédiate +LOOP. Incrémente le compteur de boucle avec la valeur déposée sur la pile de données et décide s'il faut continuer ou non à boucler. Voir aussi +LOOP.

(DO)

CODE (DO) ( fin+1 ini -- )

1 # LDY, IP )Y LDA, PHA, DEY, IP )Y LDA, PHA, BOT 3 + LDA, ( valeur finale de l'index. )

PHA, BOT 2+ LDA, PHA, BOT 1+ LDA, ( valeur initiale de l'index. )

PHA, BOT LDA, PHA, CLC, IP LDA, 2 # ADC, IP STA, CS IF, IP 1+ INC, THEN, POPTWO JMP, ;C

Partie exécution compilée par DO. Dépose sur la pile de retour l'adresse qui sera éventuellement utilisée par (LOOP) ou (+LOOP) Si l'index de boucle initial est égal ou inférieur à l'index de boucle final, le contenu de la boucle sera exécuté au moins une fois.

(?DO)

CODE (?DO) ( fin+1 ini -- )

BOT LDA, BOT 2+ CMP, 0= IF, ( pfa de (DO). )

BOT 1+ LDA, BOT 3 + CMP, 0= IF, INX, INX, INX, INX, JUMP JMP, THEN, THEN, ['] (DO) >BODY JMP, A7 C, ;C

Mot compilé par le mot d'exécution immédiate ?DO. Dépose sur la pile de retour l'adresse qui sera éventuellement utilisée par (LOOP) ou (+LOOP). La différence entre ?DO et DO tient au fait que ?DO ne réalise aucune itération si l'index initial est égal ou supérieur à l'index final.

EXECUTE

CODE EXECUTE ( cfa -- )

BOT LDA, W STA, BOT 1+ LDA, W 1+ STA, INX, INX, W 1- JMP, ;C

Exécute le mot dont le code exécutif (cfa) est sur la pile. Employé par l'interpréteur externe du système, EXECUTE se révèle très utile pour définir des procédures usant d'une forme quelconque d'indirection.

Puisqu'il suffit de connaître le cfa d'un mot (primitive ou secondaire) pour lancer son exécution, il n'est pas nécessaire que ce soit par l'intermédiaire du pfa d'une secondaire, on peut aussi passer par la pile de calcul:

  1. Chargement de W avec la valeur dépilée de la pile de calcul: W := (SP)+;
  2. Même seconde étape que pour l'automate: mip := (W).
Exemple:

: TOUT-FAIRE ACTION-1 ACTION-2 ACTION-3 ;

: CHOIX 2* ['] TOUT-FAIRE + @ EXECUTE ;

Le mot TOUT-FAIRE exécute en séquence ACTION-1, ACTION-2 et ACTION-3. La séquence 2 CHOIX n'exécute que ACTION-2.

Notez qu'on utilisera souvent la séquence @ EXECUTE.

R@

CODE R@ ( -- n | n == n )

XSAVE STX, TSX, BOT 0101 + LDA, PHA, BOT 0102 + LDA, XSAVE LDX, PUSH JMP, ;C

Copie la valeur n située au sommet de la pile de retour sur le sommet de la pile de données. Son action est équivalente à la séquence R> DUP >R.

R

CODE R ( -- n | n == n )

Le cfa de R pointe sur le pfa de R@.

Copie la valeur n située au sommet de la pile de retour sur le sommet de la pile de données. Son action est équivalente à la séquence R> DUP >R.

I

CODE I ( -- index )

Le cfa de I pointe sur le pfa de R@.

Délivre l'index de boucle lors de l'exécution d'une boucle de type DO ... LOOP ou DO ... +LOOP.

L'index de boucle est toujours en rapport avec la boucle dans laquelle il est défini.

Exemple:

: TEST ( -- ) 10 0 DO I . LOOP ;

TEST affiche 0 1 2 3 4 5 6 7 8 9.

EXIT

CODE EXIT ( -- )

PLA, IP STA, PLA, IP 1+ STA, NEXT, ;C

Pour rompre le séquencement linéaire de l'exécution d'une secondaire, il suffit d'utiliser des primitives qui manipulent le pointeur d'instruction; comme dans les machines réelles, l'adresse de la prochaine instruction à exécuter est trouvée juste après l'instruction de branchement; FORTH 83-STANDARD pour ORIC n'utilise que des sauts absolus (comme préconisé dans les nouvelles normes), plus efficaces sur 6502 que les sauts relatifs habituellement implémentés en FIG-FORTH. Puisque FORTH a aussi accès à la pile de retour (voir R> et >R), une secondaire peut parfaitement modifier le déroulement de celle qui l'a appelée, en allant modifier son pointeur d'instruction en attente au sommet de la pile retour (voilà pourquoi on vous dit de faire attention en utilisant la pile de retour).

Utilisé dans une définition "deux-points", il permet de quitter immédiatement l'exécution du mot en cours pour rendre le contrôle au mot appelant dont l'adresse est située sur la pile de retour.

Attention: la gestion correcte de la pile de retour interdit absolument l'usage de EXIT à l'intérieur d'une boucle DO ... LOOP ou d'une séquence >R ... R>, d'autant plus qu'il n'existe pas de sécurité vérifiant que le sommet de la pile de retour est bien une adresse de retour, chose que prévoyait à l'origine le 83-STANDARD.

A noter qu'une programmation simple, claire et bien structurée évite en général l'emploi de EXIT. Le mot EXIT peut être placé dans le flot d'entrée ou un écran pour en arrêter l'interprétation comme l'ancien ;S du FIG-FORTH.

Exemple:

: TEST-1 CR ." Ceci est un exemple " EXIT ." utile " ;

: TEST-2 TEST-1 ." bidon " ;

L'exécution de TEST-2 affiche "Ceci est un exemple bidon ".

UNNEST

CODE UNNEST ( -- )

Le cfa de UNNEST pointe sur le pfa de EXIT.

Identique à EXIT. Compilé par ; pour faciliter la décompilation. Marque la fin d'un mot et le retour au mot appelant.

@

CODE @ ( adr -- n )

BOT X) LDA, PHA, BOT INC, 0= IF, BOT 1+ INC, THEN, BOT X) LDA, PUT JMP, ;C

Dépose sur la pile de données la valeur 16 bits n stockée dans l'emplacement mémoire commençant à l'adresse adr (prononcer "fetch"). Voir aussi ! et ?.

Exemple:

27262 @ . affiche le contenu de l'adresse 27262.

C@

CODE C@ ( adr -- c )

BOT X) LDA, BOT STA, BOT 1+ STY, NEXT, ;C

Dépose sur la pile le contenu huit bits c de l'adresse adr. Voir aussi C!.

Exemple:

16384 C@ . affiche le contenu de l'octet d'adresse 16384.

!

CODE ! ( n adr -- )

BOT 2+ LDA, BOT X) STA, BOT INC, 0= IF, BOT 1+ INC, THEN, BOT 3 + LDA, BOT X) STA, INX, INX, INX, INX, NEXT, ;C

Affecte la valeur seize bits n à l'élément mémoire pointé par l'adresse adr. Est utilisé notamment pour affecter une valeur à une variable définie par l'utilisateur (prononcer "store").

Exemples:

55 16384 ! met la valeur 55 dans l'élément seize bits dont l'adresse mémoire commence à l'adresse 16384.

VARIABLE SCORE

10 SCORE ! affecte 10 unités à la variable SCORE précédemment définie.

656 PAD ! met la valeur 656 dans la zone de stockage temporaire.

C!

CODE C! ( c adr -- )

BOT 2+ LDA, BOT X) STA, INX, INX, INX, INX, NEXT, ;C

Stocke la valeur huit bits c à l'adresse adr.

Exemples:

ASCII A 16384 C! met la valeur 65 (code ASCII de A) à l'adresse 16384.

65 PAD C! met la valeur 65 dans la zone de stockage temporaire.

DROP

CODE DROP ( n -- )

INX, INX, NEXT, ;C

Enlève du sommet de la pile le nombre entier qui s'y trouvait.

Exemple:

10 20 DROP . affiche 10.

DUP

CODE DUP ( n -- n n )

BOT LDA, PHA, BOT 1+ LDA, PUSH JMP, ;C

Duplique le nombre entier situé au sommet de la pile de données.

Exemple:

20 DUP . . affiche 20 20.

SWAP

CODE SWAP ( n2 n1 -- n1 n2 )

BOT 2+ LDA, PHA, BOT LDA, BOT 2+ STA, BOT 3 + LDA, BOT 1+ LDY, BOT 3 + STY, PUT JMP, ;C

Les deux valeurs situées au sommet de la pile de données sont permutées.

Exemple:

20 10 SWAP . . affiche 20 10.

OVER

CODE OVER ( n2 n1 -- n2 n1 n2 )

BOT 2+ LDA, PHA, BOT 3 + LDA, PUSH JMP, ;C

Duplique le second élément de la pile de données.

Exemple:

3 5 OVER . . . affiche 3 5 3.

TUCK

CODE TUCK ( n2 n1 -- n1 n2 n1 )

BOT LDA, PHA, BOT 1+ LDY, BOT 2+ LDA, BOT STA, BOT 3 + LDA, BOT 1+ STA, PLA, PHA, BOT 2+ STA, BOT 3 + STY, TYA, PUSH JMP, ;C

Duplique le premier élément de la pile sous le second. Equivaut à la séquence SWAP OVER.

Exemple:

3 5 TUCK . . . affiche 5 3 5.

NIP

CODE NIP ( n2 n1 -- n1 )

BOT LDA, BOT 2+ STA, BOT 1+ LDA, BOT 3 + STA, POP JMP, ;C

Supprime le second élément de la pile. Equivaut à la séquence SWAP DROP.

Exemple:

2 3 5 NIP . . affiche 5 2.

ROT

CODE ROT ( n3 n2 n1 -- n2 n1 n3 )

BOT 4 + LDA, PHA, BOT 5 + LDY, BOT 2+ LDA, BOT 4 + STA, BOT 3 + LDA, BOT 5 + STA, BOT LDA, BOT 2+ STA, BOT 1+ LDA, BOT 3 + STA, TYA, PUT JMP, ;C

Effectue une opération de rotation sur les trois premiers éléments situés au sommet de la pile de données, mettant le troisième au sommet de la pile.

Exemple:

30 20 10 ROT . . . affiche 30 10 20.

-ROT

CODE -ROT ( n3 n2 n1 -- n1 n3 n2 )

BOT 2+ LDA, PHA, BOT 3 + LDY, BOT 4 + LDA, BOT 2+ STA, BOT 5 + LDA, BOT 3 + STA, BOT LDA, BOT 4 + STA, BOT 1+ LDA, BOT 5 + STA, TYA, PUT JMP, ;C

Réalise une rotation inverse sur les trois nombres entiers situés au sommet de la pile de données. Le fonctionnement de ce mot est équivalent à la séquence ROT ROT.

Exemple:

30 20 10 -ROT . . . affiche 20 30 10.

FLIP

CODE FLIP ( n2 -- n1 )

BOT LDA, BOT 1+ LDY, BOT 1+ STA, BOT STY, NEXT, ;C

Inverse les parties poids faible et poids fort de la valeur 16 bits déposée au sommet de la pile de données.

Exemple:

HEX 3FC6 FLIP U. DECIMAL affiche C63F.

?DUP

: ?DUP ( n -- n n si n<>0 )

DUP IF DUP THEN ;

Duplique le nombre entier situé au sommet de la pile de données si sa valeur n'est pas nulle. Ce mot peut, pour exemple, être utilisé avant IF si la valeur n est utilisée à la fois comme drapeau logique et dans la structure de contrôle de type IF ... THEN ou IF ... ELSE ... THEN.

Exemple:

Pour éviter la division d'un nombre par zéro, on peut définir:

: DIV ( dividende diviseur -- q ) ?DUP IF / THEN ;

22 7 DIV . affiche 3,

22 0 DIV . affiche 22,

alors que 22 0 / provoque une erreur.

SP@

CODE SP@ ( -- adr )

TXA, PHA, 0 # LDA, PUSH JMP, ;C

Renvoie l'adresse de la prochaine entrée dans la pile de données.

SP!

CODE SP! ( adr -- )

BOT LDA, TAX, NEXT, ;C

Met le pointeur de pile à la valeur spécifiée par le contenu du sommet de la pile de données.

Exemple:

SP@ 6 + SP! incrémente le pointeur de pile de trois unités.

RP@

CODE RP@ ( -- adr )

XSAVE STX, TSX, TXA, PHA, 0 # LDA, XSAVE LDX, PUSH JMP, ;C

Renvoie l'adresse de la prochaine entrée dans la pile de retour.

RP!

CODE RP! ( adr -- )

XSAVE STX, BOT LDA, TAX, TXS, XSAVE LDX, POP JMP, ;C

Met le pointeur de pile de retour à la valeur spécifiée par le contenu du sommet de la pile de données.

R>

CODE R> ( -- n | n == )

DEX, DEX, PLA, BOT STA, PLA, BOT 1+ STA, NEXT, ;C

Le nombre entier n est enlevé de la pile de retour pour être déposé sur la pile de données. Voir aussi >R.

>R

CODE >R ( n -- | == n )

BOT 1+ LDA, PHA, BOT LDA, PHA, INX, INX, NEXT, ;C

Transfère la valeur n du sommet de la pile de données vers le sommet de la pile de retour. Ce mot est utilisé notamment pour ranger temporairement certaines valeurs difficiles à manipuler autrement. Il faut cependant veiller à remettre la pile de retour dans son état initial à l'aide du mot R>, ceci avant de quitter une définition ou avant la fin d'une boucle de type DO ... LOOP, DO ... +LOOP. Voir aussi R.

Exemples:

: TEST1 5 7 3 >R + R> . . ;

L'exécution de TEST1 affiche la somme de 5 et 7, c'est-à-dire 12 et le chiffre 3.

: TEST2 5 7 3 >R + . . ;

TEST2 plantera votre système lors de son exécution. De même:

: BOUCLE 5 0 DO >R LOOP R> ;

est également peu recommandé, plantage garanti.

PICK

CODE PICK ( nx nx-1 .. n2 n1 n -- nx nx-1 .. n2 n1 nn | 2* SP@ + @ )

BOT LDA, .A ASL, N STA, 0 # LDA, N 1+ STA, INX, INX, TXA, TAY, N )Y LDA, PHA, INY, N )Y LDA, PUSH JMP, ;C

Met sur la pile de données le nième élément contenu dans la pile de données.

L'opération 1 PICK est équivalente à DUP, 2 PICK à OVER.

Exemple:

22 25 28 34 37 3 PICK . affiche 28.

CMOVE

CODE CMOVE ( srceAdr destAdr byteCnt -- )

3 # LDA, SETUP JSR, BEGIN, N CPY, 0= IF, N 1+ DEC, 0< IF, NEXT, THEN, THEN, N 4 + )Y LDA, N 2+ )Y STA, INY, 0= UNTIL, N 5 + INC, N 3 + INC, AGAIN, ;C

Transfère une zone mémoire de longueur byteCnt octets, depuis srceAdr vers destAdr. La copie débute par les adresses les plus basses. Il se produit un phénomène d'écrasement de la zone d'origine (overlap, parfois désiré) si srceAdr < destAdr < srceAdr+byteCnt-1 lors de déplacements vers le haut de la mémoire. Voir aussi CMOVE>.

CMOVE>

CODE CMOVE> ( srceAdr destAdr byteCnt -- )

3 # LDA, SETUP JSR, CLC, N LDA, N 2+ ADC, N 2+ STA, N 1+ LDA, N 3 + ADC, N 3 + STA, CLC, N LDA, N 4 + ADC, N 4 + STA, N 1+ LDA, N 5 + ADC, N 5 + STA, BEGIN, N LDA, 0= IF, N 1+ DEC, 0< IF, NEXT, THEN, THEN, N DEC, N 4 + LDA, 0= IF, N 5 + DEC, THEN, N 4 + DEC, N 2+ LDA, 0= IF, N 3 + DEC, THEN, N 2+ DEC, N 4 + )Y LDA, N 2+ )Y STA, AGAIN, ;C

Transfère une zone mémoire de byteCnt octets depuis srceAdr vers destAdr. La copie débute par les adresses les plus hautes. Il se produit un phénomène d'écrasement (overlap) de la zone origine si destAdr < srceAdr < destAdr+byteCnt-1 lors de déplacements vers le bas de la mémoire. Il n'y a pas de risque d'écrasement pour des déplacements vers le haut: CMOVE> est alors préféré à CMOVE.

AND

CODE AND ( n2 n1 -- n )

BOT LDA, BOT 2+ AND, BOT 2+ STA, BOT 1+ LDA, BOT 3 + AND, BOT 3 + STA, POP JMP, ;C

Effectue un ET logique bit à bit entre les valeurs n2 et n1.

Exemple: HEX EA39 FF0 AND . DECIMAL affiche A30.

OR

CODE OR ( n2 n1 -- n )

BOT LDA, BOT 2+ ORA, BOT 2+ STA, BOT 1+ LDA, BOT 3 + ORA, BOT 3 + STA, POP JMP, ;C

Effectue un OU logique bit à bit entre les valeurs n2 et n1.

Exemple:

HEX EA39 FF0 OR . DECIMAL affiche EFF9.

XOR

CODE XOR ( n2 n1 -- n )

BOT LDA, BOT 2+ EOR, BOT 2+ STA, BOT 1+ LDA, BOT 3 + EOR, BOT 3 + STA, POP JMP, ;C

Effectue un OU exclusif logique bit à bit entre les valeurs n2 et n1.

Exemple:

HEX EA39 FF0 XOR . DECIMAL affiche E5C9.

NOT

CODE NOT ( n -- n' )

INX, INX, BOT 1- LDA, BOT 2- ORA, 0= IF, 0 # LDA, 0= NOT IF, SWAP THEN, BOT 1- LDA, THEN, PHA, PUSH JMP, ;C

Convertit un nombre n en son complément à un. Est équivalent à la séquence -1 XOR. Ce mot peut servir à définir une bascule logique pour inverser la valeur d'un flag booléen. Notez l'utilisation de SWAP pour croiser les références.

Exemples:

TRUE NOT . affiche 0 (équivaut à FALSE).

FALSE NOT . affiche -1 (équivaut à TRUE).

HEX EA39 NOT . DECIMAL affiche 15C6.

Si vous êtes passionnés de montages électroniques, voici comment simuler une porte logique NAND:

: NAND ( b2 b1 -- b ) AND NOT ;

et la table de vérité de NAND devient:

0 0 NAND . affiche -1,

0 1 NAND . affiche -1,

1 0 NAND . affiche -1,

1 1 NAND . affiche 0.

TRUE

-1 CONSTANT TRUE ( -- -1 )

Constante délivrant le flag booléen vrai. Voir aussi FALSE.

FALSE

0 CONSTANT FALSE ( -- 0 )

Constante délivrant la valeur 0. Ce mot sert essentiellement à rendre certains tests plus explicites dans leur libellé.

Ainsi, la séquence suivante: 0= IF TRUE ELSE FALSE THEN est plus claire que celle-ci: 0= IF -1 ELSE 0 THEN.

CSET

CODE CSET ( c adr -- )

BOT X) LDA, BOT 2+ ORA, BOT X) STA, POPTWO JMP, ;C

Opérateur à l'échelle du bit. Force à 1 les bits de l'octet pointé par adr selon les bits à un du masque c. Les autres bits sont inchangés.

Le mot CSET équivaut à la séquence C@ ROT OR SWAP C!.

Exemples:

VARIABLE OCTET

6 OCTET C! (00000110)

3 OCTET CSET (00000011)

OCTET C@ . affiche 7. (00000111)

HEX 55 PAD C! 30 PAD CSET PAD C@ . DECIMAL affiche 75.

CRESET

CODE CRESET ( c adr -- )

BOT 2+ LDA, FF # EOR, BOT )X AND, BOT )X STA, POPTWO JMP, ;C

Opérateur à l'échelle du bit. Force à 0 les bits de l'octet pointé par adr selon les bits à un du masque c. Les autres bits sont inchangés.

Le mot CRESET équivaut à la séquence DUP C@ ROT NOT AND SWAP C!.

Exemples:

VARIABLE OCTET

6 OCTET C! (00000110)

3 OCTET CRESET (00000011)

OCTET C@ . affiche 4. (00000100)

HEX 55 PAD C! 30 PAD CRESET PAD C@ . DECIMAL affiche 45.

CTOGGLE

CODE CTOGGLE ( c adr -- )

BOT X) LDA, BOT 2+ EOR, BOT X) STA, POPTWO JMP, ;C

Opérateur à l'échelle du bit. Inverse les bits de l'octet pointé par adr selon les bits à un du masque c. Les autres bits sont inchangés.

Le mot CTOGGLE équivaut à la séquence DUP C@ ROT XOR SWAP C!.

Exemples:

VARIABLE OCTET

6 OCTET C! (00000110)

3 OCTET CTOGGLE (00000011)

OCTET C@ . affiche 5. (00000101)

HEX 20 PAD C! 30 PAD CTOGGLE PAD C@ . DECIMAL affiche 10.

ON

CODE ON ( adr -- )

FF # LDA, BOT X) STA, BOT INC, 0= IF, BOT 1+ INC, THEN, BOT X) STA, POP JMP, ;C

Rend vrai le contenu de la variable pointée par son adresse. Equivaut à la séquence -1 <variable> !. Voir aussi OFF.

Exemples:

VARIABLE DRAPEAU DRAPEAU ON DRAPEAU ? affiche -1.

PAD ON PAD ? affiche -1.

OFF

CODE OFF ( adr -- )

0 # LDA, BOT X) STA, BOT INC, 0= IF, BOT 1+ INC, THEN, BOT X) STA, POP JMP, ;C

Rend faux le contenu de la variable pointée par son adresse. Ce contenu sert généralement de flag booléen au sein d'une structure de contrôle. Equivaut à la séquence 0 <variable> !. Voir aussi ON.

Exemples:

VARIABLE TEST

: APPUI KEY ASCII 3 = IF TEST ON ELSE TEST OFF THEN ;

APPUI TEST ? affiche -1 si touche activée = "3", 0 sinon.

PAD OFF PAD ? affiche 0.

+

CODE + ( n2 n1 -- n | n = n2+n1 )

CLC, BOT LDA, BOT 2+ ADC, BOT 2+ STA, BOT 1+ LDA, BOT 3 + ADC, BOT 3 + STA, INX, INX, NEXT, ;C

Additionne deux nombres entiers, n2 et n1, et dépose le résultat n sur la pile de données. Les valeurs n2 et n1 sont perdues.

Exemples:

12 5 + . affiche 17.

-12 -5 + . affiche -17.

65535 1 + . affiche 0 (entiers sur 16 bits!).

NEGATE

CODE NEGATE ( n -- -n )

SEC, TYA, BOT SBC, BOT STA, TYA, BOT 1+ SBC, BOT 1+ STA, NEXT, ;C

Convertit le nombre n en son complément à deux, c'est-à-dire inverse son signe.

Exemples:

12 NEGATE . affiche -12.

-7 NEGATE . affiche 7.

-

CODE - ( n2 n1 -- n | n = n2-n1 )

SEC, BOT 2+ LDA, BOT SBC, BOT 2+ STA, BOT 3 + LDA, BOT 1+ SBC, BOT 3 + STA, INX, INX, NEXT, ;C

Le nombre entier signé n est le résultat de la soustraction de n1 à n2, équivalant à l'opération algébrique n2-n1.

Exemples:

12 5 - . affiche 7.

-12 -5 - . affiche -17.

5 12 - . affiche -7.

ABS

CODE ABS ( n -- n' )

BOT 1+ LDA, ['] NEGATE >BODY BMI, ( pfa de NEGATE ) NEXT, ;C

Renvoie la valeur absolue du nombre entier déposé sur la pile de données.

Exemples:

-5 ABS . affiche 5.

12 ABS . affiche 12.

+!

CODE +! ( n adr -- )

CLC, BOT X) LDA, BOT 2+ ADC, BOT X) STA, BOT INC, 0= IF, BOT 1+ INC, THEN, BOT X) LDA, BOT 3 + ADC, BOT X) STA, POPTWO JMP, ;C

Incrémente le contenu de l'adresse adr de la quantité n.

Exemples:

VARIABLE SCORE 10 SCORE ! 5 SCORE +! SCORE ? affiche 15.

5 PAD ! 3 PAD +! PAD ? affiche 8.

0

0 CONSTANT 0 ( -- 0 )

Constante zéro d'usage courant (plus rapide que son litéral). En effet, un nombre entier quelconque compilé dans une définition occupe quatre octets alors qu'une constante n'en occupe que deux. C'est pourquoi, les constantes 0 1 2 et 3 sont prédéfinies dans le dictionnaire, car utilisées fréquemment, elles permettent une économie de place mémoire non négligeable. Voir aussi CONSTANT.

1

1 CONSTANT 1 ( -- 1 )

Constante un d'usage courant (plus rapide que son litéral). Voir aussi 0.

2

2 CONSTANT 2 ( -- 2 )

Constante deux d'usage courant (plus rapide que son litéral). Voir aussi 0.

3

3 CONSTANT 3 ( -- 3 )

Constante trois d'usage courant (plus rapide que son litéral). Voir aussi 0.

2*

CODE 2* ( n -- n' | n' = n*2 )

CLC, BOT ROL, BOT 1+ ROL, NEXT, ;C

Multiplie le nombre n par deux (décalage arithmétique à gauche).

Exemple:

1024 2* . affiche 2048.

2/

CODE 2/ ( n -- n' | n' = n/2 )

BOT 1+ LDA, .A ASL, BOT 1+ ROR, BOT ROR, NEXT, ;C

Décalage à droite sur un bit de la valeur située au sommet de la pile de données. Equivaut à la division entière par 2 pour les nombres positifs. Voir aussi U2/.

Exemples:

-1025 2/ . affiche -512,

mais ATTENTION: -1 2/ . affiche -1.

U2/

CODE U2/ ( u -- u' | u' = u/2 )

CLC, BOT 1+ ROR, BOT ROR, NEXT, ;C

Décalage logique à droite de la valeur entière non signée u (division par deux non signée).

Exemples:

56 U2/ . affiche 28.

65534 U2/ . affiche 32767.

1+

CODE 1+ ( n -- n' | n' = n+1 )

BOT INC, 0= IF, BOT 1+ INC, THEN, NEXT, ;C

Ajoute 1 à la valeur située au sommet de la pile de données.

Exemple:

5 1+ . affiche 6.

1-

CODE 1- ( n -- n' | n' = n-1 )

BOT LDA, 0= IF, BOT 1+ DEC, THEN, BOT DEC, NEXT, ;C

Soustrait 1 à la valeur située au sommet de la pile de données.

Exemple:

5 1- . affiche 4.

2+

CODE 2+ ( n -- n' | n' = n+2 )

CLC, 2 # LDA, BOT ADC, BOT STA, TYA, BOT 1+ ADC, BOT 1+ STA, NEXT, ;C

Ajoute 2 au nombre situé au sommet de la pile de données.

Exemple:

5 2+ . affiche 7.

2-

CODE 2- ( n -- n' | n' = n-2 )

SEC, BOT LDA, 2 # SBC, BOT STA, BOT 1+ LDA, 0 # SBC, BOT 1+ STA, NEXT, ;C

Soustrait 2 au nombre situé au sommet de la pile de données.

Exemple:

5 2- . affiche 3.

UM*

CODE UM* ( u2 u1 -- ud | ud = u2*u1 )

BOT 2+ LDA, N STA, BOT 2+ STY, BOT 3 + LDA, N 1+ STA, BOT 3 + STY, 10 # LDY, BEGIN, BOT 2+ ASL, BOT 3 + ROL, BOT ROL, BOT 1+ ROL, CS IF, CLC, N LDA, BOT 2+ ADC, BOT 2+ STA, N 1+ LDA, BOT 3 + ADC, BOT 3 + STA, 0 # LDA, BOT ADC, BOT STA, THEN, DEY, 0= UNTIL, NEXT, ;C

Réalise le produit de deux nombres entiers u2 et u1 non signés. Le résultat est un nombre double précision non signé.

Exemple:

1000 2000 UM* D. affiche 2000000.

U*D

CODE U*D ( u2 u1 -- ud | ud = u2*u1 )

Le cfa de U*D pointe sur le pfa de UM*.

Synonyme de UM*. Voir ce mot.

UM/MOD

CODE UM/MOD ( ud u -- uR uQ | ud = u*uQ+uR )

BOT 4 + LDA, BOT 2+ LDY, BOT 4 + STY, .A ASL, BOT 2+ STA, BOT 5 + LDA, BOT 3 + LDY, BOT 5 + STY, .A ROL, BOT 3 + STA, 10 # LDA, N STA, BEGIN, BOT 4 + ROL, BOT 5 + ROL, SEC, BOT 4 + LDA, BOT SBC, TAY, BOT 5 + LDA, BOT 1+ SBC, CS IF, BOT 4 + STY, BOT 5 + STA, THEN, BOT 2+ ROL, BOT 3 + ROL, N DEC, 0= UNTIL, POP JMP, ;C

Correspond à la division primitive en FORTH. Ce mot réalise la division d'un nombre double précision non signé avec un nombre entier non signé. Le quotient uQ et le reste uR sont des nombres entiers non signés.

Exemple:

100003. 5 UM/MOD . . affiche 20000 3.

0=

CODE 0= ( n -- b )

BOT LDA, BOT 1+ ORA, 0= IF, DEY, THEN, BOT 1+ STY, BOT STY, NEXT, ;C

Délivre un flag booléen vrai si n est égal à zéro.

Exemples:

0 0= . affiche -1 (vrai).

10 0= . affiche 0 (faux).

0<

CODE 0< ( n -- b )

BOT 1+ ASL, CS IF, DEY, THEN, BOT 1+ STY, BOT STY, NEXT, ;C

Délivre un flag booléen vrai si n est négatif.

Exemples:

-10 0< . affiche -1 (vrai).

10 0< . affiche 0 (faux).

0 0< . affiche 0 (faux).

0>

CODE 0> ( n -- b )

BOT LDA, BOT 1+ ORA, 0= NOT IF, BOT 1+ LDA, 0< NOT IF, DEY, THEN, THEN, BOT STY, BOT 1+ STY, NEXT, ;C

Délivre un flag booléen vrai si n est strictement positif.

Exemples:

10 0> . affiche -1 (vrai).

-10 0> . affiche 0 (faux).

0 0> . affiche 0 (faux).

0<>

CODE 0<> ( n -- b )

BOT LDA, BOT 1+ ORA, 0= NOT IF, DEY, THEN, BOT 1+ STY, BOT STY, NEXT, ;C

Délivre un flag booléen vrai si n est différent de zéro. Inverse de 0=.

Exemples:

10 0<> . affiche -1 (vrai).

0 0<> . affiche 0 (faux).

=

CODE = ( n2 n1 -- b )

BOT LDA, BOT 2+ CMP, 0= IF, BOT 1+ LDA, BOT 3 + CMP, 0= IF, DEY, THEN, THEN, BOT 2+ STY, BOT 3 + STY, POP JMP, ;C

Comparateur: délivre un flag booléen vrai si n2 est égal à n1.

Exemples:

10 10 = . affiche -1 (vrai).

-10 10 = . affiche 0 (faux).

<>

CODE <> ( n2 n1 -- b )

BOT LDA, BOT 2+ EOR, N STA, BOT 1+ LDA, BOT 3 + EOR, N ORA, 0= NOT IF, DEY, THEN, BOT 2+ STY, BOT 3 + STY, POP JMP, ;C

Comparateur: délivre un flag booléen vrai si n2 est différent de n1. Inverse de =.

Exemples:

10 0 <> . affiche -1 (vrai).

10 10 <> . affiche 0 (faux).

?NEGATE

: ?NEGATE ( n2 n1 -- n )

0< IF NEGATE THEN ;

Rend négatif le second élément si celui situé au sommet de la pile est négatif.

Exemples:

5 -1 ?NEGATE . affiche -5.

5 1 ?NEGATE . affiche 5.

U<

CODE U< ( u2 u1 -- b )

BOT 3+ LDA, BOT 1+ CMP, 0= IF, BOT 2+ LDA, BOT CMP, 0= NOT IF, SWAP THEN, CS NOT IF, DEY, THEN, THEN, BOT 2+ STY, BOT 3 + STY, POP JMP, ;C

Délivre un flag booléen vrai si le nombre entier non signé u2 est inférieur au nombre entier non signé u1. Notez l'utilisation de SWAP pour croiser les références.

Exemple:

HEX FFFE FFFF U< DECIMAL . affiche -1 (vrai).

U>

CODE U> ( u2 u1 -- b )

BOT 3 + LDA, BOT 1+ CMP, 0= IF, BOT 2+ LDA, BOT CMP, 0= NOT IF, SWAP THEN, CS IF, DEY, THEN, THEN, BOT 2+ STY, BOT 3 + STY, POP JMP, ;C

Délivre un flag booléen vrai si le nombre entier non signé u2 est supérieur au nombre entier non signé u1. Notez l'utilisation de SWAP pour croiser les références.

Exemple:

HEX FFFE FFFF U> DECIMAL . affiche 0 (faux).

<

CODE < ( n2 n1 -- b )

SEC, BOT 2+ LDA, BOT SBC, BOT 3 + LDA, BOT 1+ SBC, VS IF, 80 # EOR, THEN, 0< IF, DEY, THEN, BOT 3 + STY, BOT 2+ STY, POP JMP, ;C

Comparateur: délivre un flag booléen vrai si n2 est inférieur à n1. Voir aussi U<.

Exemples:

-10 10 < . affiche -1 (vrai).

10 -10 < . affiche 0 (faux).

10 10 < . affiche 0 (faux).

10000 1 < . affiche -1 (vrai),

50000 1 < . affiche 0 (faux car nombres signés)!

>

CODE > ( n2 n1 -- b )

SEC, BOT LDA, BOT 2+ SBC, BOT 1+ LDA, BOT 3 + SBC, VS IF, 80 # EOR, THEN, 0< IF, DEY, THEN, BOT 3 + STY, BOT 2+ STY, POP JMP, ;C

Comparateur: délivre un flag booléen vrai si n2 est supérieur à n1.

Exemples:

10 -10 > . affiche -1 (vrai).

-10 10 > . affiche 0 (faux).

10 10 > . affiche 0 (faux).

2DROP

CODE 2DROP ( d -- )

POPTWO JMP, ;C

Supprime les deux dernières cellules de la pile. Les mots manipulant les nombres double précision (32 bits) sont souvent utilisés pour des paires de nombres 16 bits. Ainsi, 2DROP équivaut à DROP DROP.

Exemples:

10 20 30 2DROP . affiche 10.

123456. 98765. 2DROP D. affiche 123456.

2DUP

CODE 2DUP ( d -- d d )

4 # LDY, BEGIN, DEX, BOT 4 + LDA, BOT STA, DEY, 0= UNTIL, NEXT, ;C

Copie le nombre double précision situé au sommet de la pile de données. Equivaut à OVER OVER ( n2 n1 -- n2 n1 n2 n1 ).

Exemples:

10 20 2DUP . . . . affiche 20 10 20 10.

98765. 2DUP D. D. affiche 98765 98765.

2SWAP

CODE 2SWAP ( d2 d1 -- d1 d2 )

BOT 7 + LDA, TAY, BOT 3 + LDA, BOT 7 + STA, TYA, BOT 3 + STA, BOT 6 + LDA, TAY, BOT 2+ LDA, BOT 6 + STA, TYA, BOT 2+ STA, BOT 5 + LDA, TAY, BOT 1+ LDA, BOT 5 + STA, TYA, BOT 1+ STA, BOT 4 + LDA, TAY, BOT LDA, BOT 4 + STA, TYA, BOT STA, NEXT, ;C

Permute les deux dernières paires de cellules de la pile. Equivaut à la manipulation de la pile ( n4 n3 n2 n1 -- n2 n1 n4 n3 ).

2OVER

CODE 2OVER ( d2 d1 -- d2 d1 d2 )

4 # LDY, BEGIN, DEX, BOT 8 + LDA, BOT STA, DEY, 0= UNTIL, NEXT, ;C

Fait une copie de l'avant-dernière paire de cellules de la pile. Equivaut à la manipulation de la pile ( n4 n3 n2 n1 -- n4 n3 n2 n1 n4 n3 ).

3DUP

CODE 3DUP ( n3 n2 n1 -- n3 n2 n1 n3 n2 n1 )

6 # LDY, BEGIN, DEX, BOT 6 + LDA, BOT STA, DEY, 0= UNTIL, NEXT, ;C

Fait une copie des trois dernières cellules de la pile.

(NTOP)

00 USER (NTOP) ( -- adr )

Variable système contenant l'adresse du sommet du dictionnaire.

OFFSET

02 USER OFFSET ( -- adr )

Variable prédéfinie dont le contenu permet de positionner le pointeur en adressage absolu sur le contenu du bloc courant.

(UAREA)

04 USER (UAREA) ( -- adr )

Variable système contenant l'adresse de début de la zone des variables usager.

S0

06 USER S0 ( -- adr )

Variable système contenant l'adresse du début de la pile de données pour la tâche courante.

R0

08 USER R0 ( -- adr )

Variable système contenant l'adresse du début de la pile de retour pour la tâche courante.

#TIB

0A USER #TIB ( -- adr )

Variable utilisée par WORD, lors de l'interprétation du flot d'entrée, indiquant le nombre de caractères à interpréter.

WIDTH

0C USER WIDTH ( -- adr )

Variable dont le contenu détermine la taille des en-têtes de définition. Cette variable est initialisée à 31 par le STANDARD. Une valeur inférieure limitera le nombre de caractères pris en compte par le système.

Exemple:

3 WIDTH !

: TABLE ... ;

: TABLEAU ... ;

WORDS affiche TAB TAB etc...

Le système fera la discrimination entre ces deux mots, car la longueur prise en compte par le système diffère de la taille de l'en-tête limitée à trois caractères. Il n'en serait pas de même si les en-têtes avaient une longueur équivalente (TORE et TORT par exemple).

WARNING

0E USER WARNING ( -- adr )

Variable dont le contenu sert de drapeau booléen. Une valeur vraie indique si le système doit émettre certains messages (pour exemple, une entrée dans le dictionnaire déjà définie).

FENCE

10 USER FENCE ( -- adr )

Variable dont le contenu correspond à une adresse du dictionnaire en dessous de laquelle une définition ne peut plus être supprimée par FORGET.

DP

12 USER DP ( -- adr )

Variable système Dictionnaire-Pointeur contenant l'adresse de la première cellule libre située au sommet du dictionnaire. Le contenu de DP est fréquemment utilisé et est délivré par HERE.

VOC-LINK

14 USER VOC-LINK ( -- adr )

Variable dont le contenu pointe sur le vocabulaire le plus récemment défini. L'adresse pointée dans le champ paramètre du nom du vocabulaire pointe elle-même un vocabulaire plus ancien et tous les vocabulaires sont ainsi enfilés jusqu'au vocabulaire FORTH.

BLK

16 USER BLK ( -- adr )

Variable contenant le numéro du bloc en cours d'interprétation. Cette valeur est par convention égale à zéro quand le flot d'entrée en cours d'interprétation provient du terminal.

>IN

18 USER >IN ( -- adr )

Variable système. Pointeur d'interprétation dans le flot d'entrée.

Exemple:

>IN (suivi de 5 espaces) ? affiche 10, valeur prise par >IN après le point d'interrogation. Les structures de contrôles interprétées modifient la progression linéaire de >IN dans le texte à interpréter.

#OUT

1A USER #OUT ( -- adr )

Variable dont le contenu indique le nombre de caractères transmis après le dernier retour chariot. Son contenu est remis à zéro par l'exécution de CLS ou CR, et incrémenté de une unité à chaque exécution de EMIT. Son contenu est notamment testé par WORDS afin d'éviter qu'un mot ne soit coupé en fin de ligne lors de l'édition du contenu du dictionnaire.

SCR

1C USER SCR ( -- adr )

Variable dont le contenu détermine le numéro de l'écran courant listé ou édité.

#LINE

1E USER #LINE ( -- adr )

Variable dont le contenu indique le nombre de retours chariot transmis depuis la dernière page. Son contenu est remis à zéro lors de l'exécution du mot CLS dont la fonction est d'effacer le contenu de l'écran vidéo. Son contenu est incrémenté de une unité à chaque retour chariot.

PRIOR

20 USER PRIOR ( -- adr )

Variable dont le contenu pointe sur le dernier vocabulaire où a eu lieu la recherche.

CURRENT

22 USER CURRENT ( -- adr )

Variable système pointant le vocabulaire courant. Le vocabulaire courant est celui où sont ajoutées les nouvelles définitions. Voir aussi DEFINITIONS.

STATE

24 USER STATE ( -- adr )

Délivre l'adresse d'une variable contenant l'état de compilation. Une valeur non nulle indique que la compilation est en cours, mais cette valeur est indépendante du système. Un programme standard ne doit pas modifier cette variable.

BASE

26 USER BASE ( -- adr )

Variable dont le contenu permet le contrôle de la base numérique du système FORTH. En effet, la majorité des langages conventionnels doivent utiliser une syntaxe spécifique à chaque base numérique pour le traitement des nombres appropriés. En langage FORTH, rien de tel, on sélectionne au préalable la base numérique souhaitée avant traitement des quantités concernées. Ce traitement est possible en entrée comme en sortie. Voir aussi DECIMAL et HEX.

Exemples:

DECIMAL 255 16 BASE ! . affiche FF, ce qui correspond bien à la valeur hexadécimale 255.

Maintenant, si on tape 127 ., le système affiche 127.

Eh oui, vous restez dans la base numérique sélectionnée tant que vous ne la modifierez pas. Toutes les bases numériques sont disponibles. Certaines bases numériques sont préprogrammées dans le système FORTH, il s'agit des bases décimales et hexadécimales disponibles respectivement à l'aide des mots DECIMAL et HEX.

HEX 2C A1 + . affiche CD.

DECIMAL 32 HEX 4C + . affiche 6C.

Mais je ne résiste pas à vous donner en exemple le chef-d'oeuvre de concision que contitue le court programme permetttant de convertir un nombre quelconque de secondes au format HH:MM:SS:

: SEXTAL 6 BASE ! ;

: :00 # SEXTAL # ASCII : HOLD DECIMAL ;

: HMS <# :00 :00 #S #> TYPE ;

et dont l'exécution 4500. HMS affiche 1:15:00, c'est-à-dire 1 heure, 15 minutes et 0 seconde. Le mot SEXTAL permet de sélectionner la base 6, lequel mot est ensuite utilisé pour contrôler la base numérique de la paire de chiffres exprimant les secondes et les minutes. En effet, les unités sont exprimées en base 10, les "dizaines" en base 6.

DPL

28 USER DPL ( -- adr )

Variable dont le contenu donne la position du point décimal lors de l'entrée en interprétation d'un nombre double précision. Si le contenu de DPL est égal à -1, le nombre est un entier 16 bits; si le contenu est égal à 0, il s'agit d'un entier 32 bits sans partie décimale; si le contenu est supérieur à zéro, la valeur indique la position du point décimal.

Exemples:

3562 DPL ? affiche -1.

3562. DPL ? affiche 0.

35.62 DPL ? affiche 2.

FLD

2A USER FLD ( -- adr )

Sur versions ATMOS uniquement. Variable système dont le contenu pointe sur le champ d'en-tête. Elle n'est pas utilisée en FORTH 83-STANDARD pour ORIC.

BNK

2A USER BNK ( -- adr )

Sur version TELESTRAT uniquement. Variable système dont le contenu pointe sur le numéro de la banque courante. Cette variable est initialisée à 0 au démarrage du système. La banque 0 doit toujours être sélectionnée avant que FORTH rende la main, sinon plantage garanti. Voir aussi BANK.

Exemple:

HEX BNK @ 1 BANK C000 C@ . BANK DECIMAL affiche en base hexadécimale l'octet situé à l'adresse C000 (hexa) de la banque 1. La séquence BNK @ ... BANK permet à FORTH de retourner sur la banque initiale.

CSP

2C USER CSP ( -- adr )

Variable système de sauvegarde temporaire du pointeur de la pile de données pour les contrôles de structures de compilation. Voir aussi : et ;.

R#

2E USER R# ( -- adr )

Variable dont le contenu permet de déterminer la position du curseur d'édition. Cette position est donnée en nombre de caractères depuis le début du bloc. Pour connaître la position en ligne et colonne, il faut effectuer une division modulo 64.

Exemple:

: POSITION ( -- ) R# @ 64 /MOD CR ." Curseur en ligne " . ." , colonne " . CR ;

HLD

30 USER HLD ( -- adr )

Variable contenant le nombre de digits dans le tampon de formatage. Est initialisé par <# et incrémenté par #, #S, HOLD et SIGN.

SPAN

32 USER SPAN ( -- adr )

Délivre l'adresse d'une variable contenant le nombre de caractères actuellement reçus et stockés par la dernière exécution de EXPECT.

LAST

34 USER LAST ( -- adr )

Délivre l'adresse du champ du nom de la dernière définition compilée dans le vocabulaire courant.

CONTEXT

36 USER CONTEXT ( -- adr )

Pointeur du vocabulaire de contexte, c'est-à-dire du vocabulaire dans lequel doivent s'effectuer les recherches de mots. CONTEXT délivre l'adresse d'une table ordonnée pouvant contenir 5 vocabulaires de recherche (voir #VOCS). Si la recherche est infructueuse dans le premier vocabulaire pointé, la recherche se poursuit dans le vocabulaire suivant de la table. Un vocabulaire est pointé par le pfa du nom-de-vocabulaire qui le définit. Celui-ci pointe à son tour le champ de lien (lfa) du plus récent mot de ce vocabulaire.

Exemples:

CONTEXT @ BODY> >NAME ID. affiche le nom du premier vocabulaire de recherche.

CONTEXT @ @ L>NAME ID. affiche le premier mot rencontré lors d'une recherche.

END?

40 USER END? ( -- adr )

Variable système booléenne vraie si tout le flot d'entrée a été interprété.

BL

20 CONSTANT BL ( -- 32 )

Constante délivrant le nombre 32. L'affichage de cette valeur correspond au caractère "espace".

C/L

40 CONSTANT C/L ( -- 64 )

Constante dont le contenu détermine le nombre de caractères par ligne contenus dans un bloc écran.

FIRST

7800 CONSTANT FIRST ( -- adr )

Constante délivrant l'adresse du tampon du disque. L'adresse courante est implantée pendant l'initialisation de FORTH.

LIMIT

9800 CONSTANT LIMIT ( -- adr )

Constante définissant l'adresse supérieure du tampon de disque. Son contenu sera modifié par l'initialisation (dépendant donc du système).

B/BUF

400 CONSTANT B/BUF ( -- 1024 )

Constante 1024 du nombre d'octets par tampon de bloc (bytes per buffer).

#VOCS

5 CONSTANT #VOCS ( -- 5 )

Constante dont le contenu indique le nombre d'éléments dans la zone d'indication de l'ordre de recherche. Cette valeur est initialisée à cinq unités sur le système FORTH 83-STANDARD pour ORIC.

TIB

100 CONSTANT TIB ( -- adr )

Délivre l'adresse du tampon de texte. Ce tampon est utilisé pour recevoir des caractères, quand le flot d'entrée provient du terminal d'entrée courant. La capacité minimale du TIB (Terminal Input Buffer) est de 80 caractères.

(KEY)

CODE (KEY) ( -- c )

( versions ATMOS: )

026A LDA, 1 # ORA, 026A STA, C5E8 JSR, \ saisie d'un caractère au clavier.

7F # AND, PHA, 026A LDA, FE # AND, 026A STA, PLA, PUSH0A JMP, ;C

( version TELESTRAT: )

FLGSCR LDA, 80 # ORA, FLGSCR STA, XRDW0 BRK, 7F # AND, PHA, FLGSCR LDA, 7F # AND, FLGSCR STA, PLA, PUSH0A JMP, ;C

Attend qu'une touche du clavier soit activée et dépose le code ASCII de celle-ci sur la pile de données. A l'initialisation, ce mot est utilisé par le mot d'exécution vectorisée KEY.

KEY

DEFER KEY ( -- c )

' (KEY) IS KEY

Mot d'exécution vectorisée. Attend qu'une touche du clavier soit activée, puis délivre le code ASCII de cette touche. Ce mot exécute par défaut (KEY), lequel accède au BIOS pour toutes les fonctions du système FORTH. La re-vectorisation de cette fonction permet de modifier profondément l'accès au système, voire de le commander depuis un périphérique différent du clavier (modem ou RS232 pour exemple).

Exemple:

: DECODE-CLAVIER ( -- )

CR ." Appuyez sur une touche du clavier " KEY

CR ." Vous venez d'appuyer sur la touche de code: " . CR ;

(?KEY)

CODE (?KEY) ( -- b )

( versions ATMOS: )

EB78 JSR, ( gestion du tampon touche. )

PUSH0A JMP, ;C

( version TELESTRAT: )

XRD0 BRK, CS IF, 0 # LDA, THEN, PUSH0A JMP, ;C

Renvoie un flag booléen vrai si l'utilisateur active une touche du clavier, sinon renvoie un flag booléen faux. Ce mot est utilisé par le mot d'exécution vectorisée ?KEY.

?KEY

DEFER ?KEY ( -- b )

' (?KEY) IS ?KEY

Mot d'exécution vectorisée. Délivre un flag booléen vrai si une touche est activée au moment de l'exécution de ce mot. ?KEY exécute par défaut (?KEY), lequel accède au BIOS pour toutes les fonctions du système FORTH.

(EMIT)

CODE (EMIT) ( c -- )

( versions ATMOS: )

CLC, 1 # LDA, 1A # LDY, UP )Y ADC, UP )Y STA, 0 # LDA, INY, UP )Y ADC, UP )Y STA, XSAVE STX, BOT LDA, CCD9 JSR, ( affichage du caractère dans A. )

XSAVE LDX, POP JMP, ;C

( version TELESTRAT: )

CLC, 1 # LDA, 1A # LDY, UP )Y ADC, UP )Y STA, 0 # LDA, INY, UP )Y ADC, UP )Y STA, BOT LDA, XWR0 BRK, POP JMP, ;C

Mot utilisé par défaut par le mot d'exécution vectorisée EMIT. Ce mot affiche le caractère c sur le terminal vidéo ou sur l'imprimante selon que la variable PR du vocabulaire PRINTER est nulle ou non, la sélection étant obtenue par appuis successifs sur <CTRL> + <P> ou par le mot P-IN du vocabulaire PRINTER. Le contenu de la variable #OUT est incrémenté de une unité. Voir aussi (PEMIT) et (PRINT).

EMIT

DEFER EMIT ( c -- )

' (EMIT) IS EMIT

Mot d'exécution vectorisée. Affiche le caractère de code ASCII c sur le périphérique sélectionné. Le mot EMIT peut être vectorisé dans la version FORTH 83-STANDARD pour ORIC par l'un des mots suivants:

Selon le matériel utilisé, le code ASCII du caractère c peut être compris dans l'intervalle 0 <= c <= 127 ou 0 <= c <= 255. L'interprétation des codes compris entre 0 et 31 dépend du matériel utilisé, mais en règle générale, ce sont les codes ASCII standards qui sont exécutés. Attention, si vous utilisez les options de sélection de mode d'affichage ou de couleurs par l'intermédiaire du code ASCII ESC (27 en décimal) de votre ORIC, les commandes resteront spécifiques à votre matériel.

(CR)

CODE (CR) ( -- )

( versions ATMOS: )

XSAVE STX, 0D # LDA, CCD9 JSR, ( affichage du caractère dans A. )

0A # LDA, CCD9 JSR, 1A # LDY, 0 # LDA, UP )Y STA, INY, UP )Y STA, XSAVE LDX, NEXT, ;C

( version TELESTRAT: )

XCRLF BRK, 1A # LDY, 0 # LDA, UP )Y STA, INY, UP )Y STA, CLC, 1 # LDA, 1E # LDY, UP )Y ADC, UP )Y STA, 0 # LDA, INY, UP )Y ADC, UP )Y STA, NEXT, ;C

Exécute un retour chariot avec saut de ligne sur le terminal de sortie. Ce mot est exécuté par défaut par le mot CR. Il émet les codes ASCII 13 et 10. En impression, certaines imprimantes exécutent ces deux fonctions à la seule réception du code ASCII 13, ce qui provoque une impression en double interligne. Pour éviter ceci, il faut revectoriser CR comme suit:

ONLY FORTH DEFINITIONS DECIMAL

: RC ( -- ) 13 EMIT ;

ALSO PRINTER

: IMPRIME ( -- ) ['] (PRINT) IS EMIT ['] RC IS CR ;

: ECRAN ( -- ) ['] (EMIT) IS EMIT ['] (CR) IS CR ;

Et à partir de maintenant, tapez simplement IMPRIME pour déclencher une séance d'impression. Tapez ensuite ECRAN pour ramener l'affichage vers l'écran exclusivement. Si vous désirez une impression simultanée sur l'imprimante et l'écran, il faudra remplacer (PRINT) par (PEMIT) dans la définition de IMPRIME.

CR

DEFER CR ( -- )

' (CR) IS CR

Mot d'exécution vectorisée. Exécute par défaut le mot (CR). Exécute un retour chariot et le passage à la ligne suivante du curseur sur la console ou l'imprimante. Le contenu du compteur de caractères #OUT est remis à zéro et le contenu du compteur de lignes #LINE est incrémenté d'une unité.

FILL

CODE FILL ( adr cnt c -- )

3 # LDA, SETUP JSR, BEGIN, BEGIN, N 2+ CPY, 0= IF, N 3 + DEC, 0< IF, NEXT, THEN, THEN, N LDA, N 4 + )Y STA, INY, 0= UNTIL, N 5 + INC, AGAIN, ;C

Remplit une zone mémoire de cnt octets de longueur commençant à l'adresse adr avec le caractère de code c.

ERASE

: ERASE ( adr cnt -- )

0 FILL ;

Remplit avec le caractère "nul" (code ASCII 0) une chaîne explicite ou une zone de mémoire débutant à l'adresse adr et de longueur cnt. Voir aussi BLANK.

BLANK

: BLANK ( adr cnt -- )

BL FILL ;

Remplit avec des caractères 'espace' une chaîne explicite ou une zone mémoire de cnt octets débutant à l'adresse adr.

COUNT

CODE COUNT ( adr -- adr+1 cnt )

BOT X) LDA, BOT INC, 0= IF, BOT 1+ INC, THEN, PUSH0A JMP, ;C

Transforme une chaîne de caractères implicite en une chaîne de caractères explicite.

Exemples:

HEX 41034342. PAD 2! DECIMAL PAD COUNT TYPE affiche ABC (pour comprendre, cherchez un peu...).

: ECRIS BL WORD COUNT TYPE ;

ECRIS TEST affiche TEST.

Le mot COUNT incrémente une adresse et délivre son contenu. Ses utilisations peuvent donc dépasser le traitement des chaînes de caractères:

: PETIT-DUMP ( adr cnt -- ) 0 DO COUNT . LOOP DROP ;

16384 10 PETIT-DUMP affiche les contenus de 10 emplacements mémoire à partir de 16384.

TYPE

: TYPE ( adr cnt -- )

0 ?DO COUNT EMIT LOOP DROP ;

Affiche cnt caractères lus depuis l'emplacement mémoire d'adresse adr.

Exemple:

: TEST " Ceci est un test" ;

TEST dépose sur la pile les paramètres adr et cnt.

TYPE ( adr cnt -- ) affiche "Ceci est un test".

SPACE

: SPACE ( -- )

BL EMIT ;

Envoie un caractère "espace" vers le terminal (console, imprimante ou les deux).

SPACES

: SPACES ( n -- )

0 ?DO SPACE LOOP ;

Envoie n caractères "espace" vers le terminal.

STATLINE

BB80 CONSTANT STATLINE ( -- adr )

Constante délivrant l'adresse de début d'écran du terminal, en mode texte.

HEX

: HEX ( -- )

10 BASE ! ;

Sélectionne la base numérique hexadécimale. Dans la table initiale CTRL1, HEX est exécuté par action sur <CTRL> + <E>.

Exemple:

Conversion hexadécimale-décimale:

: H>D. ( n -- ) DECIMAL D. HEX ;

HEX 3FC6 H>D. affiche 16326.

C7 H>D. affiche 199.

DECIMAL

: DECIMAL ( -- )

0A BASE ! ;

Sélectionne la base numérique décimale. A l'initialisation du système, c'est cette base numérique qui est sélectionnée par défaut. Dans la table initiale CTRL1, DECIMAL est exécuté par action sur <CTRL> + <D>.

Exemple:

Conversion hexadécimale-décimale:

HEX 3F DECIMAL . affiche 63.

HOME

: HOME ( -- )

1E EMIT ;

Partie exécution du caractère de contrôle de renvoi du curseur en haut et à gauche de l'écran. Envoie le code ASCII 30 sur le terminal de sortie. Dans la table initiale CTRL1, HOME est exécuté par action sur <CTRL> + <B>.

KCLK

: KCLK ( -- )

( versions ATMOS: )

6 (EMIT) ;

( version TELESTRAT: )

40 FLGKBD CTOGGLE ;

Bascule: interrompt ou rétablit le déclic du clavier lors de l'appui sur une touche. Sur versions ATMOS, dans la table initiale CTRL1, KCLK est exécuté par action sur <CTRL> + <F>.

BS-IN

: BS-IN ( -- )

8 (EMIT) ;

Partie exécution du caractère de contrôle d'espace arrière. Envoie le code ASCII 8 sur le terminal de sortie, ce qui a pour effet de faire reculer le curseur d'un espace vers l'arrière sans effacement. Dans la table initiale CTRL1, BS-IN est exécuté par action sur <CTRL> + <H>.

FW-IN

: FW-IN ( -- )

9 (EMIT) ;

Partie exécution du caractère de contrôle d'espace avant. Envoie le code ASCII 9 sur le terminal de sortie, ce qui a pour effet de faire avancer le curseur d'un espace vers l'avant sans effacement. Dans la table initiale CTRL1, FW-IN est exécuté par action sur <CTRL> + <I>.

DOWN-IN

: DOWN-IN ( -- )

0A (EMIT) ;

Partie exécution du caractère de contrôle d'espace bas. Envoie le code ASCII 10 sur le terminal de sortie, ce qui a pour effet de faire avancer le curseur d'un espace vers le bas sans effacement. Dans la table initiale CTRL1, DOWN-IN est exécuté par action sur <CTRL> + <J>.

UP-IN

: UP-IN ( -- )

0B (EMIT) ;

Partie exécution du caractère de contrôle d'espace haut. Envoie le code ASCII 11 sur le terminal de sortie, ce qui a pour effet de faire reculer le curseur d'un espace vers le haut sans effacement. Dans la table initiale CTRL1, UP-IN est exécuté par action sur <CTRL> + <K>.

CLS

: CLS ( -- )

0C (EMIT) #LINE OFF ;

Partie exécution du caractère de contrôle d'effacement de l'écran. Envoie le code ASCII 12 sur le terminal de sortie, ce qui a pour effet d'effacer l'affichage vidéo. Dans la table initiale CTRL1, CLS est exécuté par action sur <CTRL> + <L>.

CAP-IN

: CAP-IN ( -- )

14 (EMIT) ;

Sur versions ATMOS uniquement. Partie exécution du caractère de contrôle de bascule clavier minuscules-majuscules. Envoie le code ASCII 20 sur le terminal de sortie, ce qui a pour effet de passer alternativement le clavier en minuscules ou en majuscules. Dans la table initiale CTRL1, CAP-IN est exécuté par action sur <CTRL> + <T>.

CLL-IN

: CLL-IN ( -- )

0E (EMIT) ;

Partie exécution du caractère de contrôle d'annulation d'entrée. Envoie le code ASCII 14 sur le terminal de sortie, ce qui a pour effet d'effacer les caractères précédemment entrés et de vider le tampon d'entrée. Dans la table initiale CTRL1, le mot CLL-IN est exécuté par <CTRL> + <N>.

NOOP

CODE NOOP ( -- )

JMP NEXT, ;C

Un des mots les plus utiles de FORTH. Ne fait rien! En fait, il permet de réserver des adresses mémoire au sein de définitions "auto-vectorisées". Il permet aussi de créer des tables telle que celle exécutant les caractères de contrôle CTRL1. Voir aussi DOES>.

CR-IN

: CR-IN ( n adr c -- n adr n )

SPAN ! OVER BL EMIT ;

Mot de contrôle des fonctions du clavier et utilisé dans la table CTRL1. Ce mot est exécuté à chaque action sur la touche <RETURN> ou par action sur <CTRL> + <M>.

DEL-IN

: DEL-IN ( n c -- n' | n' = 0 ou n-1 )

DROP DUP IF 1- 8 EMIT SPACE 8 ELSE 7 THEN EMIT ;

Exécute un retour chariot et efface le caractère courant, sinon émet seulement un signal sonore si le curseur est en début de ligne.

(CHAR)

: (CHAR) ( adr n c -- adr n+1 )

3DUP EMIT + C! 1+ ;

Traite un caractère ordinaire c en l'affichant et en le rajoutant au contenu du tampon dont l'adresse adr indique le début, et n la position relative du pointeur dans le tampon. L'adresse adr peut être n'importe quelle adresse mémoire. Ce mot est utilisé par défaut par le mot d'exécution vectorisée CHAR.

CHAR

DEFER CHAR ( adr n c -- adr n+1 )

' (CHAR) IS CHAR

Mot d'exécution vectorisée. Son exécution prend en compte un caractère habituel ou un code de contrôle frappé au clavier, l'affiche et le concatène au contenu du tampon d'entrée. Ce mot exécute par défaut le mot (CHAR) qui enregistre le caractère dans le tampon et incrémente cette position.

CTRL

VARIABLE CTRL ( -- adr )

' CTRL1 >BODY CTRL !

Variable dont le contenu pointe sur la table des caractères de contrôle. A l'initialisation, contient l'adresse du pfa de CTRL1.

Note: le vrai STANDARD attribue le nom CC à ce mot, ce qui est une petite bévue des concepteurs, car il faut alors faire précéder le nombre hexadécimal CC de 0 (s'il est fait usage de cette valeur), soit écrire 0CC, ceci afin d'éviter tout conflit. C'est pourquoi le nom CTRL a été choisi ici.

CTRL1

CREATE CTRL1 ( -- adr )

( versions ATMOS: )

] NOOP A-IN HOME C-IN DECIMAL HEX KCLK NOOP BS-IN FW-IN DOWN-IN UP-IN CLS CR-IN CLL-IN NOOP NOOP CURSOR NOOP SAVE-BUFFERS CAP-IN NOOP EMPTY-BUFFERS NOOP X-IN NOOP NOOP NOOP NOOP NOOP NOOP ONLY [

( version TELESTRAT: )

] NOOP A-IN HOME C-IN DECIMAL HEX NOOP NOOP BS-IN FW-IN DOWN-IN UP-IN CLS CR-IN CLL-IN NOOP NOOP CURSOR NOOP SAVE-BUFFERS NOOP NOOP EMPTY-BUFFERS NOOP X-IN NOOP NOOP NOOP NOOP NOOP NOOP ONLY [

Délivre l'adresse d'un tableau unidimentionnel. Son contenu détermine les actions du curseur en fonction des codes de contrôle tapés au clavier lors de l'utilisation du flot d'entrée. Tous les codes de contrôle, à l'exception des suivants, sont insérés au contenu du flot d'entrée:

A l'initialisation, l'adresse adr délivrée par CTRL1 est stockée dans la variable CTRL. Mais vous pouvez définir votre propre table de codes de contrôle comme suit:

CREATE CTRL2 ] C-IN C-IN ... [ CTRL2 CTRL !

Le premier mot C-IN correspond au code ASCII 0, le second au code ASCII 1 (<CTRL> + <A>), etc... Ceci généralement avec les 26 à 30 premiers codes ASCII. Dans la définition de CTRL1, le mot C-IN est vectorisé. Même remarque pour CTRL. Voir aussi CHAR.

EXPECT

: EXPECT ( adr cnt -- )

DUP SPAN ! SWAP 0 BEGIN 2 PICK OVER - WHILE KEY DUP BL < IF 2* CTRL @ + @ EXECUTE ELSE DUP 7F = IF DEL-IN ELSE CHAR THEN THEN REPEAT 2DROP DROP ;

Attend du terminal d'entrée l'introduction d'une chaîne de caractères de longueur maximale cnt rangée à l'adresse adr. Le terminal d'entrée est habituellement le clavier, mais peut être modifié en fonction de la revectorisation de KEY.

L'entrée d'une chaîne est achevée quand tous les caractères attendus sont introduits ou avant ce terme par l'appui d'un retour chariot. Les caractères de contrôle, activés par la table CTRL et la touche de correction <DEL>, sont traités directement en priorité sans enregistrement dans la chaîne. La variable SPAN conserve le nombre de caractères valides réellement entrés.

Exemple:

: REPONSE " NON!" ;

: TEST REPONSE EXPECT CR REPONSE TYPE ;

L'exécution de TEST et l'appui sur <RETURN> vous met en attente d'une réponse. Puis essayez <C> <RETURN> ou <Y>, <DEL>, <O>, <U>, <I>, <D>, <A>, <RETURN>. Notez après chaque essai la valeur prise par SPAN en tapant SPAN ?. Le résultat apparemment toujours incongru à 6 s'explique par le fait que le système a lui-même utilisé entre-temps EXPECT et que vous venez de taper SPAN ? qui fait 6 caractères.

QUERY

: QUERY ( -- )

TIB 50 EXPECT SPAN @ #TIB ! BLK OFF >IN OFF ;

Attend la frappe de données ou de commandes et place le résultat dans le tampon d'entrée.

Exemple:

: ATTENTE BEGIN QUERY INTERPRET .S 0 UNTIL ;

Provoque une exécution indéfinie de la définition ATTENTE. Pourtant, si vous tapez un mot FORTH quelconque, ou une suite de mots comme 2 3 +, ils seront exécutés et le contenu de la pile de données s'affichera. Ce mot illustre parfaitement la ré-entrance de l'interpréteur FORTH. Pour arrêter son fonctionnement, il faut taper la commande ABORT.

MIN

: MIN ( n2 n1 -- n )

2DUP > IF SWAP THEN DROP ;

Laisse sur la pile le plus petit de n2 ou de n1. Voir aussi MAX.

Exemple:

12 7 MIN . affiche 7.

MAX

: MAX ( n2 n1 -- n )

2DUP < IF SWAP THEN DROP ;

Délivre le plus grand de n2 ou n1. Voir aussi MIN.

Exemples:

12 7 MAX . affiche 12.

7 12 MAX . affiche 12.

Ce mot, associé au mot MIN permet d'encadrer dans un domaine borné l'exécution d'une fonction. Pour exemple, si vous désirez qu'une entrée numérique soit filtrée avec deux valeurs servant de bornes dans un domaine de définition précis (en graphisme pour exemple, pour que les coordonnées d'un point ne sortent pas de l'écran vidéo), on définit:

: FILTRE-X ( x -- x' ) 0 MIN 239 MAX ;

et à l'exécution:

-5 FILTRE-X . affiche 0.

0 FILTRE-X . affiche 0.

25 FILTRE-X . affiche 25.

239 FILTRE-X . affiche 239.

450 FILTRE-X . affiche 239.

BETWEEN

: BETWEEN ( n3 n2 n1 -- b )

>R OVER > SWAP R> > OR NOT ;

Comparateur d'intervalle. Délivre un flag booléen vrai si n3 est compris entre n2 et n1, bornes comprises, c'est-à-dire si n2 <= n3 <= n1. A noter que si n2 est supérieur à n1, BETWEEN n'a plus de sens et le flag booléen est toujours faux.

Exemples:

2 1 3 BETWEEN . affiche -1 (vrai).

2 3 1 BETWEEN . affiche 0 (faux).

WITHIN

: WITHIN ( n3 n2 n1 -- b )

1- BETWEEN ;

Renvoie un flag booléen vrai (b = -1) si n2 <= n3 < n1. Voir aussi BETWEEN.

D+

CODE D+ ( d2 d1 -- d | d = d2+d1 )

CLC, BOT 2+ LDA, BOT 6 + ADC, BOT 6 + STA, BOT 3 + LDA, BOT 7 + ADC, BOT 7 + STA, BOT LDA, BOT 4 + ADC, BOT 4 + STA, BOT 1+ LDA, BOT 5 + ADC, BOT 5 + STA, POPTWO JMP, ;C

Le nombre double précision d est le résultat de la somme des deux nombres double précision d2 et d1, correspondant à l'opération algébrique d = d2+d1.

Exemple:

123456. 654321. D+ D. affiche 777777.

DNEGATE

CODE DNEGATE ( d -- -d )

SEC, TYA, BOT 2+ SBC, BOT 2+ STA, TYA, BOT 3 + SBC, BOT 3 + STA, TYA, BOT SBC, BOT STA, TYA, BOT 1+ SBC, BOT 1+ STA, NEXT, ;C

Inverse le signe du nombre double précision signé d.

Exemples:

3. DNEGATE D. affiche -3.

-3. DNEGATE D. affiche 3.

S>D

: S>D ( n -- d )

DUP 0< ;

Transforme un nombre simple précision signé en nombre double précision signé.

Exemples:

3 S>D D. affiche 3.

-7 S>D D. affiche -7.

?DNEGATE

: ?DNEGATE ( d2 n -- d )

0< IF DNEGATE THEN ;

Change le signe du double d2 si n est négatif.

Exemples:

-123456. 7 ?DNEGATE D. affiche -123456.

DABS

: DABS ( d -- d' )

DUP ?DNEGATE ;

Renvoie sur la pile de données la valeur absolue d'un nombre double précision signé.

Exemples:

55. DABS D. affiche 55.

-55. DABS D. affiche 55.

*D

: *D ( n2 n1 -- d | d = n2*n1 )

2DUP XOR >R ABS SWAP ABS UM* R> ?DNEGATE ;

Multiplie deux nombres entiers, n2 et n1, et dépose le résultat d, qui est un nombre double précision (32 bits) sur la pile de données. Les valeurs n2 et n1 sont perdues. Les règles des signes appliquées à n2 et n1 sont identiques à celle du mot *.

Exemple:

-1000 2000 *D D. affiche -2000000.

M/MOD

: M/MOD ( d n -- nR nQ | d = n*nQ+nR )

?DUP IF DUP >R 2DUP XOR >R >R DABS R@ ABS UM/MOD SWAP R> ?NEGATE SWAP R> 0< IF NEGATE OVER IF 1- R@ ROT - SWAP THEN THEN R> DROP THEN ;

Division d'un nombre entier double précision d par un nombre entier simple précision n. Le quotient nQ et le reste nR sont des entiers simple précision signés.

Exemples:

100000. 25 M/MOD . . affiche 4000 0.

-100003. -5 M/MOD . . affiche 20000 -3.

MU/MOD

: MU/MOD ( ud u -- uR udQ | ud = u*udQ+uR )

>R 0 R@ UM/MOD R> SWAP >R UM/MOD R> ;

Divise un nombre entier double précision par un nombre entier. Délivre un quotient en double précision et un reste entier.

Exemple:

400003. 5 MU/MOD D. . affiche 80000 3.

*

: * ( n2 n1 -- n | n = n2*n1 )

UM* DROP ;

Effectue la multiplication signée de n2 par n1 et laisse le résultat n sur la pile de données. Attention aux effets de débordement de capacité risquant d'entrainer des erreurs en cas de multiplication de deux nombres entiers trop importants. Pour être valide, le résultat doit rester dans l'intervalle -32768 ... 32767.

Le signe du résultat dépend du signe des nombres n2 et n1.

Exemples:

45 3 * . affiche 135, ce qui est exact,

45 1000 * . affichera un résultat faux.

/MOD

: /MOD ( n2 n1 -- nR nQ | n2 = n1*nQ+nR )

>R S>D R> M/MOD ;

Opérateur division entière signée avec reste. nQ est le quotient plancher et nR le reste de la division de n2 par n1. Le reste a le même signe que le diviseur. Voir aussi / et MOD.

Exemples:

22 7 /MOD . . affiche 3 1.

22 -7 /MOD . . affiche -4 -6.

-22 7 /MOD . . affiche -4 6.

-22 -7 /MOD . . affiche 3 -1.

/

: / ( n2 n1 -- nQ )

/MOD NIP ;

Opérateur division entière signée. nQ est le quotient plancher (entier inférieur) de n2 et n1.

Note: le STANDARD prévoit qu'un message d'erreur soit généré en cas de division par zéro.

Exemples:

7 2 / . affiche 3.

-7 2 / . affiche -4.

MOD

: MOD ( n2 n1 -- nR )

/MOD DROP ;

Délivre le reste nR de la division de n2 par n1.

Exemple:

-103 -5 MOD . affiche -3.

*/MOD

: */MOD ( n3 n2 n1 -- nR nQ | n3*n2 = n1*nQ+nR )

>R *D R> M/MOD ;

Effectue le produit des nombres entiers n3 et n2 et divise le résultat par n1. Le résultat final correspond au quotient nQ et au reste nR de l'opération (n3*n2)/n1. L'exécution de ce mot en remplacement des opérations de multiplication et de division simultanées permet de supprimer l'erreur apparaissant lors du dépassement de capacité pendant la multiplication.

Les signes de nR et nQ dépendent des signes n3, n2 et n1. Voir aussi /*.

Exemples:

302 7 100 */MOD . . affiche 21 2.

1027 25 100 */MOD . . affiche 256 3.

/*

: /* ( n3 n2 n1 -- nQ )

*/MOD NIP ;

Effectue le produit des nombres entiers n3 et n2 et divise le résultat par n1. Le résultat final correspond au quotient signé nQ de l'opération (n3*n2)/n1.

Le signe du résultat dépend des signes de n3, n2 et n1.

Note: le vrai nom de ce mot est */ dans le STANDARD.

Exemples:

1027 25 100 /* . affiche 256 (soit 25% de 1027).

Soit à calculer 7 pour 100 d'un nombre:

: 7% 7 100 /* ;

100 7% . affiche 7.

300 7% . affiche 21.

Attention: 302 7% affiche aussi 21, car le mot /* ne calcule le quotient nQ qu'en nombre entier signé. Notez que le résultat intermédiaire est sur 32 bits, ce qui donne tout son intérêt à ce mot pour éviter les débordements.

UPPER

CODE UPPER ( adr cnt -- )

2 # LDA, SETUP JSR, N LDY, BEGIN, 0 # CPY, 0= NOT IF, DEY, N 2+ )Y LDA, G000 JSR, N 2+ )Y STA, ELSE, NEXT, THEN, AGAIN,

LABEL G000

61 # CMP, CS IF, 7B # CMP, CS NOT IF, SEC, 20 # SBC, THEN, THEN, RTS, ;C

Transforme tous les caractères minuscules contenus dans la chaîne de caractères pointés par adr et cnt en caractères majuscules.

Si vous désirez conserver un original de la chaîne en caractères minuscules, assurez-vous d'abord de la sauvegarder avant conversion des caractères.

Exemple:

: TEST " ceci est un test" ;

TEST TYPE affiche "ceci est un test".

TEST UPPER TEST TYPE affiche "CECI EST UN TEST".

LEAVE

CODE LEAVE ( -- )

PLA, PLA, PLA, PLA, PLA, IP STA, PLA, IP 1+ STA, NEXT, ;C

Mot d'exécution immédiate. Son exécution permet l'interruption du déroulement d'une boucle de type DO ... LOOP ou DO ... +LOOP.

Exemple:

VARIABLE TOTAL

: SIGMA ( n9 n8 ... n1 n0 -- ntotal si nn <> 0 ) 0 TOTAL ! 10 0 DO ?DUP IF TOTAL +! ELSE ." INTERROMPU" CR LEAVE THEN LOOP ;

et en exécution:

1 2 3 4 5 6 7 8 9 10 SIGMA TOTAL ? affiche 55.

1 3 7 0 4 6 8 5 2 1 SIGMA TOTAL ? affiche INTERROMPU 11 car la présence du nombre 0 a interrompu la boucle.

?LEAVE

CODE ?LEAVE ( b -- )

INX, INX, BOT 2- LDA, BOT 1- ORA, 0= IF, NEXT, THEN, ['] LEAVE >BODY JMP, ( pfa de LEAVE ) ;C

Abandonne la boucle en cours d'exécution si le flag booléen b est vrai. Dans le cas contraire, l'exécution se poursuit.

HERE

: HERE ( -- adr )

DP @ ;

Délivre l'adresse du pointeur de dictionnaire, c'est-à-dire l'adresse du premier emplacement libre dans le dictionnaire. En cas de sauvegarde de votre programme sous forme compilée, c'est cette adresse qui doit être stockée dans la variable FENCE par la séquence HERE FENCE ! (BYE le fait automatiquement).

PAD

: PAD ( -- adr )

HERE 50 + ;

Délivre l'adresse d'une zone de stockage temporaire pour des chaînes de caractères.

Le PAD a une position qui varie dans la mémoire avec la taille du dictionnaire, c'est-à-dire l'importance que vous devez donner au mot temporaire.

Exemple:

PAD 80 EXPECT

PAD 80 TYPE affiche la chaîne de caractères précédemment tapée.

-TRAILING

: -TRAILING ( adr cnt -- adr cnt' )

DUP 0 DO 2DUP + 1- C@ BL - ?LEAVE 1- LOOP ;

Renvoie les paramètres d'une chaîne de caractères, à savoir l'adresse et la longueur, après avoir supprimé les espaces superflus situés en fin de chaîne.

Exemple:

: TITRE " MENU GENERAL " ;

TITRE TYPE affiche "MENU GENERAL ".

TITRE -TRAILING TYPE affiche "MENU GENERAL".

COMP

CODE COMP ( adr1 adr2 cnt -- n )

3 # LDA, SETUP JSR, BEGIN, N CPY, 0= NOT IF, N 2+ )Y LDA, N 4 + )Y CMP, 0= NOT IF, CS NOT IF, 1 # LDA, PUSH0A JMP, THEN, FF # LDA, PHA, PUSH JMP, THEN, INY, ELSE, 0 # LDA, PUSH0A JMP, THEN, AGAIN, ;C

Réalise une comparaison de chaînes de caractères commençant à adr1 et adr2, ceci sur cnt caractères. Si les deux chaînes sont égales, le résultat du test est nul. Si les deux chaînes sont différentes, le résultat est -1 ou 1. Si c'est -1 qui est renvoyé, la chaîne 1 est inférieure à la chaîne 2. Si c'est 1 qui est renvoyé, la chaîne 1 est supérieure à la chaîne 2.

Toutes les comparaisons sont relatives au jeu de caractères ASCII. La comparaison tient dûment compte des différences entre caractères majuscules et minuscules. Voir aussi CAPS-COMP et COMPARE.

Exemples:

: TEST1 " VACHE" DROP " VACCIN" DROP 3 COMP . ;

TEST1 affiche 0.

: TEST2 " VACHE" DROP " VACCIN" DROP 4 COMP . ;

TEST2 affiche 1.

CAPS-COMP

CODE CAPS-COMP ( adr1 adr2 cnt -- n )

3 # LDA, SETUP JSR, BEGIN, N CPY, 0= NOT IF, N 4 + )Y LDA, G000 JSR, ( sous-programme de UPPER: voir ce mot. )

N 1- STA, N 2+ )Y LDA, G000 JSR, N 1- CMP, 0= NOT IF, CS NOT IF, 1 # LDA, PUSH0A JMP, THEN, FF # LDA, PHA, PUSH JMP, THEN, INY, ELSE, 0 # LDA, PUSH0A JMP, THEN, AGAIN, ;C

Compare deux chaînes de caractères en ne tenant pas compte des différences majuscules/minuscules. Chaque caractère minuscule est converti en caractère majuscule avant la comparaison de chaîne. Ainsi, les caractères "a" et "A" sont considérés comme étant identiques. Voir aussi COMP et COMPARE.

Exemple:

: TEST ( -- ) " VACHE" DROP " vache" CAPS-COMP . ;

TEST affiche 0.

Les chaînes "VACHE" et "vache" sont identiques.

CAPS

VARIABLE CAPS ( -- adr )

-1 CAPS !

Variable dont le contenu permet le contrôle de la conversion des caractères alphabétiques minuscules en caractères majuscules. La conversion a lieu si son contenu est vrai, c'est-à-dire égal à moins un. Ainsi, en exécutant la séquence -1 CAPS !, ou mieux CAPS ON, vous pourrez taper indifféremment vos définitions en caractères minuscules ou majuscules, le système se chargeant de la conversion.

Sur les systèmes FORTH 83-STANDARD pour ORIC, CAPS est vraie par défaut.

COMPARE

: COMPARE ( adr1 adr2 cnt -- n )

CAPS @ IF CAPS-COMP ELSE COMP THEN ;

Compare deux chaînes de caractères. Si le contenu de la variable CAPS est vrai (égal à -1), les caractères des chaînes sont convertis en majuscules avant comparaison. Voir aussi CAPS-COMP et COMP.

Exemples:

: TEST1 0 CAPS ! " VACHE" DROP " vache" COMPARE . ;

TEST1 affiche 0.

: TEST2 -1 CAPS ! " VACHE" DROP " vache" COMPARE . ;

TEST2 affiche -1.

DIGIT

CODE DIGIT ( c base -- n b )

SEC, BOT 2+ LDA, ASCII 0 # SBC, 0> IF, ( ASCII >= "0" ) 0A # CMP, 0> IF, ( ASCII > "9" ) SEC, 7 # SBC, 0A # CMP, 0< IF, ( ASCII >= "A" ) SWAP THEN, ( ASCII dans [ 0 ... 9 ] U [ A ... [ --> accumulateur = digit )

BOT CMP, 0< IF, BOT 2+ STA, FF # LDA, PHA, PUT JMP, THEN, ( ASCII incorrect ) THEN, THEN, 0 # LDA, PHA, PUT JMP, ;C

Primitive de conversion ASCII-numérique. Cherche à convertir un caractère donné en un nombre dans la base numérique spécifiée. Laisse ce nombre sur la pile et un drapeau booléen vrai si le caractère est valide dans cette base numérique, sinon laisse le caractère inchangé et un drapeau booléen faux. Notez l'utilisation de SWAP pour croiser les références.

Exemples:

DECIMAL

ASCII C 16 DIGIT . . affiche -1 12.

ASCII H 16 DIGIT . . affiche 0 72.

DOUBLE?

: DOUBLE? ( -- b )

DPL @ 1+ 0<> ;

Délivre un drapeau booléen vrai si la dernière chaîne numérique interprétée est celle d'un nombre en double précision. Rappelons qu'une chaîne ASCII est interprétée en un nombre double précision si et seulement si elle contient un point décimal quelque soit sa position dans la chaîne.

CONVERT

: CONVERT ( ud1 adr1 -- ud2 adr2 )

BEGIN 1+ DUP >R C@ BASE @ DIGIT WHILE SWAP BASE @ UM* DROP ROT BASE @ UM* D+ DOUBLE? IF 1 DPL +! THEN R> REPEAT DROP R> ;

Primitive de conversion d'une chaîne de caractères en un nombre double précision non signé. Le nombre 32 bits ud1 est généralement initialisé avec une valeur nulle en début de conversion, adr1 l'adresse de la chaîne, ud2 le nombre résultant de la conversion, adr2 l'adresse du premier caractère non convertible dans la chaîne. Voir aussi NUMBER.

(NUMBER?)

: (NUMBER?) ( adr -- d b )

0 0 ROT DUP 1+ C@ ASCII . = DUP >R - -1 DPL ! BEGIN CONVERT DUP C@ ASCII , ASCII / BETWEEN WHILE 0 DPL ! REPEAT -ROT R> IF DNEGATE THEN ROT C@ BL = ;

Convertit la chaîne de caractères pointée par l'adresse adr en un nombre double précision. Ce mot est utilisé dans la définition du mot NUMBER?. Le flag booléen b vrai indique si la conversion s'est bien passée. Voir aussi NUMBER.

BOUNDS

: BOUNDS ( adr cnt -- adrfin adrdébut )

OVER + SWAP ;

Convertit une chaîne explicite en ses adresses de début et de fin. Cette fonction sert par exemple à préparer une boucle DO ... LOOP.

NUMBER?

: NUMBER? ( adr -- d b )

FALSE OVER COUNT BOUNDS ?DO I C@ BASE @ DIGIT NIP IF DROP TRUE LEAVE THEN LOOP IF (NUMBER?) ELSE DROP 0 0 FALSE THEN ;

Convertit la chaîne de caractères pointée par adr, la longueur de ladite chaîne étant contenue dans adr, en un nombre double précision. Le mot NUMBER? teste si le signe "-" est présent et met un pointeur correspondant à la position du dernier délimiteur dans la variable DPL. La chaîne doit se terminer par un espace. Un flag booléen vrai indique que la conversion a réussi.

NUMBER

DEFER NUMBER ( adr -- d )

' (NUMBER) IS NUMBER

Mot d'exécution vectorisée. A l'initialisation, ce mot exécute le mot (NUMBER) dont l'exécution convertit une chaîne de caractères en un nombre double précision signé. Le fait que ce mot soit vectorisé est très intéressant. On peut redéfinir le mot (NUMBER) et affecter la nouvelle définition en tant que vecteur à NUMBER. Ainsi, vous pouvez modifier le comportement de l'interpréteur en admettant systématiquement un nombre en tant que nombre double précision ou un nombre en virgule flottante. Mieux encore, si un mot n'existe pas dans le dictionnaire et si ce n'est pas un nombre, votre nouvelle définition peut le convertir automatiquement en un mot de type DEFER, ce qui permet la récursivité croisée. Voir aussi NUMBER?.

R0RP!

CODE R0RP! ( -- | ... n1 == )

XSAVE STX, 8 # LDY, UP )Y LDA, TAX, TXS, XSAVE LDX, NEXT, ;C

Vide la pile retour; à n'utiliser que dans une boucle infinie (cas de l'interpréteur) sous peine de tuer le FORTH!

ABORT

DEFER ABORT ( -- )

' (ABORT) IS ABORT

Interrompt l'exécution du mot en cours, restaure les piles de retour et de données à leur état primitif et redonne le contrôle à l'utilisateur. L'exécution de ce mot renvoie à la boucle d'interprétation de l'interpréteur FORTH. En général, il est utilisé pour la gestion des erreurs. Voir aussi ABORT".

?ERROR

DEFER ?ERROR ( adr cnt b -- )

' (?ERROR) IS ?ERROR

Mot d'exécution vectorisée exécutant par défaut le mot (?ERROR). Ce mot affiche la chaîne de caractères commençant à l'adresse adr et de longueur cnt si le flag booléen b est vrai. Ce mot est utilisé par (ABORT"). En cas d'erreur lors de la lecture du contenu d'un bloc écran, le mot WHERE sera exécuté, permettant ainsi de pointer l'erreur dans le code source.

WHERE

DEFER WHERE ( adr n -- )

' (WHERE) IS WHERE

Mot d'exécution vectorisée. Ce mot est prévu sur les systèmes FIG (tel TELE-FORTH V1.1 pour ORIC TELESTRAT) et 79-STANDARD pour exécuter une réédition en cas d'erreur de compilation pendant la lecture du contenu d'un bloc écran. Exécute normalement (WHERE).

(?ERROR)

: (?ERROR) ( adr cnt b -- )

IF BLK @ IF >IN @ BLK @ WHERE THEN SPACE TYPE SPACE ABORT ELSE 2DROP THEN ;

Mot exécuté par défaut par le mot ERROR. Ce mot exécute WHERE puis affiche la chaîne de caractères dont l'adresse adr et la longueur cnt sont sur la pile si b est vrai (différent de zéro).

Exemple:

: FULL? ( -- ) " pile pleine" 1 (?ERROR) ;

(ABORT'')

: (ABORT") ( b -- )

R@ COUNT ROT ?ERROR R> COUNT + >R ;

Mot compilé par le mot d'exécution immédiate ABORT". Ce mot affiche la chaîne de caractères précédemment compilée par ABORT" si le flag booléen b est vrai, puis exécute ?ERROR et réinitialise le pointeur de pile de retour.

?MISSING

: ?MISSING ( b -- )

IF HERE COUNT TYPE TRUE ABORT" inconnu dans ce contexte" THEN ;

Mot utilisé par l'interpréteur externe. Informe l'utilisateur qu'un mot n'est pas défini dans le vocabulaire courant ou dans l'ordre de recherche courant.

(NUMBER)

: (NUMBER) ( adr -- d )

NUMBER? NOT ?MISSING ;

Convertit la chaîne dont la longueur est pointée par le contenu de adr en un nombre double précision. La chaîne doit se terminer par un caractère "espace", sinon il se produit une erreur. Ce mot est utilisé par défaut par le mot d'exécution vectorisée NUMBER.

HOLD

: HOLD ( c -- )

-1 HLD +! HLD @ C! ;

Insère le caractère c lors d'un formatage de chaîne. Voir aussi <#, #, #S, #> et SIGN.

Exemple:

Pour bien présenter vos dates:

: .DATE ( d -- ) <# # # ASCII / HOLD # # ASCII / HOLD # # #> TYPE SPACE ;

150891. .DATE affiche 15/08/91.

<#

: <# ( -- )

PAD HLD ! ;

Marque le début d'une conversion numérique-ASCII en initialisant l'adresse de construction de la chaîne au niveau du PAD ("bloc-note", voir ce mot). Voir aussi #, HOLD, #S, #> et SIGN.

#>

: #> ( d -- adr cnt )

2DROP HLD @ PAD OVER - ;

Termine une conversion numérique-ASCII. Ce mot enlève le nombre double précision d et dépose sur la pile l'adresse de la chaîne formatée ainsi que sa longueur. Ces paramètres sont utilisés par TYPE pour afficher la chaîne, mais ils peuvent également être utilisés à des fins de stockage ou de manipulation de chaînes. Le mot #> est utilisé en fin de séquence de format de la chaîne définie à partir des mots <# et #. Voir aussi HOLD, #S et SIGN.

SIGN

: SIGN ( n -- )

0< IF ASCII - HOLD THEN ;

Si n est négatif, le caractère ASCII "-" (signe moins) est ajouté à l'affichage du nombre à éditer sous forme de chaîne. S'utilise ordinairement entre <# et #>. Voir aussi #, HOLD et #S.

#

: # ( d -- d' )

BASE @ MU/MOD ROT 9 OVER < IF 7 + THEN ASCII 0 + HOLD ;

Utilisé pour formater un nombre lors d'une conversion numérique-ASCII. Réalise une conversion binaire-ASCII de un chiffre à partir du reste de la division de d avec le contenu de la variable BASE. La valeur du caractère ASCII ainsi calculée est placée dans un tampon provisoire. Le quotient d' résultant de la division de d par le contenu de BASE reste sur la pile. Ce mot s'utilise entre les mots <# et #>. Voir aussi HOLD, #S et SIGN.

Exemple:

: H. ( n -- ) HEX 0 <# 4 0 DO # LOOP #> TYPE SPACE DECIMAL ;

55 H. affiche 0037.

#S

: #S ( d -- 0. )

BEGIN # 2DUP OR 0= UNTIL ;

Réalise une conversion binaire-ASCII comme le ferait une succession de #, ceci tant que la valeur d n'est pas nulle. La valeur restant sur la pile est un nombre double précision de valeur nulle. Voir aussi <#, HOLD, #> et SIGN.

Exemple:

: B. ( n -- ) 2 BASE ! 0 <# #S #> TYPE SPACE DECIMAL ;

33 B. affiche 100001.

(U.)

: (U.) ( u -- adr cnt )

0 <# #S #> ;

Convertit un nombre entier non signé en une chaîne de caractères. Ce mot est utilisé dans la définition des mots U. et U.R.

U.

: U. ( u -- )

(U.) TYPE SPACE ;

Le nombre u est affiché comme nombre entier non signé, sans sélection d'un format particulier, ceci dans la base numérique courante.

Exemples:

3 U. affiche 3.

-1 U. affiche 65535 (eh oui, étonnant non?).

50000 DUP . U. affiche -15536 50000.

U.R

: U.R ( u c -- )

>R (U.) R> OVER - SPACES TYPE ;

Affichage d'un nombre entier simple précision u dans un champ de c espaces, cadré à droite. Les caractères les plus à gauche non significatifs sont remplis avec le caractère "espace".

Exemples:

10 6 U.R affiche " 10".

-4 6 U.R affiche " 65532" (même raison que pour U.).

(.)

: (.) ( n -- adr cnt )

DUP ABS 0 <# #S ROT SIGN #> ;

Convertit un nombre double précision en une chaîne de caractères déterminée par l'adresse adr de début de la chaîne et la longueur cnt de cette chaîne. La conversion s'effectue dans la base numérique courante. Ce mot est utilisé par les mots . et .R. La chaîne de caractères résultant de la conversion ne contient pas d'espace en début et fin de chaîne.

Exemple:

3654 (.) TYPE affiche la chaîne de caractères "3654".

.

: . ( n -- )

(.) TYPE SPACE ;

Affiche le nombre entier signé dont la valeur est située au sommet de la pile de données, ceci dans la base numérique courante. Après exécution de ce mot, le nombre n ne figure plus au sommet de la pile.

Exemples:

45 . affiche 45.

45 HEX . DECIMAL affiche 2D.

45 8 BASE ! . DECIMAL affiche 55.

.( /) 1234 . .( /) affiche /1234 /.

.R

: .R ( n c -- )

>R (.) R> OVER - SPACES TYPE ;

Affiche le nombre entier n dans un champ de c caractères avec justification à droite. Si le nombre de caractères à afficher est supérieur à c, il se produit une condition d'erreur. Voir aussi D.R.

Exemples:

45 10 .R affiche " 45".

-3 10 .R affiche " -3".

175 10 .R affiche " 175".

.( /) 1234 6 .R .( /) affiche / 1234/.

(UD.)

: (UD.) ( ud -- adr cnt )

<# #S #> ;

Convertit un nombre double précision non signé en une chaîne de caractères. Ce mot est utilisé dans la définition du mot UD.

UD.

: UD. ( ud -- )

(UD.) TYPE SPACE ;

Affichage d'un nombre double précision (32 bits) en valeur absolue.

Exemples:

55. UD. affiche 55.

-1. UD. affiche 4294967295.

(D.)

: (D.) ( d -- adr cnt )

TUCK DABS <# #S ROT SIGN #> ;

Convertit un nombre double précision signé en une chaîne de caractères. Ce mot est utilisé par les mots D. et D.R. Aucun espace n'est rajouté devant ou derrière la chaîne de caractères.

Exemple:

3654. (D.) TYPE affiche la chaine "3654".

D.

: D. ( d -- )

(D.) TYPE SPACE ;

Affichage d'un nombre double précision signé. Tout nombre contenant un point décimal est assimilé à un nombre entier double précision au format 32 bits. Mais lors des opérations arithmétiques, le système FORTH ne tient pas compte de la position du point décimal. Ainsi: 32.55 4.472 D+ ou 0.3255 4472. D+ délivreront le même résultat.

Exemples:

32.55 44.72 D+ D. affiche 7727.

.( /) 12345678. D. .( /) affiche /12345678 /.

D.R

: D.R ( d c -- )

>R (D.) R> OVER - SPACES TYPE ;

Affichage d'un nombre double précision signé cadré à droite dans un champ de c caractères. Les caractères les plus à gauche sont remplis avec des espaces s'ils ne contiennent pas de chiffres significatifs.

Exemples:

55. 10 D.R affiche " 55".

3. 10 D.R affiche " 3".

4315. 10 D.R affiche " 4315".

.( /) 12345678. 10 D.R .( /) affiche / 12345678/.

SKIP

CODE SKIP ( adr1 cnt1 c -- adr2 cnt2 )

3 # LDA, SETUP JSR, BEGIN, N 2+ LDA, N 3 + ORA, 0= NOT IF, N 4 + )Y LDA, N CMP, 0= IF, N 4 + INC, 0= IF, N 5 + INC, THEN, SEC, N 2+ LDA, 1 # SBC, N 2+ STA, N 3 + LDA, 0 # SBC, N 3 + STA, ROT AGAIN, THEN, THEN, 4 # LDY, BEGIN, N 1+ ,Y LDA, DEX, BOT STA, DEY, 0= UNTIL, NEXT, ;C

Explore le contenu d'une chaîne de caractères spécifiée par adr1 cnt1 tant qu'il trouve le caractère c. Quand le caractère n'est plus trouvé, il délivre l'adresse de la position de ce caractère et la longueur de la chaîne résiduelle. Notez l'utilisation de ROT pour croiser les références.

SCAN

CODE SCAN ( adr1 cnt1 c -- adr2 cnt2 )

3 # LDA, SETUP JSR, BEGIN, N 2+ LDA, N 3 + ORA, 0= NOT IF, N 4 + )Y LDA, N CMP, 0= NOT IF, N 4 + INC, 0= IF, N 5 + INC, THEN, SEC, N 2+ LDA, 1 # SBC, N 2+ STA, N 3 + LDA, 0 # SBC, N 3 + STA, ROT AGAIN, THEN, THEN, 4 # LDY, BEGIN, N 1+ ,Y LDA, DEX, BOT STA, DEY, 0= UNTIL, NEXT, ;C

Explore le contenu d'une chaîne de caractères spécifiée par adr1 cnt1 à la recherche du caractère c. Quand le caractère est trouvé, il délivre l'adresse de la position de ce caractère et la longueur de la chaîne résiduelle.

/STRING

: /STRING ( adr1 cnt1 n -- adr2 cnt2 )

OVER MIN ROT OVER + -ROT - ;

Partie droite d'une chaîne de caractères après son nième caractère. Les chaînes (adr1, cnt1) et (adr2, cnt2) sont des chaînes explicites, avec adr2 = adr1+n, cnt2 = cnt1-n (une chaîne est explicite quand elle est décrite par son adresse de début et sa longueur. Une chaîne implicite est donnée par la seule adresse de début dont l'octet initial donne la longueur: voir COUNT).

Exemples:

Un mot utilisant les mêmes arguments pour donner la sous-chaîne des n derniers caractères s'écrirait:

: RIGHT OVER SWAP - /STRING ;

Tandis que la sous-chaîne à gauche des n premiers caractères serait:

: LEFT NIP ;

MOVE

: MOVE ( srceAdr destAdr byteCnt -- )

-ROT 2DUP U< IF ROT CMOVE> ELSE ROT CMOVE THEN ;

Déplace byteCnt octets des adresses srceAdr à destAdr sans recouvrement. Très utile si vous hésitez entre CMOVE et CMOVE>.

PLACE

: PLACE ( srceAdr cnt destAdr -- )

2DUP C! 1+ SWAP MOVE ;

Déplace le contenu de la chaîne de caractères explicite pointée par srceAdr cnt vers la zone mémoire débutant par destAdr.

SOURCE

DEFER SOURCE ( -- adr cnt )

' (SOURCE) IS SOURCE

Mot d'exécution vectorisée. A l'initialisation, exécute par défaut le mot (SOURCE). Renvoie la chaîne de caractères devant servir de flot d'entrée. Au besoin, celle-ci est prélevée sur la mémoire de masse.

PARSE-WORD

: PARSE-WORD ( c -- adr cnt )

>R SOURCE TUCK >IN @ /STRING R@ SKIP OVER SWAP R> SCAN >R OVER - ROT R> DUP 0<> + - >IN ! ;

Explore le flot d'entrée jusqu'à la rencontre du caractère c. Le reste de la chaîne est omis. Dépose sur la pile l'adresse et la longueur de la chaîne après mise à jour du pointeur contenu dans la variable >IN.

PARSE

: PARSE ( c -- adr cnt )

>R SOURCE >IN @ /STRING OVER SWAP R> SCAN >R OVER - DUP R> 0<> - >IN +! ;

Explore le flot d'entrée jusqu'à la rencontre du caractère c. Dépose sur la pile l'adresse et la longueur de la chaîne après mise à jour du pointeur contenu dans la variable >IN.

WORD

: WORD ( c -- adr )

PARSE-WORD HERE PLACE HERE DUP COUNT + BL SWAP C! ;

Scrute le contenu du flot d'entrée jusqu'à la rencontre du caractère séparateur de code ASCII c. Renvoie une chaîne de caractères à l'adresse pointée par HERE. A noter qu'il y a toujours un espace à la fin de cette chaîne.

(

: ( ( -- )

ASCII ) PARSE 2DROP ; IMMEDIATE

Mot d'exécution immédiate. Ce mot signale la présence d'un commentaire dont le délimiteur est une parenthèse fermée. Les caractères situés entre ( et ) ne sont pas compilés ni exécutés. Le mot ( est séparé du début du commentaire par au moins un caractère "espace" obligatoire, aucun espace n'étant requis entre la fin du commentaire et le signe ). Quand on désire réserver toute une ligne à un commentaire, on utilisera la barre de fraction inverse en début de commentaire. Dans ce cas, le commentaire est compris entre ce signe et la fin de la ligne courante. Voir les sources .FTH.

Exemple:

: H. ( n -- ) ( affichage hexa d'un nombre entier)

HEX ( sélectionne la base numérique hexadécimale)

. DECIMAL ( affichage de n et retour base décimale) ;

: ( -- )

END? ON ; IMMEDIATE

Mot blanc. L'identificateur de ce mot est composé d'un seul caractère de code ASCII espace (C0 A0).

HASH

CODE HASH ( adr1 adr2 -- n )

2 # LDA, SETUP JSR, 1 # LDY, N 2+ )Y LDA, 3 # AND, .A ASL, N ADC, PHA, 0 # LDA, N 1+ ADC, PUSH JMP, ;C

C'est l'opérateur de "hashage" qui permet à chaque vocabulaire d'être tissé en quatre brins indépendants. Le nombre de brins est fixé à 4 dans les systèmes FORTH 83-STANDARD pour ORIC. Dans chaque vocabulaire, les mots sont liés les uns aux autres dans l'un seulement des 4 brins entremêlés tout au long du vocabulaire. Le champ paramètre du nom de vocabulaire contient quatre cellules pointant le lfa de chaque tête de brin. Il suffit de savoir dans quel brin doit se situer un mot pour réduire les recherches au quart seulement des mots du vocabulaire. On comprend l'intérêt du dispositif pour accélérer les compilations. Le brin dans lequel doit se situer un mot est déterminé par la première lettre de ce mot, plus précisément par les deux bits de poids faible du premier caractère (00, 01, 10 ou 11, ce qui donne bien quatre possibilités).

Ainsi, dans un vocabulaire, les mots commençant par un A, un E ou un I, ou ceux commençant par (AEIMQU) ou (BFJNRV) sont dans un même brin.

Adr1 étant l'adresse d'une chaîne implicite de caractères, adr2 pointant un vocabulaire, n est le hash-code de la chaîne concernée.

Evidemment HASH complique sérieusement des mots travaillant sur les vocabulaires tels que FIND, WORDS ou FORGET, mais heureusement, ces mots sont déjà écrits et fonctionnent très bien, merci!

(FIND)

CODE (FIND) ( adr lfa -- cfa b )

2 # LDA, SETUP JSR, BEGIN, N LDA, N 1+ ORA, 0= IF, DEX, DEX, N 2+ LDA, BOT STA, N 3 + LDA, BOT 1+ STA, 0 # LDA, PUSH0A JMP, THEN, 1 # LDY, N )Y LDA, N 5 + STA, DEY, N )Y LDA, N 4 + STA, CLC, 2 # LDA, N ADC, N STA, TYA, N 1+ ADC, N 1+ STA, N )Y LDA, N 2+ )Y EOR, 3F # AND, 0= IF, BEGIN, INY, N )Y LDA, N 2+ )Y EOR, .A ASL, 0= IF, SWAP CS UNTIL, DEX, DEX, INY, CLC, TYA, N ADC, BOT STA, 0 # LDY, TYA, N 1+ ADC, BOT 1+ STA, N )Y LDA, .A ROL, 0< IF, 1 # LDA, PUSH0A JMP, THEN, FF # LDA, PHA, PUSH JMP, THEN, THEN, N 4 + LDA, N STA, N 5 + LDA, N 1+ STA, AGAIN, ;C

Provoque la recherche d'un mot dans le dictionnaire. Si le mot est trouvé, il dépose le cfa de ce mot sur la pile de données; si le mot recherché est immédiat, le flag booléen b est égal à 1; si le mot n'est pas immédiat, le flag booléen b est égal à -1. Si le mot recherché n'est pas trouvé, l'adresse de la chaîne est retournée avec un flag booléen nul.

FIND

: FIND ( adr -- cfa b )

PRIOR OFF FALSE #VOCS 0 DO DROP CONTEXT 1 2* + @ DUP IF DUP PRIOR @ OVER PRIOR ! = IF DROP FALSE ELSE OVER SWAP HASH @ (FIND) DUP ?LEAVE THEN THEN LOOP ;

Recherche le cfa d'un mot à partir du libellé de ce mot défini par la chaîne implicite située à l'adresse adr. Si le mot n'est pas trouvé dans le dictionnaire, il laisse l'adresse de cette chaîne suivie d'un flag booléen faux. Si le mot est trouvé, il laisse le code exécutif (cfa) de ce mot sur la pile suivi d'un flag booléen vrai.

DEFINED

: DEFINED <mot> ( -- cfa b )

BL WORD CAPS @ IF DUP COUNT UPPER THEN FIND ;

Mot d'interprétation: prélève dans le flot d'entrée le mot suivant et cherche s'il existe dans les vocabulaires de contexte. La recherche peut ignorer les différences entre caractères majuscules et minuscules selon l'état de CAPS (voir ce mot).

Si le mot existe dans le ou les vocabulaires de recherche, son cfa est empilé, ainsi qu'un drapeau à 1 ou -1 selon que le mot est trouvé immédiat ou non.

Si le mot n'est pas trouvé, DEFINED laisse le pointeur de dictionnaire HERE et un drapeau booléen faux (zéro) au sommet de la pile de données.

?STACK

: ?STACK ( -- )

( versions ATMOS: )

SP@ S0 @ SWAP U< ABORT" pile vide" SP@ 24 U< ABORT" pile pleine" ;

( version TELESTRAT: )

SP@ S0 @ SWAP U< ABORT" pile vide" SP@ 8C U< ABORT" pile pleine" ;

Délivre un message en cas de dépassement de capacité de la pile ou de pile vide. Les messages "pile vide" et "pile pleine" sont affichés dans l'une ou l'autre situation. Ce mot est généralement utilisé dans la définition d'un mot manipulant des éléments contenus dans la pile de données.

DONE?

: DONE? ( n -- b )

STATE @ <> END? @ OR END? OFF ;

Mot de l'interpréteur externe. Délivre un drapeau booléen vrai si tout le flot d'entrée a été interprété ou si n n'est pas égal à STATE (voir ce mot).

INTERPRET

: INTERPRET ( -- )

BEGIN ?STACK DEFINED IF EXECUTE ELSE NUMBER DOUBLE? NOT IF DROP THEN THEN FALSE DONE? UNTIL ;

Interprète le contenu du flot d'entrée. Ceci est fort utile dans le cas où une commande FORTH est attendue dans un programme interactif.

Exemple:

: NOUVEAU ( -- ) BEGIN QUERY INTERPRET ." Oui" 0 UNTIL ;

Le mot NOUVEAU accepte toutes les commandes FORTH, y compris les actions de compilation, à la différence que "Oui" s'affiche à la place du prompt habituel après chaque interprétation.

ALLOT

: ALLOT ( n -- )

DP +! ;

Réserve un emplacement de n octets à partir de la position courante du pointeur de dictionnaire (variable DP) et incrémente ce pointeur. Ce mot sert notamment pour la définition de tableaux de valeurs ou de zones de stockage de paramètres ou données diverses.

Exemple:

VARIABLE TABLEAU 254 ALLOT

Crée une variable TABLEAU, suivie de 254 octets libres. Le mot TABLEAU dispose donc de 256 octets (254+2 de définition de variable). L'accès à un élément de ce tableau est réalisé comme suit: n TABLEAU + C@ ce qui délivre la nième valeur contenue dans TABLEAU.

,

: , ( n -- )

HERE ! 2 ALLOT ;

Met à l'adresse pointée par l'exécution de HERE la valeur 16 bits n en mémoire, par exemple pour assembler directement une définition en code machine sans faire appel au vocabulaire assembleur. Voir aussi C,.

C,

: C, ( c -- )

HERE C! 1 ALLOT ;

Compile dans le dictionnaire une valeur sur un octet à l'adresse pointée par DP et incrémente le contenu de cette variable d'une unité. Voir aussi ,.

Exemple:

HERE . affiche l'adresse adr.

35 C, HERE . affiche l'adresse adr+1.

HERE 1- C@ . affiche le contenu de adr, soit 35.

?COMP

: ?COMP ( -- )

STATE @ 0= ABORT" en definition seulement" ;

Génère le message d'erreur "en définition seulement" si FORTH est en interprétation.

COMPILE

: COMPILE <mot> ( -- )

?COMP R> DUP 2+ >R @ , ;

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, UNTIL, .", etc...

IMMEDIATE

: IMMEDIATE ( -- )

40 LAST @ CTOGGLE ;

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?).

LITERAL

: LITERAL ( n -- )

DUP 100 U< IF COMPILE CLIT C, ELSE COMPILE LIT , THEN ; IMMEDIATE

Mot d'exécution immédiate. Compile le mot LIT suivi du nombre n situé au sommet de la pile de données en tant que litéral (compile CLIT si n est une constante numérique 8 bits).

Exemple:

HERE

: TEST LITERAL [ 0 ] ID. ;

DROP

L'exécution de TEST affiche TEST. L'adresse délivrée par HERE est compilée en tant que valeur litérale dans la définition de TEST. La séquence [ 0 ] immédiate est destinée simplement à laisser la pile au même niveau pour que la définition "deux-points" soit validée.

DLITERAL

: DLITERAL ( d -- )

SWAP [COMPILE] LITERAL [COMPILE] LITERAL ; IMMEDIATE

Mot d'exécution immédiate compilant comme litéral double le nombre 32 bits présent sur la pile. Voir aussi LITERAL.

Exemple:

: PI* [ 22 7 ] DLITERAL /* ;

100 PI* . affiche 314.

ASCII

: ASCII <caractère> ( -- c )

BL WORD 1+ C@ STATE @ IF [COMPILE] LITERAL THEN ; IMMEDIATE

Compile le code ASCII du prochain caractère du flot d'entrée en tant que valeur litérale entière.

Pour compiler un code de contrôle, on utilisera le mot CONTROL.

Exemple:

: TEST ASCII A EMIT ;

TEST affiche A.

CONTROL

: CONTROL <lettre majuscule> ( -- c )

BL WORD 1+ C@ 40 - STATE @ IF [COMPILE] LITERAL THEN ; IMMEDIATE

Empile ou compile le code ASCII de contrôle du mot qui le suit. Ce mot doit se réduire à une lettre majuscule, les autres caractères éventuels n'étant pas pris en compte.

Exemple:

CONTROL C . affiche 3 (code de <CTRL> + <C>).

'

: ' <mot> ( -- cfa )

DEFINED 0= ?MISSING ;

Prononcer "tick". Utilisé en interprétation, ce mot dépose sur la pile l'adresse du champ de code (cfa) du mot qui suit dans le flot d'entrée. En compilation, ce mot est simplement compilé. La version immédiate du mot ' utilisable au sein d'une définition "deux-points" est ['].

Exemple:

' DROP dépose sur la pile de données le cfa de DROP.

[']

: ['] <mot> ( -- cfa )

?COMP ' [COMPILE] LITERAL ; IMMEDIATE

Mot d'exécution immédiate. Lors de son exécution, il compile l'adresse du cfa (Code Field Adress, adresse du champ d'exécution) du mot qui suit dans le flot d'entrée en tant que litéral. Ce mot n'est utilisé qu'en compilation. Il permet notamment de préparer l'affectation d'un vecteur à un mot d'exécution vectorisée.

Exemple:

ONLY FORTH DEFINITIONS ALSO PRINTER

: OUT-SELECT ( -- ) CR ." Sélectionnez votre sortie:" CR CR ." 1. sur écran" CR ." 2. sur imprimante" CR KEY ASCII 1 = IF ['] (EMIT) IS EMIT ELSE ASCII 2 = IF ['] (PRINT) IS EMIT THEN THEN ;

[COMPILE]

: [COMPILE] <mot> ( -- )

?COMP ' , ; IMMEDIATE

Force la compilation d'un mot immédiat dans une définition en cours de compilation. Le mot a compiler est situé après ce mot. 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...

Exemple:

: MOTIMM ." Je suis immédiat" CR ; IMMEDIATE

: UTILISE CR [COMPILE] MOTIMM ;

UTILISE affiche "Je suis immédiat".

('')

: (") ( -- adr cnt )

R> COUNT 2DUP + >R ;

Partie compilée par le mot d'exécution immédiate ". A ne pas utiliser directement. Ce mot renvoie l'adresse et la longueur d'une chaîne de caractères compilée dans une définition.

(.'')

: (.") ( -- )

R> COUNT 2DUP + >R TYPE ;

Partie exécution compilée par le mot d'exécution immédiate ." et à ne pas utiliser directement. Lors de son exécution, ce mot affiche la chaîne de caractères compilée par le mot .".

,''

: ," ( -- )

ASCII " PARSE TUCK HERE PLACE 1+ ALLOT ;

Compile la chaîne de caractères qui suit dans le dictionnaire. La chaîne de caractères est délimitée par le signe ". Ce mot est utilisé dans la définition du mot ". Voir aussi (").

.''

: ." <chaîne de caractères>" ( -- )

?COMP COMPILE (.") ," ; IMMEDIATE

Mot d'exécution immédiate compilant le mot (.") et une chaîne de caractères située entre le mot ." et le signe ". Ce mot ne peut être utilisé en exécution. Un espace minimal sépare le mot ." et le début de la chaîne de caractères à compiler. Aucun espace minimal n'est requis en fin de chaîne.

Exemple:

: SALUT ." BONJOUR" ;

Compile la chaîne de caractères "BONJOUR" dans la définition du mot SALUT. Lors de l'exécution de SALUT, la chaîne de caractères précédemment compilée sera affichée.

''

: " <chaîne de caractères>" ( -- adr cnt )

COMPILE (") ," ; IMMEDIATE

Mot d'exécution immédiate permettant la compilation d'une chaîne de caractères terminée par le signe ". Ce mot compile le cfa du mot (") avant le contenu de la chaîne de caractères. A l'exécution du mot ("), l'adresse et la longueur de la chaîne de caractères compilée lors de l'exécution du mot " sont déposés sur la pile. Ces paramètres peuvent ensuite être exploités pour afficher ou traiter la chaîne de caractères.

Exemple:

: TEST ( -- adr cnt ) " Ceci est compilé" ;

TEST TYPE affiche "Ceci est compilé".

ABORT''

: ABORT" <chaîne de caractères>" ( b -- )

?COMP COMPILE (ABORT") ," ; IMMEDIATE

Mot d'exécution immédiate compilant le mot (ABORT") et la chaîne de caractères située après ce mot et terminée par le signe ". Lors de l'exécution, le mot (ABORT") teste le contenu du sommet de la pile; si cette valeur correspond à un flag booléen faux, il ne se passe rien; si cette valeur correspond à un flag booléen vrai, la chaîne de caractères est affichée en tant que message d'erreur et le mot ABORT est exécuté.

Ce mot simplifie la gestion des erreurs. En effet, dans les précédents STANDARDS, ces messages provenaient soit du disque, soit se résumaient à des codes trop laconiques. De plus, les types d'erreurs étaient limités. A présent, chacun peut gérer à n'importe quel niveau ses propres codes d'erreur.

Exemple:

: MALADE? ( température-corporelle -- ) DUP 34 < OVER 41 > OR ABORT" Je ne suis pas vétérinaire... " DUP 37 = IF ." Pas de fièvre " ELSE DUP 38 = SWAP 38 > OR IF ." Voyez le médecin traitant " THEN THEN ;

Ce qui donne à l'exécution:

45 MALADE? affiche "Je ne suis pas vétérinaire...".

37 MALADE? affiche "Pas de fièvre".

38 MALADE? affiche "Voyez le médecin traitant".

Dans le premier cas, celui où le malade aurait plus de 41 degrés (si vous le faites bien cuire), le système affiche la chaîne qui suit ABORT" et interrompt la poursuite de l'exécution du mot MALADE?.

?EXEC

: ?EXEC ( -- )

STATE @ ABORT" hors definition seulement" ;

Génère le message d'erreur "hors définition seulement" si FORTH est en compilation.

.(

: .( <chaîne de caractères>) ( -- )

?EXEC ASCII ) PARSE TYPE ; IMMEDIATE

Mot d'exécution immédiate affichant la chaîne de caractères comprise entre ce mot et la première parenthèse fermée située dans le flot d'entrée. Un espace minimal de séparation est nécessaire entre ce mot et le début de la chaîne de caractères. S'il est utilisé dans une définition en cours de compilation, le contenu de la chaîne sera affiché et non compilé. Pour compiler une chaîne de caractères, on fera appel au mot ." ou ".

Exemple:

.( Ceci est un test) affiche "Ceci est un test".

?PAIRS

: ?PAIRS ( n2 n1 -- )

<> ABORT" controles mal appaires" ;

Génère le message d'erreur "contrôles mal appairés" si n2 et n1, positionnés par les mots de construction des structures de contrôle, sont différents.

>MARK

: >MARK ( -- adr )

HERE 0 , ;

Elément d'une structure de compilation pour opérer une rupture de séquence avec saut en avant. Empile une adresse où >RESOLVE placera l'argument d'un branchement en avant. Le couple >MARK ... >RESOLVE placé dans deux mots immédiats de contrôle de compilation est indissociable.

Exemple:

Soit à ajouter aux structures déjà riches du FORTH une structure de type:

<condition> SAUF <mot1> ... <motn> PUIS ...

qui réalisera une boucle <mot1> ... <motn> si la <condition> est fausse. Sans faire appel à NOT IF ... THEN il est possible d'écrire:

: SAUF COMPILE NOT COMPILE ?BRANCH >MARK ; IMMEDIATE

: PUIS >RESOLVE ; IMMEDIATE

qui pourront être utilisés sous une forme du type:

: PROMENADE ( -- ) IL-PLEUT SAUF SORTIR PUIS SIESTE ;

>RESOLVE

: >RESOLVE ( adr -- )

HERE SWAP ! ;

Elément d'une structure de compilation pour opérer une rupture de séquence avec un saut en avant. Utilise l'adresse laissée par >MARK pour compiler l'argument du déplacement en avant.

<MARK

: <MARK ( -- adr )

HERE ;

Elément d'une structure de compilation pour opérer une rupture de séquence avec saut en arrière. Empile une adresse de retour utilisée par <RESOLVE pour définir un branchement en arrière. Le couple <MARK ... <RESOLVE placé dans deux mots immédiats de contrôle de compilation est indissociable.

Exemple:

Soit à ajouter aux structures déjà riches du FORTH une structure de type:

... FAIRE <mot1> ... <motn> <condition> TANT-QUE ...

qui réalisera une boucle <mot1> ... <motn> tant que la <condition> est vraie. Sans faire appel à BEGIN ... NOT UNTIL, il est possible d'écrire:

: FAIRE <MARK ; IMMEDIATE

: TANT-QUE COMPILE NOT COMPILE ?BRANCH <RESOLVE ; IMMEDIATE

qui pourront être utilisés sous une forme du type:

: PROMENADE ( -- ) FAIRE UN-TOUR IL-FAIT-BEAU TANT-QUE ;

<RESOLVE

: <RESOLVE ( adr -- )

, ;

Elément d'une structure de compilation pour opérer une rupture de séquence avec saut en arrière. Utilise l'adresse laissée par <MARK pour compiler l'argument du déplacement en arrière.

BEGIN

: BEGIN ( -- )

?COMP <MARK 1 ; IMMEDIATE

Mot d'exécution immédiate marquant le début d'une structure de contrôle et correspondant à la compilation d'une boucle infinie ou indéfinie. Ce mot laisse sur la pile une adresse de retour utilisée par le mot de fin de boucle, ainsi qu'un flag booléen de contrôle de structure. Trois structures de boucle sont possibles à partir de BEGIN:

Exemple:

: DACTYLO ( -- ) BEGIN KEY DUP EMIT CONTROL C UNTIL ;

Lors de l'exécution de DACTYLO, tous les caractères frappés au clavier sont envoyés au terminal jusqu'à la frappe de <CTRL> + <C>.

THEN

: THEN ( -- )

?COMP 2 ?PAIRS >RESOLVE ; IMMEDIATE

Mot d'exécution immédiate utilisé en compilation seulement. Marque la fin d'une structure de contrôle de type IF ... THEN ou IF ... ELSE ... THEN.

Exemple:

10 CONSTANT LIMITE

: TROP? ( n -- ) LIMITE > IF CR ." Il y en a trop" ELSE CR ." Mettez-en encore" THEN ;

DO

: DO ( n2 n1 -- )

COMPILE (DO) >MARK <MARK 3 ; IMMEDIATE

Mot d'exécution immédiate et utilisé en compilation seulement, pour marquer le début d'une structure de contrôle définie en tant que boucle du type:

Le corps de boucle est exécuté itérativement pour qu'un indice de boucle présent sur la pile de retour, disponible avec I (voir ce mot), parcoure l'intervalle de n1 à n2, n2 non compris, par pas de 1 dans la forme numéro 1, ou par pas de n3 dans la forme numéro 2.

L'exécution du mot DO compile le mot (DO) qui gère sur la pile de retour l'adresse de fin de boucle et les indices de boucle pour LOOP ou +LOOP (voir <RESOLVE). Quelque soient n1 et n2, la boucle est exécutée au moins une fois. Si n1 est égal à n2, la boucle est exécuté 65536 fois.

La gestion de la pile de retour et des structures de contrôle couplées autorise l'imbrication de boucles sans chevauchement. Voir aussi ?DO, LEAVE et ?LEAVE.

Exemple:

: CARRE 5 0 DO CR 5 0 DO ASCII * EMIT LOOP LOOP ;

L'exécution de CARRE affiche 25 étoiles disposées en carré.

?DO

: ?DO ( n2 n1 -- )

COMPILE (?DO) >MARK <MARK 3 ; IMMEDIATE

Mot d'exécution immédiate marquant le début d'une structure de contrôle itérative de type ?DO ... LOOP ou ?DO ... +LOOP. Son exécution compile le mot (?DO). A la différence de DO, le contenu de la boucle n'est pas exécuté dans le cas où les index de boucle sont identiques (DO ... LOOP exécutant la boucle 65536 fois).

Les boucles de type ?DO ... LOOP et ?DO ... +LOOP peuvent s'imbriquer.

Malheureusement, le nouveau STANDARD ne prévoit aucun test d'erreur dans le cas de structures de contrôle dépareillées, comme ?DO ... IF ... LOOP .. THEN ... pour exemple.

Exemples:

: BOUCLE ?DO ." *" LOOP ;

4 0 BOUCLE affiche "****".

4 4 BOUCLE n'affiche rien.

: BOUCLES ( -- ) 20 10 ?DO I 20 10 ?DO DUP I AT ASCII * EMIT LOOP DROP LOOP ;

LOOP

: LOOP ( -- )

3 ?PAIRS COMPILE (LOOP) <RESOLVE >RESOLVE ; IMMEDIATE

Mot d'exécution immédiate. Termine une structure de contrôle répétitive de type DO ... LOOP ou ?DO ... LOOP. L'exécution de la boucle peut être interrompue par LEAVE ou ?LEAVE.

L'index de la boucle peut être prélevé lors de l'exécution de la boucle à l'aide du mot I. Plusieurs boucles peuvent s'imbriquer.

Exemples:

: BOUCLE ( -- ) 10000 0 DO LOOP ;

: TEST ( -- ) 15 5 DO I DUP AT ASCII * EMIT LOOP ;

+LOOP

: +LOOP ( n -- )

3 ?PAIRS COMPILE (+LOOP) <RESOLVE >RESOLVE ; IMMEDIATE

Mot d'exécution immédiate, utilisé en compilation seulement. Il termine une structure de type DO ... +LOOP ou ?DO ... +LOOP. Le mot +LOOP compile le mot (+LOOP) et la valeur de branchement vers laquelle l'exécution doit se poursuivre pour réaliser l'itération. L'index de boucle est incrémenté avec la valeur déposée sur la pile de données. La valeur n peut être négative. Voir aussi LOOP.

Exemple:

: BOUCLE 100 0 DO I . 3 +LOOP ;

L'exécution de BOUCLE affiche tous les nombres compris entre 0 et 100, ceci de trois en trois.

UNTIL

: UNTIL ( b -- )

1 ?PAIRS COMPILE ?BRANCH <RESOLVE ; IMMEDIATE

Compile un branchement arrière dans une structure de contrôle de type BEGIN ... UNTIL. Le contenu de la structure de contrôle est réexécuté si le flag booléen situé sur la pile avant UNTIL est faux (b=0). Voir aussi WHILE et REPEAT.

Exemple:

: ARRET BEGIN ( ...définition... ) KEY 3 = ( action sur <CTRL> + <C> ) UNTIL ;

AGAIN

: AGAIN ( -- )

1 ?PAIRS COMPILE BRANCH <RESOLVE ; IMMEDIATE

Mot d'exécution immédiate compilant un branchement inconditionnel arrière dans une structure de contrôle de type BEGIN ... AGAIN. Il n'est pas possible d'interrompre une boucle de ce type, à moins de provoquer une erreur.

Exemple:

: BOUCLE BEGIN AGAIN ;

Une fois lancé, le mot BOUCLE ne peut être interrompu. Il ne reste plus qu'à appuyer sur le bouton de RESET pour relancer FORTH. Voici un moyen d'éviter ce désagrément:

: BOUCLE BEGIN ?KEY IF EXIT THEN AGAIN ;

IF

: IF ( b -- )

COMPILE ?BRANCH >MARK 2 ; IMMEDIATE

Mot d'exécution immédiate. Marque le début d'une structure de contrôle de type IF ... THEN ou IF ... ELSE ... THEN. Lors de l'exécution, la partie de définition située entre IF et THEN ou entre IF et ELSE est exécutée si le flag booléen situé au sommet de la pile de données est vrai (b<>0). Dans le cas contraire, si le flag booléen est faux (b=0), c'est la partie de définition située entre ELSE et THEN qui sera exécutée. S'il n'y a pas de ELSE, l'exécution se poursuit après THEN.

Exemple:

: BEAU? ( b -- ) IF ." Beau temps " ELSE ." Temps couvert " THEN ;

1 BEAU? affiche "Beau temps".

0 BEAU? affiche "Temps couvert".

ELSE

: ELSE ( -- )

2 ?PAIRS COMPILE BRANCH >MARK SWAP >RESOLVE 2 ; IMMEDIATE

Mot d'exécution immédiate et utilisé en compilation seulement. Marque une alternative dans une structure de contrôle du type:

<condition> IF ... ELSE ... THEN ....

A l'exécution, si la condition située sur la pile avant IF est fausse, il y a rupture de séquence avec saut à la suite de ELSE, puis reprise en séquence après THEN.

A la compilation, IF a déposé sur la pile une adresse de saut conditionnel qui est résolue (voir >RESOLVE) par ELSE. En cas de structures IF ... ELSE ... THEN imbriquées, ELSE se rapporte à la dernière adresse non résolue, ce qui interdit en principe les imbrications chevauchantes pour n'autoriser que des structures du type:

IF ... ELSE ... IF ... ELSE ... THEN ... THEN ... ou

IF ... IF ... ELSE ... THEN ... ELSE ... THEN ....

Exemple:

: TEST CR ." Appuyez sur une touche " KEY DUP ASCII A ASCII z BETWEEN IF CR 3 SPACES ." c'est une lettre " ELSE DUP ASCII 0 ASCII 9 BETWEEN IF CR 3 SPACES ." c'est un chiffre " ELSE CR 3 SPACES ." c'est un caractère spécial " THEN THEN DROP ;

A titre d'exercice, réécrivez TEST pour qu'il sépare les majuscules des minuscules ainsi que les caractères de contrôle.

WHILE

: WHILE ( b -- )

1 ?PAIRS [COMPILE] IF 1- ; IMMEDIATE

Mot d'exécution immédiate. Utilisé dans la définition d'une structure de contrôle de type BEGIN ... WHILE ... REPEAT. Exécute la partie de définition située entre WHILE et REPEAT si le flag booléen qui précède son exécution est vrai, puis réexécute la partie de définition depuis BEGIN. Dans le cas contraire, l'exécution se poursuit après le mot REPEAT. Voir aussi UNTIL.

REPEAT

: REPEAT ( -- )

1 ?PAIRS SWAP COMPILE BRANCH <RESOLVE >RESOLVE ; IMMEDIATE

Mot d'exécution immédiate. Marque la fin d'une structure de contrôle de type BEGIN ... WHILE ... REPEAT.

[

: [ ( -- )

STATE OFF ; IMMEDIATE

Fait passer en mode interprétation. Le texte suivant, provenant du flot d'entrée, est interprété. Voir aussi ].

Exemple:

: TEST ( -- ) [ HERE CR . .( = Pointeur dictionnaire ) ] DUP 2* + ;

]

: ] ( -- )

STATE ON BEGIN ?STACK DEFINED DUP IF 0> IF EXECUTE ELSE , THEN ELSE DROP NUMBER DOUBLE? IF [COMPILE] DLITERAL ELSE DROP [COMPILE] LITERAL THEN THEN TRUE DONE? UNTIL ;

Fait passer en mode compilation. Le texte suivant, provenant du flot d'entrée, est compilé. Voir aussi [.

HEADER

: HEADER <mot> ( -- )

HERE 0 , HERE LAST ! WARNING @ IF DEFINED IF HERE COUNT TYPE ." (redefini) " CR THEN DROP HERE ELSE BL WORD THEN CURRENT @ HASH DUP @ HERE 2- ROT ! SWAP ! HERE DUP C@ WIDTH @ MIN 1+ ALLOT 80 SWAP CSET 80 HERE 1- CSET DP C@ FF = IF 1 ALLOT LAST @ 2- DUP 1+ OVER HERE SWAP - CMOVE> 1 LAST +! 1 LAST @ CURRENT @ HASH +! THEN ;

Crée une nouvelle entrée dans le dictionnaire; un message "(redéfini)" signale si une entrée du même nom existait déjà; la longueur du nom est limitée à WIDTH caractères (normalement 31); est utilisé par CREATE.

!CSP

: !CSP ( -- )

SP@ CSP ! ;

Mot système assurant la sauvegarde du pointeur de pile dans la variable CSP.

?CSP

: ?CSP ( -- )

SP@ CSP @ <> ABORT " definition incomplete" ;

La valeur du pointeur de pile est comparée à celle contenue dans la variable CSP et un message d'erreur est généré si ces valeurs ne sont pas égales. Ce mot est utilisé par ; pour tester une éventuelle erreur de compilation. Cette situation peut se produire notamment dans le cas de l'exécution d'un mot immédiat s'exécutant dans une définition en cours de compilation et modifiant le contenu de la pile de données.

TRAVERSE

: TRAVERSE ( adr direction -- adr' )

SWAP BEGIN OVER + 7F OVER C@ < UNTIL NIP ;

Traverse le nfa d'une définition dans la direction spécifiée. Aboutit lorsqu'il rencontre un octet dont le bit de poids fort est à un.

N>LINK

: N>LINK ( nfa -- lfa )

2- ;

Convertit l'adresse du champ du nom en adresse du champ de lien. Voir aussi L>NAME, BODY>, NAME>, LINK>, >BODY, >NAME et >LINK.

L>NAME

: L>NAME ( lfa -- nfa )

2+ ;

Délivre l'adresse du champ du nom à partir de l'adresse du champ de lien. Voir aussi NAME>.

BODY>

: BODY> ( pfa -- cfa )

2- ;

Convertit l'adresse du champ paramétrique d'un mot en celle de son champ de code.

NAME>

: NAME> ( nfa -- cfa )

1 TRAVERSE 1+ ;

Convertit l'adresse du champ du nom en adresse d'exécution. Voir aussi N>LINK, L>NAME, BODY>, LINK>, >BODY, >NAME et >LINK.

LINK>

: LINK> ( lfa -- cfa )

2+ 1 TRAVERSE 1+ ;

Transforme l'adresse du champ de lien en adresse de compilation. Voir aussi NAME>.

>BODY

: >BODY ( cfa -- pfa )

2+ ;

Convertit l'adresse du code exécutif d'un mot (cfa) en celle de son champ paramétrique (pfa).

Exemple:

Pour changer la valeur d'une constante:

5 CONSTANT CINQ

6 ' CINQ >BODY !

CINQ . affiche désormais 6 (étonnant non?...)

>NAME

: >NAME ( cfa -- nfa )

1- -1 TRAVERSE ;

Transforme l'adresse du champ de code (cfa) en adresse de champ du nom (nfa).

>LINK

: >LINK ( cfa -- lfa )

1- -1 TRAVERSE 2- ;

Convertit l'adresse du code exécutif (cfa) d'un mot en celle de son champ de lien (lfa).

Exemple:

: MOT1 ;

: MOT2 ;

' MOT2 >LINK @ ID. affiche MOT1.

HIDE

: HIDE ( -- )

LAST @ DUP N>LINK @ SWAP CURRENT @ HASH ! ;

Détruit la dernière définition située en tête de dictionnaire. En fait, se contente d'en supprimer le chaînage dans le vocabulaire courant sans récupérer sa place dans le dictionnaire.

REVEAL

: REVEAL ( -- )

LAST @ DUP N>LINK SWAP CURRENT @ HASH ! ;

Remet la dernière définition en tête du vocabulaire courant.

CREATE

: CREATE <mot> ( -- )

HEADER DOVAR , ;

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 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 et [;

<mot-codifiant>: du type DOES>, ;CODE, et ;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 CTRL1, que dans les possibilités de nouvelles structures. Voir aussi ,".

Exemple:

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 la 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 ,

NOMBRE-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.

CONSTANT

: CONSTANT <mot> ( n -- | -- n )

HEADER DOCON , , ;

Mot de compilation 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.

Exemples:

5 CONSTANT CINQ

CINQ . affiche 5.

365 CONSTANT JOURS/AN

JOURS/AN . affiche 365.

VARIABLE

: VARIABLE <mot> ( -- | -- adr )

HEADER DOVAR , 0 , ;

Mot de définition. 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.

USER

: USER <mot> ( n -- | -- adr )

HEADER DOUSE , , ;

Crée une "variable-utilisateur"; les variables-utilisateur s'utilisent de la même manière que les autres variables.

ASSEMBLER

DEFER ASSEMBLER ( -- )

' FORTH IS ASSEMBLER

Sélectionne le vocabulaire ASSEMBLER en tant que vocabulaire de contexte (sous KERNEL, il faut auparavant compiler ASM.FTH pour revectoriser ASSEMBLER). Sur votre système, ce mot sélectionne le vocabulaire utilisable avec le microprocesseur 6502.

(;CODE)

: (;CODE) ( -- )

R> LAST @ NAME> ! ;

Mot compilé par le mot d'exécution immédiate ;CODE. Son exécution met l'adresse qui suit dans le cfa du mot à définir.

;CODE

: ;CODE ( -- )

?CSP COMPILE (;CODE) [COMPILE] [ REVEAL ASSEMBLER ; IMMEDIATE

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 ;, ;CODE vérifie la profondeur de pile, valide la définition en cours, compile une fin de définition rompant la séquence DOCOL, à savoir le mot (;CODE) qui définira les cfas 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,

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.

(;USES)

: (;USES) ( -- )

R> @ LAST @ NAME> ! ;

Mot compilé par le mot d'exécution immédiate ;USES. Son exécution met le contenu de l'adresse qui suit dans le cfa du mot à définir.

;USES

: ;USES ( -- )

?CSP COMPILE (;USES) [COMPILE] [ REVEAL ; IMMEDIATE

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). 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.

DOES>

: DOES> ( -- | -- pfa )

COMPILE (;CODE) 4C C, DODOES , ; IMMEDIATE

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épot sur la pile de données de l'adresse de son champ paramétrique (pfa).

Exemples:

(montrant mieux l'emploi de CREATE et de DOES>)

On pourrait définir CONSTANT de la manière suivante:

: CSTE ( n -- | -- adr ) CREATE , DOES> @ ;

Reprenons le premier exemple d'emploi donné pour CONSTANT:

5 CSTE CINQ

CINQ . affiche 5.

Au moment de l'exécution de CSTE, 5 est sur la pile; de la définition de CSTE, seule la partie "construction", comprise entre CREATE et DOES> va être exécutée: CREATE va créer un nouvel en-tête de nom CINQ dans le dictionnaire, puis "virgule" va prendre la valeur 5 sur la pile et la compiler à la suite de l'en-tête, enfin DOES> va terminer le travail (en faisant pointer le cfa de CINQ sur la première instruction suivant (;CODE) dans la définition de DOES>, et le premier mot du pfa de CINQ, réservé par CREATE, sur le premier mot suivant DOES> dans la définition de CSTE); au moment de l'exécution de CINQ, ce sont les instructions machine qui suivent (;CODE) dans la définition de DOES> qui vont être exécutées: elles vont laisser sur la pile l'adresse de valeur 5 (suivant le mot réservé par CREATE après l'en-tête de CINQ), et provoquer l'exécution de la partie "action" de CSTE (qui suit DOES> dans la définition de CSTE): @ va remplacer l'adresse sur la pile par son contenu, c'est-à-dire la valeur 5.

Définissons une famille de tableaux (à une seule dimension) de variables:

: ARRAY ( dim -- | n -- adr ) CREATE 2* HERE OVER ERASE ALLOT DOES> SWAP 2* + ;

ARRAY crée une nouvelle entrée, d'en-tête TABLE par exemple, dans le dictionnaire, et réserve dim mots initialisés à 0; quand TABLE est exécuté, l'indice n au sommet de la pile est transformé en l'adresse du nième élément du tableau:

4 ARRAY TABLE

0 TABLE ? 2 TABLE ? affiche 0 0.

13 3 TABLE ! 10 0 TABLE !

0 TABLE ? 3 TABLE ? affiche 10 13.

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éfinition 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".

AVOC

VARIABLE AVOC ( -- adr )

Variable destinée à recevoir l'ancien vocabulaire de contexte. Ce mot est utilisé par CODE de manière à permettre la restitution de l'ancien vocabulaire lors de l'exécution de ;C marquant la fin d'une séquence d'assemblage.

CODE

: CODE <mot> ( -- )

CREATE HIDE HERE DUP 2- ! CONTEXT @ AVOC ! ASSEMBLER ;

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.

Exemples:

Pratiquement toutes les définitions des primitives du présent manuel...

CRASH

: CRASH ( -- )

TRUE ABORT" vecteur non initialise" ;

Mot utilisé par défaut par le mot d'exécution vectorisée auquel un vecteur n'a pas encore été affecté. Voir aussi DEFER.

Exemple:

DEFER DARK

DARK affiche "vecteur non initialisé".

' CLS IS DARK

DARK efface le contenu de l'affichage vidéo.

DEFER

: DEFER <mot> ( -- )

HEADER DODEF , ['] CRASH , ;

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é 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 génère un message d'erreur (voir CRASH).

Le concept de mots d'exécution vectorisée introduit dans le FORTH 83-STANDARD (il existe aussi dans la version FIG-FORTH TELE-FORTH pour TELESTRAT) est d'une importance théorique considérable. Les mots "différés" facilitent l'adaptation et la portabilité du système à son environnement, notamment dans la gestion des entrées-sorties. Pour exemple, voir le mot EMIT.

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.

Exemples:

Un exemple caractéristique est celui de EMIT qui permet soit d'afficher des caractères sur le moniteur et l'imprimante si la variable PR du vocabulaire PRINTER est vraie sinon de n'afficher que sur le moniteur (avec (EMIT)), soit d'imprimer des caractères sur l'imprimante (avec (PRINT)), soit d'afficher et d'imprimer des caractères respectivement sur le moniteur et sur l'imprimante (avec (PEMIT)).

L'exemple qui suit montre un fonctionnement équivalent, bien que moins efficace et plus lourd d'emploi, en utilisant une variable:

Avec DEFER:

DEFER VECTEUR

' 1+ IS VECTEUR

3 VECTEUR . affiche 4.

Sans DEFER:

' CRASH BODY> VARIABLE WECTEUR

' 1+ BODY> WECTEUR !

3 WECTEUR @ EXECUTE . affiche 4.

Soit un mot convivial AIDE destiné à porter secours à un utilisateur 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-tâche 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> ( -- )

!CSP CURRENT @ CONTEXT ! HEADER DOCOL , HIDE ] ;

Mot de création le plus utilisé en FORTH. Il définit un mot <mot> dit mot "deux-points" sous la forme:

: NOM nomex1 nomex2 ... nomexn ;

L'exécution ultérieure de NOM réalise l'enchaînement 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 DOCOL à 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 (voir ces mots).

Lors d'une définition "deux-points", le vocabulaire pointé par le contenu de CURRENT recevant les définitions 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 FORTH 83-STANDARD.

Exemples:

Pratiquement tous ceux du présent manuel...

;

: ; ( -- )

?CSP COMPILE UNNEST REVEAL [COMPILE] [ ; IMMEDIATE

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 la compilation de la routine UNNEST dont le rôle est de suspendre le chaînage par DOCOL 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 au mode exécution.

#BUFFERS

8 CONSTANT #BUFFERS ( -- 8 )

Constante dont le contenu détermine le nombre de blocs utilisables simultanément dans le système. Normalement, sa valeur est initialisée à huit unités dans les versions FORTH 83-STANDARD pour ORIC.

FILE

VARIABLE FILE ( -- adr )

' FCB >BODY FILE !

Variable dont le contenu pointe sur le bloc de contrôle (FCB) du fichier courant.

>SIZE

4A CONSTANT >SIZE ( -- 74 )

Constante délivrant la valeur 74 lors de son exécution. Ce mot est utilisé par les routines de gestion de blocs.

>BUFFERS

: >BUFFERS ( -- adr )

FIRST >SIZE - ;

Délivre l'adresse de base des pointeurs de tampons de blocs. Est utilisé dans un système de gestion des tampons faisant appel à une zone de pointeurs séparés de la zone des tampons. Voir aussi BUFFER#.

>END

: >END ( -- adr )

FIRST 2- ;

Délivre l'adresse de fin de la zone des pointeurs de tampons de blocs.

BUFFER#

: BUFFER# ( n -- adr )

8 * >BUFFERS + ;

Délivre l'adresse du nième pointeur de tampon de bloc. La valeur n est comprise entre 1 et la constante #BUFFERS qui est de 8 unités dans les systèmes FORTH 83-STANDARD pour ORIC.

Le FORTH 83-STANDARD adopte un système dynamique de gestion des tampons de blocs destiné à accélérer les accès et les opérations sur les tampons. L'allocation des tampons passe par des pointeurs physiquement séparés de la zone des tampons. Chaque pointeur, à raison d'un par tampon disponible, occupe 4 cellules de 16 bits, contenant respectivement le numéro de bloc alloué, le fichier référencé, l'adresse du tampon pointé et le drapeau de mise à jour.

Quelque soit l'occupation et la répartition physique des tampons, le premier pointeur de tampon désigne toujours le bloc de plus récemment utilisé, tandis que le huitième pointe le plus ancien.

De plus, le système offre l'avantage de tampons de 1024 octets jointifs sans octets séparateurs. Bien entendu, toute la gestion des tampons et de leurs pointeurs est transparente pour l'utilisateur.

Exemple:

: .BLOCKS #BUFFERS 0 DO I 1+ BUFFER# ? LOOP ;

A l'exécution, le mot .BLOCKS affiche les numéros des blocs présents dans les tampons, le plus récemment utilisé figurant en premier.

OPEN ASM ouvre le fichier ASM (.FTH par défaut).

EMPTY-BUFFERS vide les tampons.

1 LIST 2 LIST 3 LIST 4 LIST 5 LIST 6 LIST 7 LIST 8 LIST charge et liste les écrans 1, 2, 3, 4, 5, 6, 7 et 8.

1 LIST liste à nouveau l'écran 1.

9 LIST charge et liste l'écran 9.

8 LIST liste à nouveau l'écran 8.

.BLOCKS affiche 8 9 1 7 6 5 4 3. L'écran 2 n'est plus présent.

LATEST?

: LATEST? ( n -- n /-- adr b )

OFFSET @ + 1 BUFFER# 2DUP @ = SWAP 2+ @ FILE @ = AND IF DROP 1 BUFFER# 4 + @ FALSE R> DROP THEN ;

Signale si le bloc n est la première entrée dans la zone du pointeur du tampon. Si c'est le cas, retourne l'adresse du tampon et un flag booléen faux. Dans le cas contraire, renvoie le numéro du bloc.

ABSENT?

ABSENT? ( n -- adr b )

LATEST? DUP >BUFFERS ! TRUE SWAP 1 BUFFER# #BUFFERS 0 DO 2DUP @ = OVER 2+ @ FILE @ = AND IF DUP >BUFFERS 8 CMOVE DUP >BUFFERS DUP 8 + ROT >BUFFERS - CMOVE> DROP 2DROP FALSE DUP 1 BUFFER# LEAVE THEN 8 + LOOP 4 + @ NIP SWAP ;

Recherche le bloc n au travers de la zone des pointeurs de tampons de blocs. Si le bloc est trouvé, déplace le pointeur du tampon en tête de zone et renvoie l'adresse du tampon ainsi qu'un flag booléen faux. Si le tampon n'est pas trouvé dans la zone, renvoie une adresse quelconque avec un flag booléen vrai.

UPDATE

: UPDATE ( -- )

1 BUFFER# 6 + ON ;

Marque le bloc écran le plus récemment selectionné comme étant modifié. Cette opération est réalisée automatiquement sous éditeur dès l'exécution d'une commande modifiant le contenu d'un bloc écran. Un bloc modifié est réécrit sur la mémoire si son tampon doit être utilisé pour un autre bloc ou lors des commandes SAVE-BUFFERS et FLUSH.

DISCARD

: DISCARD ( -- )

1 BUFFER# 6 + OFF ;

Force à zéro le drapeau de mise à jour du dernier tampon de bloc utilisé. Ce bloc est ainsi marqué non modifié et ne nécessitant donc pas de réécriture sur le disque. DISCARD exécute le contraire de UPDATE (voir ce mot).

WRITE-BLOCK

DEFER WRITE-BLOCK ( adr -- )

' FILE-WRITE IS WRITE-BLOCK

Mot d'exécution vectorisée. A l'initialisation, ce mot exécute le mot FILE-WRITE (voir ce mot).

READ-BLOCK

: READ-BLOCK ( adr -- )

' FILE-READ IS READ-BLOCK

Mot d'exécution vectorisée. A l'initialisation, ce mot exécute le mot FILE-READ (voir ce mot).

MISSING

: MISSING ( -- )

>END 2- @ IF >END 8 - WRITE-BLOCK >END 2- OFF THEN FILE @ >BUFFERS 2+ ! >END 4 - @ >BUFFERS 4 + ! >BUFFERS 6 + OFF >BUFFERS DUP 8 + #BUFFERS 8 * CMOVE> ;

Décale le tampon de bloc le plus récemment utilisé. Si ce tampon a été modifié, il est réécrit sur disque. A l'initialisation, le système FORTH 83-STANDARD pour ORIC a une capacité de 8 blocs dans le tampon de bloc. Si vous avez déjà appelé huit blocs précédemment, les sept derniers blocs les plus récemment appelés sont décalés par l'appel d'un nouveau bloc.

Exemple:

OPEN <fichier>

n1 LIST contenu du tampon: n1.

n2 LIST contenu du tampon: n2, n1.

n3 LIST contenu du tampon: n3, n2, n1.

n4 LIST contenu du tampon: n4, n3, n2, n1.

n5 LIST contenu du tampon: n5, n4, n3, n2, n1.

n6 LIST contenu du tampon: n6, n5, n4, n3, n2, n1.

n7 LIST contenu du tampon: n7, n6, n5, n4, n3, n2, n1.

n8 LIST contenu du tampon: n8, n7, n6, n5, n4, n3, n2, n1.

n9 LIST contenu du tampon: n9, n8, n7, n6, n5, n4, n3, n2.

et n1 est réécrit sur le disque si son contenu a été modifié. Le contenu du tampon est géré à la manière d'une liste circulaire FIFO (First In, First Out, c'est-à-dire premier entré, premier sorti).

BUFFER

: BUFFER ( n -- adr )

ABSENT? IF DROP MISSING 1 BUFFER# 4 + @ THEN ;

Alloue au bloc n un tampon de bloc dont l'adresse est laissée sur la pile. Le bloc n'est pas lu sur la mémoire de masse. Les opérations sur disque se résument éventuellement à la sauvegarde d'un bloc marqué "mis à jour" (updated) s'il faut faire de la place. Le mot BUFFER équivaut à BLOCK si le bloc est déjà présent dans les tampons.

BLOCK

: BLOCK ( n -- adr )

ABSENT? IF DROP MISSING 1 BUFFER# DUP READ-BLOCK 4 + @ THEN ;

Convertit un numéro de bloc en l'adresse physique du tampon de bloc où il est logé. Si le bloc n'est pas présent dans les tampons, il y est placé par une lecture de la mémoire de masse. Le mot BLOCK rend transparente la notion de mémoire virtuelle pour l'utilisateur.

EMPTY-BUFFERS

: EMPTY-BUFFERS ( -- )

>BUFFERS LIMIT OVER - ERASE FIRST 1 BUFFER# #BUFFERS 0 DO -1 OVER ! 4 + 2DUP ! SWAP B/BUF + SWAP 4 + LOOP 2DROP ;

Initialise tous les tampons de blocs. Ceux-ci sont vidés sans aucune sauvegarde sur disque et les pointeurs de tampons restitués à leur état initial. Les indicateurs de modification sont notamment remis à zéro. L'exécution d'un EMPTY-BUFFERS est incluse à chaque initialisation du système (voir HELLO) et à chaque FLUSH, si bien qu'on aura à utiliser ce mot que rarement, comme à la suite d'une grosse bêtise pour éviter toute écriture sur disque de blocs verminés.

SAVE-BUFFERS

: SAVE-BUFFERS ( -- )

1 BUFFER# #BUFFERS 0 DO DUP @ 1+ IF DUP 6 + @ IF DUP WRITE-BLOCK DUP 6 + OFF THEN 8 + THEN LOOP DROP ;

Le contenu de tous les blocs marqués UPDATEd (mis à jour), sont écrits sur les blocs de mémoire de masse correspondants. Les tampons restent assignés.

FLUSH

: FLUSH ( -- )

SAVE-BUFFERS EMPTY-BUFFERS ;

Provoque la sauvegarde sur disque du contenu de tous les blocs modifiés, ramène le contenu du bloc de référence à 0 et vide le tampon de bloc. Pour ne pas vider accidentellement le tampon de bloc, on utilisera de préférence SAVE-BUFFERS. Voir aussi EMPTY-BUFFERS.

RAM/ROM

CODE RAM/ROM ( -- )

0477 JSR, NEXT, ;C

Sur versions ATMOS uniquement. Bascule: fait passer de la RAM Overlay contenant le DOS à la ROM ATMOS et vice-versa. Voir BANK et BNK pour la version TELESTRAT.

RD#

CODE RD# ( piste secteur adr -- 8 )

( versions ATMOS: )

3 # LDA, SETUP JSR, XSAVE STX, 0477 JSR, N 4 + LDA, C001 STA, ( PISTE ) N 2+ LDA, C002 STA, ( SECTEUR ) N LDA, C003 STA, ( RWBUF ) N 1+ LDA, C004 STA, ( RWBUF + 1 ) 88 # LDX, CFCD JSR, 0= IF, 0 # LDA, >MARK JMP, SWAP THEN, FF # LDA, >RESOLVE XSAVE LDX, 0477 JSR, PHA, PUSH JMP, ;C

( version TELESTRAT: )

3 # LDA, SETUP JSR, XSAVE STX, N 4 + LDA, PISTE STA, N 2+ LDA, SECTEU STA, N LDA, RWBUF STA, N 1+ LDA, RWBUF 1+ STA, PHP, SEI, V2DRA LDA, 7 # AND, N 1- STA, V2DRA LDA, F8 # AND, V2DRA STA, PLP, 88 # LDX, RWTS JSR, PHP, SEI, V2DRA LDA, N 1- ORA, V2DRA STA, PLP, 0= IF, 0 # LDA >MARK JMP, SWAP THEN, FF # LDA, >RESOLVE XSAVE LDX, PHA, PUSH JMP, ;C

Lit un secteur sur le disque. Notez, dans les différentes versions, l'utilisation de SWAP pour croiser les références et celle du couple >MARK ... >RESOLVE pour réaliser une rupture de séquence avec saut en avant.

WR#

CODE WR# ( piste secteur adr -- b )

( versions ATMOS: )

3 # LDA, SETUP JSR, XSAVE STX, 0477 JSR, N 4 + LDA, C001 STA, ( PISTE ) N 2+ LDA, C002 STA, ( SECTEUR ) N LDA, C003 STA, ( RWBUF ) N 1+ LDA, C004 STA, ( RWBUF + 1 ) A8 # LDX, CFCD JSR, 0= IF, 0 # LDA, >MARK JMP, SWAP THEN, FF # LDA, >RESOLVE XSAVE LDX, 0477 JSR, PHA, PUSH JMP, ;C

( version TELESTRAT: )

3 # LDA, SETUP JSR, XSAVE STX, N 4 + LDA, PISTE STA, N 2+ LDA, SECTEU STA, N LDA, RWBUF STA, N 1+ LDA, RWBUF 1+ STA, PHP, SEI, V2DRA LDA, 7 # AND, N 1- STA, V2DRA LDA, F8 # AND, V2DRA STA, PLP, A8 # LDX, RWTS JSR, PHP, SEI, V2DRA LDA, N 1- ORA, V2DRA STA, PLP, 0= IF, 0 # LDA >MARK JMP, SWAP THEN, FF # LDA, >RESOLVE XSAVE LDX, PHA, PUSH JMP, ;C

Ecrit un secteur sur le disque. Notez, dans les différentes versions, l'utilisation de SWAP pour croiser les références et celle du couple >MARK ... >RESOLVE pour réaliser une rupture de séquence avec saut en avant.

DISK-ERR?

: DISK-ERR? ( b -- )

ABORT" erreur disque" ;

Génère le message "erreur disque" si le flag booléen présent au sommet de la pile de données est vrai (différent de zéro).

RESERVE

96 CONSTANT RESERVE ( -- 150 )

Constante délivrant le nombre de secteurs réservés en accès direct: 150.

S/T

10 CONSTANT S/T ( -- 16 )

Constante délivrant le nombre de secteurs par piste (Sectors per Track) en accès direct: 16.

RDBLOCK

: RDBLOCK ( adr -- )

DUP 4 + @ SWAP @ 4 * RESERVE + 4 0 DO 2DUP S/T /MOD SWAP 1+ ROT RD# DISK-ERR? 1+ SWAP 100 + SWAP LOOP 2DROP ;

Lit un bloc en accès direct sans SEDORIC (sur versions ATMOS) ou STRATSED (sur version TELESTRAT), permettant de créer des disques compatibles avec tous les FORTH depuis le TANSOFT jusqu'au TELESTRAT en passant par le DOS V1 ou les autres systèmes. Voir aussi RDM-FILE et WRBLOCK.

WRBLOCK

: WRBLOCK ( adr -- )

DUP 4 + @ SWAP @ 4 * RESERVE + 4 0 DO 2DUP S/T /MOD SWAP 1+ ROT WR# DISK-ERR? 1+ SWAP 100 + SWAP LOOP 2DROP ;

Ecrit un bloc en accès direct sans SEDORIC (sur versions ATMOS) ou STRATSED (sur version TELESTRAT), permettant de créer des disques compatibles avec tous les FORTH depuis le TANSOFT jusqu'au TELESTRAT en passant par le DOS V1 ou les autres systèmes. Voir aussi RDM-FILE et RDBLOCK.

.FILE

DEFER .FILE ( -- )

' (.FILE) IS .FILE

Mot d'exécution vectorisée affichant le nom du fichier courant. Voir aussi (.FILE).

?STOP

: ?STOP ( -- b )

FALSE ?KEY IF DROP KEY 13 = THEN ;

L'activation d'une touche suspend l'exécution de ce mot qui attend ensuite une confirmation par <RETURN>. Dans ce cas, ?STOP délivre sur la pile de données un drapeau booléen vrai, sinon renvoie un drapeau booléen faux.

(IS)

: (IS) ( cfa -- )

R@ @ >BODY ! R> 2+ >R ;

Mot compilé par le mot d'exécution immédiate IS. Met dans le mot vectorisé qui suit le code d'exécution du mot dont le cfa est sur la pile. Voir aussi DEFER.

IS

: IS <mot> ( cfa -- )

STATE @ IF COMPILE (IS) ELSE ' >BODY ! THEN ; IMMEDIATE

Affecte le cfa d'un mot à la zone paramétrique d'un mot d'exécution vectorisée. Cette affectation peut être réalisée en interprétation:

' (PRINT) IS EMIT

ou en compilation:

ALSO PRINTER

: IMPRIME ( -- ) ['] (PRINT) IS EMIT ;

Voir aussi DEFER.

Exemple:

Pour compléter la définition précédente:

: ECRAN ( -- ) ['] (EMIT) IS EMIT ;

Ainsi vous serez moins perdu quand vous taperez:

1 IMPRIME CR .( PAGE ) . CR ECRAN

Comme c'est beau le FORTH!

RUN

: RUN ( -- )

STATE @ IF ] STATE @ NOT IF INTERPRET THEN ELSE INTERPRET THEN ;

( version TELESTRAT: )

A6 C,

Permet la compilation multi-ligne, que le flot d'entrée provienne du clavier ou d'un bloc éditeur. Son fonctionnement est transparent pour l'utilisateur.

STATUS

DEFER STATUS ( -- )

' CR IS STATUS

Mot d'exécution vectorisée proposé pour indiquer l'état courant du système. A l'initialisation, ce mot exécute le mot CR. Le mot STATUS est exécuté à chaque mise en instance de l'interpréteur.

QUIT

: QUIT ( -- )

BLK OFF [COMPILE] [ BEGIN R0RP! STATUS QUERY RUN STATE @ NOT IF PROMPT THEN AGAIN ;

Nettoie la pile de retour et revient au mode interprétation. Accepte de nouvelles entrées à partir du terminal courant et commence l'interprétation du texte. N'affiche aucun message.

BOOT

DEFER BOOT ( -- )

' HELLO IS BOOT

Mot d'exécution vectorisée. A l'initialisation, c'est ce mot qui exécute HELLO dont le résultat affiche:

FORTH 83-STANDARD

Vx.xx KERNEL (ou DEVELOPPEMENT, selon la version),

fichier par défaut : <fichier>.<ext> /

(ou "pas de fichier par défaut", selon le cas).

Vous pouvez modifier le vecteur contenu dans BOOT, ce qui aura pour résultat de provoquer l'exécution de la définition remplaçant HELLO dans le vecteur de BOOT lors de la mise en route du système. Voir aussi BYE.

Exemple:

: SALUT CLS ." FORTH 83-STANDARD" CR ." Version modifiée du 15/08/1991" CR ;

' SALUT IS BOOT

Puis tapez BYE. Ensuite, sous BASIC (sur ATMOS, HYPER-BASIC ou TELE-ASS sur TELESTRAT), tapez:

SAVE "fichier.COM",A#dddd,E#ffff,AUTO

où fichier est le nom de votre version FORTH, dddd et ffff les adresses de début et de fin du dictionnaire indiquées par FORTH lors de l'exécution de BYE, pour sauver le dictionnaire sous forme compilée. Le rechargement de votre version se fera à partir du BASIC (ou de l'assembleur) en tapant simplement fichier.

WARM

: WARM ( -- )

TRUE ABORT" demarrage a chaud" ;

Réalise un démarrage à chaud du système. Equivaut à la commande ABORT.

COLD

: COLD ( -- )

BOOT QUIT ;

Réalise un démarrage à froid du système. Voir aussi BOOT.

LOAD

DEFER LOAD ( scr -- )

' (LOAD) IS LOAD

Mot d'exécution vectorisée. A l'initialisation, exécute le mot (LOAD). Charge et compile ou exécute le contenu du bloc écran scr du fichier courant.

(LOAD)

: (LOAD) ( scr -- )

BLK @ >R >IN @ >R >IN OFF BLK ! RUN R> >IN ! R> BLK ! ;

Charge et compile le contenu de l'écran dont le numéro est sur la pile de données. Le flot d'entrée devient le disque. Ce mot est utilisé par le mot d'exécution vectorisée LOAD.

(SOURCE)

: (SOURCE) ( -- adr cnt )

BLK @ ?DUP IF BLOCK B/BUF ELSE TIB #TIB @ THEN ;

Mot utilisé par défaut par le mot d'exécution vectorisée SOURCE qui délivre l'adresse et la longueur du flot d'entrée a exécuter. Le mot SOURCE délivre soit l'adresse et la longueur du TIB (Terminal Input Buffer), soit l'adresse et la longueur du tampon du bloc courant. Au besoin, celui-ci est d'abord lu sur la mémoire de masse.

BASIC

CODE BASIC ( -- )

F9AA JSR, ( initialise le VIA 6522 ) 7 # LDA, 40 # LDX, F590 JSR, ( routine d'e/s avec le PSG 8912 ) EDE0 JSR, ( autorise IRQ par T1 (gestion clavier). )

3 # LDA, 026A STA, ( registre d'état ) B0 # LDA, 1B STA, ( #1B-#1C: vecteur #CCB0 (imprime une chaîne pointée par AY). )

CC # LDA, 1C STA, 35 # LDX, BEGIN, >MARK ,X LDA, -ROT 80 ,X STA, DEX, 0= UNTIL, C471 JMP, ( point d'entrée de l'interpréteur (RESET à chaud). )

20 C, >RESOLVE 00 C, 00 C, 00 C, 00 C, 00 C, 88 C, 85 C, 00 C, 0A C, B2 C, C3 C, 00 C, 00 C, 00 C, 00 C, 00 C, 00 C, B2 C, C3 C, 00 C, 00 C, 00 C, 00 C, 00 C, 00 C, 00 C, 01 C, 05 C, 00 C, 60 C, 00 C, 60 C, 00 C, 60 C, 5F C, 77 C, 5F C, 77 C, 5F C, 77 C, 32 C, FF C, 00 C, 00 C, 78 C, 00 C, 00 C, 00 C, 00 C, 05 C, 00 C, 00 C, 00 C, 00 C, 00 C, ;C

Versions ATMOS. BASIC permet de quitter FORTH pour utiliser par exemple les commandes du SEDORIC. Après cette escapade, il est possible de retourner au FORTH en tapant CALL #504 (WARM JMP,). Notez l'utilisation de -ROT pour croiser les références et celle du couple >MARK ... >RESOLVE pour créer une référence en amont.

VOCABULARY

: VOCABULARY <mot> ( -- )

CREATE 0 , 0 , 0 , 0 , HERE VOC-LINK @ , VOC-LINK ! DOES> CONTEXT ! ;

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 appartenant à 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 <mot> précise le premier vocabulaire de recherche et de définition. Voir aussi ORDER.

Exemples:

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:

: SETUP ONLY FORTH ALSO FPACK DEFINITIONS ;

L'ordre de recherche peut être consulté à tout moment à l'aide du mot ORDER.

DEFINITIONS

: DEFINITIONS ( -- )

CONTEXT @ CURRENT ! ;

Etablit comme vocabulaire courant le premier vocabulaire de contexte. Le vocabulaire courant est celui où s'inscriront les prochaines définitions.

Exemple:

ONLY DEFINITIONS FORTH VOCABULARY TOOLS

ONLY FORTH ALSO TOOLS DEFINITIONS

La première ligne crée un nouveau vocabulaire TOOLS; notez que TOOLS est défini dans ONLY, ce qui est une pratique habituelle pour un accès général à un vocabulaire. La seconde ligne prépare les définitions de mots dans TOOLS en ajustant les vocabulaires de contexte à TOOLS, FORTH et ONLY pour le vocabulaire courant TOOLS.

FORTH

VOCABULARY FORTH ( -- )

Sélectionne le vocabulaire FORTH comme vocabulaire de contexte. Voir aussi VOCABULARY.

SEAL

: SEAL ( -- )

CONTEXT 2+ #VOCS 1- 2* ERASE ;

Isole le premier vocabulaire dans CONTEXT. Voir aussi VOCABULARY.

(ABORT)

: (ABORT) ( -- )

S0 @ SP! QUIT ;

Interrompt l'exécution du mot en cours, restaure les piles de retour et de données à leur état primitif et redonne le contrôle à l'utilisateur. L'exécution de ce mot renvoie à la boucle d'interprétation de l'interpréteur FORTH. En général, il est utilisé pour la gestion des erreurs. Voir aussi ABORT".

LIST

: LIST ( scr -- )

CR DUP SCR ! .FILE ." ecran no " DUP . 10 0 DO CR I 3 .R SPACE DUP BLOCK I C/L * + C/L -TRAILING TYPE ?STOP ?LEAVE LOOP DROP CR ;

Liste le contenu d'un écran source contenu dans le fichier courant. Dans les systèmes FORTH 83-STANDARD pour ORIC, un fichier par défaut est ouvert à l'initialisation, s'il en existe un sur le disque. Pour ouvrir un fichier, il faut taper une séquence de type OPEN fichier.ext (.ext équivaut à .FTH par défaut). Vous pouvez ouvrir tous les fichiers disponibles sous le système d'exploitation (SEDORIC sur ATMOS ou STRATSED sur TELESTRAT), mais la commande LIST est applicable correctement aux seuls fichiers source FORTH.

TERMINAL

DEFER TERMINAL ( -- )

' (TERMINAL) IS TERMINAL

Mot d'exécution vectorisée configurant le terminal. A l'initialisation, exécute le mot (TERMINAL).

.VERSION

DEFER .VERSION ( -- )

' (.VERSION) IS .VERSION

Sur version TELESTRAT uniquement. Mot d'exécution vectorisée. A l'initialisation, exécute (.VERSION) qui affiche un message permettant l'identification du système.

DEFAULT

DEFER DEFAULT ( -- )

' (DEFAULT) IS DEFAULT

Version TELESTRAT. Ouverture de fichier par défaut. Déplace le contenu du bloc de contrôle du fichier dans FCB1 et ouvre le fichier. Il ne se passe rien si aucun fichier n'est précisé.

HELLO

: HELLO ( -- )

( versions ATMOS: )

CLS ." FORTH 83-STANDARD" EMPTY-BUFFERS ONLY FORTH DEFINITIONS TERMINAL DECIMAL ;

( version TELESTRAT: )

ONLY FORTH DEFINITIONS EMPTY-BUFFERS TERMINAL DECIMAL CLS ." FORTH 83-STANDARD " .VERSION CR DEFAULT ;

Réalise l'initialisation du système et affiche l'en-tête de présentation:

FORTH 83-STANDARD

Vx.xx KERNEL (ou DEVELOPPEMENT, selon la version),

fichier par défaut : <fichier>.<ext> /

(ou "pas de fichier par défaut", selon le cas).

Les tampons de blocs sont mis à jour, le vocabulaire FORTH est sélectionné par défaut. Ce mot est ensuite utilisé comme vecteur par BOOT afin de s'exécuter lors de la mise en route de FORTH à partir du BASIC (ou HYPER-BASIC ou TELE-ASS) (commande F83KER, F83DEV, F83ASS, F83KERx, F83DEVx, F83ASSx ou une version personnelle). Si vous désirez sauvegarder une application en version compilée et démarrant automatiquement, il faut initialiser votre système avant exécution du programme:

: <mot> EMPTY-BUFFERS ONLY FORTH ALSO DEFINITIONS DEFAULT <application> ;

' <mot> IS BOOT

où <mot> est le mot à exécuter au démarrage de FORTH, et <application> le mot terminal de votre programme. Voir aussi BYE.

(COLD)

CODE (COLD) ( -- )

( versions ATMOS: )

15 # LDY, 0= IF, 0F # LDY, THEN, ADRUSE LDA, UP STA, ADRUSE 1+ LDA, UP 1+ STA, BEGIN, LASTWO ,Y LDA, UP )Y STA, DEY, 0< UNTIL, 6C # LDA, ( JMP, ) W 1- STA, ['] COLD >BODY 0 100 UM/MOD # LDA, ( partie haute ) IP 1+ STA, # LDA, ( partie basse ) IP STA, CLD, 9D # LDX, ( début de la pile ) ['] R0RP! >BODY JMP, ( pfa de R0RP! ) ;C

( version TELESTRAT: )

15 # LDY, 0= IF, 0F # LDY, THEN, ADRUSE LDA, UP STA, ADRUSE 1+ LDA, UP 1+ STA, BEGIN, LASTWO ,Y LDA, UP )Y STA, DEY, 0< UNTIL, 6C # LDA, ( JMP, ) W 1- STA, ['] COLD >BODY 0 100 UM/MOD # LDA, ( partie haute ) IP 1+ STA, # LDA, ( partie basse ) IP STA, CLD, B9 # LDX, ( début de la pile ) ['] R0RP! >BODY JMP, ( pfa de R0RP! ) ;C

C'est ici que tout commence pour FORTH, lancé pour un "Démarrage à froid" par le moniteur.

DEPTH

: DEPTH ( -- n )

SP@ S0 @ SWAP - 2/ ;

Empile le nombre de cellules 16 bits présentes sur la pile de données. La valeur n ne tient pas compte de sa propre existence, c'est-à-dire que DEPTH compte exactement le nombre de cellules présentes sur la pile avant empilement de ce nombre.

Exemple:

5 6 7 DEPTH . affiche 3,

sauf si vous avez oublié des nombres sur la pile avant d'exécuter cet exemple.

.S

: .S ( -- )

CR DEPTH ?DUP IF 0 DO DEPTH I - 1- PICK . SPACE LOOP ELSE ." pile vide " THEN CR ;

Affiche le contenu de la pile de données de manière non destructive. Ce mot est un outil de mise au point fort utile.

Exemple:

1 2 3 .S affiche 1 2 3

mais laisse 1 2 et 3 sur la pile de données.

H.

: H. ( u -- )

BASE @ 10 BASE ! SWAP U. BASE ! ;

Affiche le nombre u en hexadécimal; utilisé surtout pour les adresses mémoire.

Exemple:

DECIMAL 32768 H. affiche 8000.

PROMPT

DEFER PROMPT ( -- )

' OK IS PROMPT

Mot d'exécution vectorisée. A l'initialisation, c'est ce mot qui exécute OK dont le résultat affiche le message d'invite.

?

: ? ( adr -- )

@ . ;

Imprime le mot 16 bits situé à adr; utile surtout en intéractif.

Exemple:

123 PAD ! PAD ? affiche 123.

OK

: OK ( -- )

." Ok." BASE @ DUP 0A = IF ASCII . ELSE DUP 10 = IF ASCII # ELSE DUP 2 = IF ASCII % ELSE ASCII * THEN THEN THEN EMIT DROP DEPTH . ;

Mot utilisé par le mot d'exécution vectorisée PROMPT qui affiche le message d'invite.

?LOADING

: ?LOADING ( -- )

BLK @ 0= ABORT" sur disque seulement " ;

Génère l'erreur "sur disque seulement" si le flot d'entrée n'est pas un fichier.

?ENOUGH

: ?ENOUGH ( n -- )

DEPTH 1- > ABORT" pas assez de parametres" ;

Délivre un message d'erreur et arrête l'exécution du mot en cours si le nombre de paramètres déposés sur la pile de données est inférieur à la valeur n.

Exemple:

: DIV ( n2 n1 -- q ) 2 ?ENOUGH / ;

22 DIV . affiche "pas assez de paramètres".

22 7 DIV . affiche 3.

-->

: --> ( -- )

?LOADING >IN OFF 1 BLK +! ; IMMEDIATE

Force l'interprétation (et la compilation s'il y a lieu) du contenu du bloc suivant le bloc courant. Ce mot figure généralement en fin de bloc. Ainsi, si vous tapez n LOAD et que le mot --> figure en fin de ce bloc, l'interpréteur poursuit la lecture vers le contenu du bloc n+1. Mais on lui préférera généralement le mot THRU qui permet un encadrement du code source à compiler.

caractère backslash

: caractère backslash <chaîne de caractères> ( -- )

?LOADING >IN @ NEGATE C/L MOD >IN +! ; IMMEDIATE

Début d'un commentaire en ligne dans un bloc écran. Le commentaire débute après l'espace de séparation et s'achève en fin de ligne.

Exemples:

Voir les lignes 0 des blocs écrans des fichiers fournis avec votre système FORTH 83-STANDARD.

THRU

: THRU ( scr1 scrn -- )

2 ?ENOUGH 1+ SWAP DO I LOAD LOOP ;

Chargement du contenu d'une série de blocs écrans. L'usage de ce mot permet (et impose) de se passer du mot --> en fin de bloc.

ID.

: ID. ( nfa -- )

COUNT 1F AND ?DUP IF 0 DO COUNT 7F AND EMIT LOOP THEN DROP SPACE ;

Affiche l'en-tête du nom dont l'adresse du champ de nom (nfa) est sur la pile de données.

Exemple:

' DUP >NAME ID. affiche DUP.

ALSO

: ALSO ( -- )

CONTEXT DUP 2+ #VOCS 1- 2* CMOVE> ;

Prépare la pile des vocabulaires à recevoir un nouveau vocabulaire de contexte.

PREVIOUS

: PREVIOUS ( -- )

CONTEXT DUP 2+ SWAP 8 CMOVE CONTEXT 8 + OFF ;

Manipule la pile des vocabulaires de contexte de façon à faire disparaître le premier vocabulaire.

ONLY

VOCABULARY ONLY ( -- )

DOES> SEAL CONTEXT 2DUP 2+ ! ! ;

Vocabulaire. Permet de sélectionner l'ordre de recherche dans les différents vocabulaires définis dans le dictionnaire. L'ordre de recherche est réduit au minimum.

ONLY DEFINITIONS

:( -- )

END? ON ; IMMEDIATE

Mot blanc. L'identificateur de ce mot est composé d'un seul caractère de code ASCII espace (C0 A0).

ALSO

: ALSO ( -- )

ALSO ;

Prépare la pile des vocabulaires à recevoir un nouveau vocabulaire de contexte.

FORTH

: FORTH ( -- )

FORTH ;

Sélectionne le vocabulaire FORTH comme vocabulaire de contexte. Voir aussi VOCABULARY.

DEFINITIONS

: DEFINITIONS ( -- )

DEFINITIONS ;

Etablit comme vocabulaire courant le premier vocabulaire de contexte. Le vocabulaire courant est celui où s'inscriront les prochaines définitions.

Exemple:

ONLY DEFINITIONS FORTH VOCABULARY TOOLS

ONLY FORTH ALSO TOOLS DEFINITIONS

La première ligne crée un nouveau vocabulaire TOOLS; notez que TOOLS est défini dans ONLY, ce qui est une pratique habituelle pour un accès général à un vocabulaire.

La seconde ligne prépare les définitions de mots dans TOOLS en ajustant les vocabulaires de contexte à TOOLS, FORTH et ONLY pour le vocabulaire courant TOOLS.

ORDER

: ORDER ( -- )

CR ." contexte : " CONTEXT #VOCS 0 DO DUP @ ?DUP IF BODY> >NAME ID. THEN 2+ LOOP DROP CR ." vocabulaire courant : " CURRENT @ BODY> >NAME ID. ;

Affiche la liste des vocabulaires de contexte dans l'ordre de recherche lexicale ainsi que le vocabulaire courant. Voir aussi ONLY, PREVIOUS, SEAL et VOCABULARY.

VOCS

: VOCS ( -- )

VOC-LINK @ BEGIN DUP 8 - BODY> >NAME ID. @ DUP 0= UNTIL DROP ;

Affiche la liste des vocabulaires du dictionnaire. Voir aussi VOCABULARY.

FORTH DEFINITIONS

2@

: 2@ ( adr -- d )

DUP @ SWAP 2+ @ SWAP ;

Version TELESTRAT. Délivre le nombre double précision contenu à l'adresse adr. Voir aussi 2!.

2!

: 2! ( d adr -- )

DUP -ROT ! 2+ ! ;

Version TELESTRAT. Stocke le nombre double précision d (32 bits) à l'adresse adr. Voir aussi 2@.

Exemple:

656565. PAD 2! PAD 2@ D. affiche 656565.

2CONSTANT

: 2CONSTANT <mot> ( d -- | -- d )

CREATE , , DOES> 2@ ;

Version TELESTRAT. Mot de définition d'une constante 32 bits. Est utilisé sous la forme:

<d> 2CONSTANT <mot>

A l'exécution, le mot <mot> empile la valeur d qui lui a été attribuée lors de sa définition:

<mot> D. affiche <d>

Voir aussi 2! et 2@.

2VARIABLE

: 2VARIABLE <mot> ( -- | -- adr )

0 0 2CONSTANT DOES> ;

Version TELESTRAT. Mot de définition d'une variable 32 bits. Est utilisé sous la forme:

2VARIABLE <mot>

Le contenu de la variable ainsi définie est nul. L'exécution de <mot> dépose sur la pile l'adresse de son champ paramétrique. Voir aussi 2! et 2@.

Exemples:

2VARIABLE ESSAI

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.

LARGEST

: LARGEST ( adr1 n1 -- adr2 n2 )

OVER 0 SWAP ROT 0 DO 2DUP @ U< IF -ROT 2DROP DUP @ OVER THEN 2+ LOOP DROP ;

A partir d'une adresse adr1 et d'un nombre n1 déposés sur la pile de données, délivre l'adresse et la plus grande valeur dans la zone ainsi pointée. Ceci permet notamment au sein d'un tableau de nombres, de rechercher la plus grande valeur numérique.

Exemple:

CREATE TABLEAU 5 , 35 , 75 , 7 , 25 ,

TABLEAU 5 LARGEST (exploration sur 5 valeurs) délivre l'adresse TABLEAU + 6 et la valeur 75.

WORDS

: WORDS ( -- )

CR CONTEXT @ HERE 8 CMOVE BEGIN HERE 4 LARGEST DUP 0<> ?STOP NOT AND WHILE DUP L>NAME DUP C@ 1F AND #OUT @ + C/L U> IF CR THEN ID. @ SWAP ! REPEAT 2DROP ;

Le mot certainement le plus utile pendant la phase d'apprentissage et de développement en langage FORTH. Grâce à lui, vous visualisez les noms de toutes les définitions contenues dans le vocabulaire courant.

Exemples:

FORTH WORDS liste les mots du vocabulaire FORTH,

EDITOR WORDS liste les mots du vocabulaire EDITOR,

ASSEMBLER WORDS liste les mots du vocabulaire ASSEMBLER... il y en a beaucoup, hein... un peu d'aspirine?

ONLY DEFINITIONS

WORDS

: WORDS ( -- )

WORDS ;

Le mot certainement le plus utile pendant la phase d'apprentissage et de développement en langage FORTH. Grāce à lui, vous visualisez les noms de toutes les définitions contenues dans le vocabulaire courant.

Exemples:

FORTH WORDS liste les mots du vocabulaire FORTH,

EDITOR WORDS liste les mots du vocabulaire EDITOR,

ASSEMBLER WORDS liste les mots du vocabulaire ASSEMBLER... il y en a beaucoup, hein... un peu d'aspirine?

FORTH DEFINITIONS

TRIM

: TRIM ( adr1 adr2 -- )

4 0 DO 2DUP @ BEGIN 2DUP U> NOT WHILE @ REPEAT NIP OVER ! 2+ LOOP 2DROP ;

Change les quatre pointeurs de "hash-code" dans un vocabulaire de manière à rendre leur valeur inférieure à la valeur spécifiée par adr1.

(FORGET)

: (FORGET) ( adr -- )

DUP FENCE @ U< ABORT" dictionnaire protege" DUP VOC-LINK @ BEGIN 2DUP U< WHILE @ REPEAT DUP VOC-LINK ! NIP BEGIN DUP WHILE 2DUP 8 - TRIM @ REPEAT DROP DP ! ;

Oublie une partie du dictionnaire. Le mot (FORGET) réinitialise les liens et restitue l'espace mémoire. Ce mot est utilisé dans la définition de FORGET.

FORGET

: FORGET <mot> ( -- )

BL WORD CAPS @ IF DUP COUNT UPPER THEN CURRENT @ OVER SWAP HASH @ (FIND) 0= ?MISSING >LINK (FORGET) ;

Provoque l'oubli de <mot> ainsi que de toutes les autres définitions définies après <mot>.

Exemple:

: MOT1 ;

: MOT2 ;

: MOT3 ;

FORGET MOT2 détruit MOT2 et MOT3 du dictionnaire.

FORBID

: FORBID <mot> ( -- )

BL WORD CAPS @ IF DUP COUNT UPPER THEN CURRENT @ OVER SWAP HASH TUCK @ (FIND) 0= ?MISSING >LINK SWAP BEGIN 2DUP @ <> WHILE @ REPEAT >R @ R> ! ;

"Strappe" dans le vocabulaire courant un mot devenu inutile et encombrant; frappe <mot> d'interdiction; il ne figure plus dans une liste WORDS et n'est plus exécutable. Sa définition quoique invisible reste toutefois présente et les mots qui l'ont utilisé restent valides, à la différence d'une procédure FORGET. Il est permis d'interdire des mots dans le dictionnaire protégé (en deça de FENCE). Le FORTH 83-STANDARD aurait bien besoin de quelques coups de FORBID: clarté et rapidité de recherche y gagneraient!

BIOS

CODE BIOS ( fun -- )

BOT LDA, >MARK STA, AYX LDA, AYX 1+ LDY, XSAVE STX, AYX 2+ LDX, 1 PC +! >RESOLVE -1 PC +! 24 BRK, AYX STA, AYX 1+ STY, AYX 2+ STX, PHP, PLA, PIO STA, XSAVE LDX, POP JMP, ;C

Sur version TELESTRAT uniquement. BIOS prend le numéro de fonction sur la pile et prend les valeurs des registres dans la variable AYX (adresse CC hexa, registre accumulateur en CC, registre Y en CD, registre X en CE) et l'indicateur de retenue C dans le bit 0 de la variable PIO (adresse CF); après exécution de BIOS, les valeurs des registres sont retournées aux mêmes adresses, et l'indicateur d'état est retourné à l'adresse PIO (bit 7 à 0: NV-BDIZC), pour exemples, voir les différentes interfaces avec le moniteur (OPCH, CLCH, (KBD)). Notez l'utilisation du couple >MARK ... 1 PC +! >RESOLVE -1 PC +! pour créer une référence en aval.

OPCH

: OPCH ( ch io -- )

80 OR CC ( AYX ) C! 3 AND BIOS ;

Sur version TELESTRAT uniquement. OPCH ouvre sur le canal ch le driver de l'entrée/sortie io. Voir aussi BIOS, CLCH et (KBD).

CLCH

: CLCH ( ch io -- )

80 OR CC ( AYX ) C! 3 AND 4 + BIOS ;

Sur version TELESTRAT uniquement. CLCH ferme sur le canal ch le driver de l'entrée/sortie io. Voir aussi BIOS, OPCH et (KBD).

CALL

CODE CALL ( adr -- )

BOT LDA, >MARK STA, BOT 1+ LDA, >MARK STA, INX, INX, XSAVE STX, 2 PC +! >RESOLVE -2 PC +! 1 PC +! >RESOLVE -1 PC +! C000 JSR, XSAVE LDX, NEXT, ;C

Appelle le sous-programme dont l'adresse commence à celle qui est spécifiée au sommet de la pile de données. Notez l'utilisation des couples >MARK ... 2 PC +! >RESOLVE -2 PC +! et >MARK ... 1 PC +! >RESOLVE -1 PC +! pour créer deux références en aval.

BANK

CODE BANK ( n -- )

PHP, SEI, BOT LDA, 7 # AND, 2A # LDY, UP )Y STA, V2DRA LDA, F8 # AND, UP )Y ORA, V2DRA STA, PLP, POP JMP, ;C

Sur version TELESTRAT uniquement. BANK permet de passer sur la banque n. Voir aussi BNK.

DUMP

: DUMP ( adr -- )

BASE @ SWAP 10 BASE ! BEGIN CR DUP 0 <# # # # # #> TYPE SPACE 8 0 DO DUP I + C@ 0 <# # # #> TYPE SPACE LOOP 8 0 DO DUP I + C@ 7F AND 20 MAX 7E MIN EMIT LOOP 8 + ?STOP UNTIL DROP CR BASE ! ;

( version TELESTRAT: )

8F C,

DUMP affiche le contenu de huit adresses consécutives par ligne, suivi des caractères ASCII équivalents au contenu de ces adresses. L'adresse de départ du vidage mémoire équivaut à l'adresse adr. Le vidage mémoire (francisation de DUMP, pour faire du mieux disant culturel...) se fait jusqu'à l'activation d'une touche quelconque qui met l'exécuteur d'adresse en attente de l'activation d'une autre touche qui, si elle est différente de <RETURN>, poursuit le traitement et l'arrête dans le cas contraire.

INDEX

: INDEX ( prem dern -- )

2 ?ENOUGH 1+ SWAP DO CR I 3 .R SPACE I BLOCK C/L -TRAILING TYPE ?STOP ?LEAVE LOOP CR ;

Affiche le contenu de la première ligne des blocs écrans prem à dern, valeurs comprises entre 1 et le nombre de blocs écran contenus dans le fichier courant.

DEFAULT

DEFER DEFAULT ( -- )

' (DEFAULT) IS DEFAULT

Versions ATMOS. Ouverture de fichier par défaut. Déplace le contenu du bloc de contrôle du fichier dans FCB1 et ouvre le fichier. Il ne se passe rien si aucun fichier n'est précisé.

A-IN

: A-IN ( adr n1 -- adr n2 )

( versions ATMOS: )

12 @ 269 C@ + C@ 7F AND CHAR ;

( version TELESTRAT: )

24C ( CURSCR ) C@ CHAR ;

Permet de recopier des séquences sans avoir a les réécrire, tout comme avec l'éditeur BASIC de l'ATMOS. Dans la table initiale CTRL1, le mot A-IN est exécuté par <CTRL> + <A>. Voir aussi CTRL.

C-IN

: C-IN ( -- )

DEFAULT CR WARM ;

Version TELESTRAT. Relance le système par un démarrage à chaud et affiche un fichier ouvert par défaut, s'il en existe un, lors d'un changement de disque. Dans la table initiale CTRL1, C-IN est exécuté par <CTRL> + <C>. Voir aussi CTRL.

X-IN

: X-IN ( adr n -- adr 0 )

0<> IF 5C EMIT CR THEN 0 ;

Reprend la saisie depuis le début. Dans la table initiale CTRL1, le mot X-IN est exécuté par <CTRL> + <X>. Voir aussi CTRL.

C-IN

: C-IN ( -- )

DEFAULT CR WARM ;

Versions ATMOS. Relance le système par un démarrage à chaud et affiche un fichier ouvert par défaut, s'il en existe un, lors d'un changement de disque. Dans la table initiale CTRL1, C-IN est exécuté par <CTRL> + <C>. Voir aussi CTRL.

CURSOR

: CURSOR ( -- )

10 (EMIT) ;

Partie exécution du caractère de contrôle de bascule curseur visible. Envoie le code ASCII 16 sur le terminal de sortie, ce qui a pour effet de passer alternativement le curseur à l'état visible ou invisible. Dans la table initiale CTRL1, CURSOR est exécuté par action sur <CTRL> + <Q>.

AT

( versions ATMOS: )

CODE AT ( Xcolonne Yligne -- ) 80 # LDA, 12 STA, BB # LDA, 13 STA, BOT LDA, 268 STA, TAY, 0= NOT IF, CLC, BEGIN, 28 # LDA, 12 ADC, 12 STA, 0 # LDA, 13 ADC, 13 STA, DEY, 0= UNTIL, THEN, BOT 2+ LDA, 269 STA, 30 STA, POPTWO JMP, ;C

( version TELESTRAT: )

: AT ( Xcolonne Yligne -- ) 1F (EMIT) 40 + (EMIT) 40 + (EMIT) ;

Positionne le curseur d'écran en (X, Y).

BASIC

: BASIC ( -- )

" COM" 55D ( EXTDEF ) SWAP CMOVE CR CR 6 BANK C000 CALL ;

Version TELESTRAT. BASIC permet de quitter FORTH pour utiliser par exemple les commandes du STRATSED. Après cette escapade, il est possible de retourner au FORTH en tapant CALL #904 (WARM JMP,).

LOCK

: LOCK ( -- )

( versions ATMOS: )

ONLY FORTH DEFINITIONS CONTEXT @ @ 50C ( LASTWO ) ! HERE 51C ( FENCE ) ! HERE 51E ( DP ) ! VOC-LINK @ 520 ( ADRVLI ) ! HERE FENCE ! ;

( version TELESTRAT: )

ONLY FORTH DEFINITIONS CONTEXT @ @ 90C ( LASTWO ) ! HERE 91C ( FENCE ) ! HERE 91E ( DP ) ! VOC-LINK @ 920 ( ADRVLI ) ! HERE FENCE ! ;

Verrouille le dictionnaire et ajuste les pointeurs initiaux. Voir aussi BYE.

BYE

: BYE ( -- )

( versions ATMOS: )

LOCK CR 500 ( ORIGIN ) H. HERE H. BASIC ;

( versions TELESTRAT: )

LOCK CR 900 ( ORIGIN ) H. HERE CR H. BASIC ;

Si vous avez terminé votre travail sous FORTH, vous avez deux solutions, couper le courant (... sauvagement) ou taper BYE. FORTH revient alors sous BASIC (sur ATMOS, sous HYPER-BASIC ou TELE-ASS sur TELESTRAT) après avoir indiqué les adresses de début et de fin du dictionnaire (en hexadécimal). Cette indication vous permet de réaliser sous BASIC (HYPER-BASIC ou TELE-ASS) une sauvegarde en version compilée de votre dictionnaire tel que vous l'avez laissé en tapant:

SAVE "<fichier>.<ext>",A#dddd,E#ffff,AUTO

(ceci sous BASIC, HYPER-BASIC ou TELE-ASS bien entendu) où dddd et ffff sont respectivement les adresses de début et de fin du dictionnaire indiquées au moment de l'exécution de BYE. Le contenu du fichier est ainsi sauvegardé et réexécutable en tapant ensuite <fichier>.<ext> à partir du BASIC (de l'HYPER-BASIC ou de TELE-ASS).

INK

: INK ( couleur -- )

( versions ATMOS: )

ABS 7 MIN 2E1 ( Param1 ) ! F210 ( commande INK ) CALL ;

( version TELESTRAT: )

7 AND CC ( AYX ) C! CD ( AYX+1 ) OFF 93 ( XINK ) BIOS ;

Change la couleur de l'encre ("foreground"). Voir aussi PAPER.

PAPER

: PAPER ( couleur -- )

( versions ATMOS: )

ABS 7 MIN 2E1 ( Param1 ) ! F204 ( commande PAPER ) CALL ;

( version TELESTRAT: )

7 AND 10 + CC ( AYX ) C! CD ( AYX+1 ) OFF 92 ( XPAPER ) BIOS ;

Change la couleur du papier ("background"). Voir aussi INK.

(KBD)

: (KBD) ( n -- )

CC ( AYX ) C! 52 ( XGOKBD ) BIOS ;

Sur version TELESTRAT uniquement. Permet de changer le type de clavier. Les mots QWERTY, AZERTY et ACCENT ont été créés dans le vocabulaire FORTH avec les valeurs de n suivantes:

Rappel : QWERTY, AZERTY et ACCENT existent dans le vocabulaire FORTH.

QWERTY

: QWERTY ( -- )

( versions ATMOS: )

RAM/ROM EBE1 CALL RAM/ROM ;

( version TELESTRAT: )

0 (KBD) ;

Clavier prédéfini de type anglais. Voir aussi (KBD) (sur TELESTRAT), AZERTY et ACCENT.

AZERTY

: AZERTY ( -- )

( versions ATMOS: )

RAM/ROM EBDE CALL RAM/ROM ;

( version TELESTRAT: )

1 (KBD) ;

Clavier prédéfini de type français. Voir aussi (KBD) (sur TELESTRAT), QWERTY et ACCENT.

ACCENT

: ACCENT ( -- )

( versions ATMOS: )

RAM/ROM 40 C03D ( MODCLA ) C! EBE6 CALL RAM/ROM ;

( version TELESTRAT: )

4 (KBD) ;

ACCENT fait basculer entre les types de clavier avec ou sans accents. Voir aussi (KBD) (sur TELESTRAT), AZERTY et QWERTY.

VERSION

: VERSION ( -- adr cnt )

" V2.4 KERNEL " ;

Version TELESTRAT. Retourne la chaîne de caractères explicite spécifiant la version en cours. Voir aussi .VERSION et (.VERSION).

(.VERSION)

: (.VERSION) ( -- )

CR VERSION TYPE ;

Sur version TELESTRAT uniquement. Affiche la version en cours. Voir aussi VERSION et .VERSION.

(TERMINAL)

: (TERMINAL) ( -- )

QWERTY 80 275 ( FLGKBD ) C! " FTH" 55D ( EXTDEF ) SWAP CMOVE ;

Version TELESTRAT. Vecteur standard de TERMINAL (voir ce mot).

INSERT

: INSERT ( adr1 cnt1 adr2 cnt2 -- )

ROT OVER MIN >R R@ - OVER DUP R@ + ROT CMOVE> R> CMOVE ;

Insère la chaîne adr1 cnt1 dans le tampon adr2 cnt2. La longueur cnt1 doit être inférieure à cnt2.

Exemple:

: TEXTE " que le FORTH soit avec vous " ;

: CHATS " Nous n'aimons pas les chats " ;

CHATS 14 NIP TEXTE INSERT

TEXTE TYPE affiche "Nous n'aimons que le FORTH".

REPLACE

: REPLACE ( adr1 cnt1 adr2 cnt2 -- )

ROT MIN CMOVE ;

Opérateur de chaîne. Recouvre avec le minimum de cnt1 ou cnt2 dans adr2 depuis adr1.

DELETE

: DELETE ( adr cnt1 cnt2 -- )

OVER MIN >R R@ - DUP 0> IF 2DUP SWAP DUP R@ + -ROT SWAP CMOVE THEN + R> BLANK ;

Opérateur sur chaîne de caractères: efface les cnt2 premiers caractères d'une chaîne de caractères explicite de longueur cnt1 débutant à l'adresse adr. Le reste de la chaîne est décalé à gauche et sa fin est complétée par des espaces. La valeur de cnt2 est contrôlée et éventuellement tronquée pour ne pas dépasser la longueur de la chaîne.

Exemple:

: TEXTE " BONJOUR" ;

TEXTE 3 DELETE

TEXTE TYPE affiche "JOUR" suivi de 3 espaces.

FOUND

VARIABLE FOUND ( -- adr )

Variable dont le contenu sert d'indicateur booléen par SEARCH.

SEARCH

: SEARCH ( adr1 cnt1 adr2 cnt2 -- n b )

FOUND OFF OVER >R ROT TUCK - 1+ 0 ?DO 3DUP COMPARE 0= IF FOUND ON LEAVE THEN SWAP 1+ SWAP LOOP DROP NIP R> - FOUND @ ;

Recherche la chaîne de caractères pointée par adr1 cnt1 dans la chaîne de caractères pointée par adr2 cnt2. Si la chaîne est trouvée, b est vrai et n correspond au décalage depuis le début de la chaîne de recherche. Si la chaîne n'est pas trouvée, b est faux et n est sans signification.

LINE

: LINE ( lig -- adr cnt )

DUP -10 AND 0<> ABORT" hors limites ecran " C/L * SCR @ BLOCK + C/L ;

Génère le message d'erreur "hors limites écran" si lig est hors de l'intervalle [ 0 ... 15 ].

2@

: 2@ ( adr -- d )

DUP @ SWAP 2+ @ SWAP ;

Versions ATMOS. Délivre le nombre double précision contenu à l'adresse adr. Voir aussi 2!.

2!

: 2! ( d adr -- )

DUP -ROT ! 2+ ! ;

Versions ATMOS. Stocke le nombre double précision d (32 bits) à l'adresse adr. Voir aussi 2@.

Exemple:

656565. PAD 2! PAD 2@ D. affiche 656565.

2CONSTANT

: 2CONSTANT <mot> ( d -- | -- d )

CREATE , , DOES> 2@ ;

Versions ATMOS. Mot de définition d'une constante 32 bits. Est utilisé sous la forme:

<d> 2CONSTANT <mot>

A l'exécution, le mot <mot> empile la valeur d qui lui a été attribuée lors de sa définition:

<mot> D. affiche <d>

Voir aussi 2! et 2@.

2VARIABLE

: 2VARIABLE <mot> ( -- | -- adr )

0 0 2CONSTANT DOES> ;

Versions ATMOS. Mot de définition d'une variable 32 bits. Est utilisé sous la forme:

2VARIABLE <mot>

Le contenu de la variable ainsi définie est nul. L'exécution de <mot> dépose sur la pile l'adresse de son champ paramétrique. Voir aussi 2! et 2@.

Exemples:

2VARIABLE ESSAI

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.

CLEAR

: CLEAR ( scr -- )

DUP SCR ! BUFFER B/BUF BLANK UPDATE ;

L'écran scr est effacé et marqué "modifié".

(COPY)

: (COPY) ( srce dest -- )

SWAP BLOCK DROP 1 BUFFER# ! UPDATE ;

Définition primitive utilisée par COPY pour copier le contenu du bloc écran srce vers le bloc écran dest.

COPY

DEFER COPY ( srce dest -- )

' (COPY) IS COPY

Copie l'écran srce dans l'écran dest avec mise à jour sur la mémoire de masse.

?RANGE

: ?RANGE ( n3 n2 n1 -- )

BETWEEN NOT ABORT" hors limites " ;

Vérifie qu'un numéro de bloc écran est compatible. Les numéros de blocs écran sont compris entre 1 et 30.

CAPACITY

VARIABLE CAPACITY ( -- adr )

Délivre le nombre total de blocs accessibles dans le fichier courant.

ONLY DEFINITIONS

DOS

VOCABULARY DOS ( -- )

' DOS >BODY 8 + SWAP !

Sélectionne le vocabulaire DOS comme vocabulaire de contexte. Ce vocabulaire contient tous les mots servant à gérer les fichiers de la mémoire de masse. Voir aussi VOCABULARY.

DOS DEFINITIONS

B/FCB

14 CONSTANT B/FCB ( -- 20 )

Constante, 20 sur ORIC, du nombre d'octets par bloc de contrôle d'un fichier (Bytes per File Control Block).

FCB

VARIABLE FCB ( -- adr )

12 ALLOT

FCB 14 BLANK

Tableau pointant sur le bloc de contrôle de fichier utilisé par défaut. Une zone de 20 octets est réservée sur les versions pour ORIC.

?DOS

: ?DOS ( -- )

( versions ATMOS: )

FILE @ 0= ABORT" pas de DOS " ;

( version TELESTRAT: )

FILE @ 0= ABORT" pas de STRATSED " ;

Génère le message d'erreur "pas de DOS" (sur versions ATMOS, "pas de STRATSED" sur version TELESTRAT) si le disque n'a pas été formaté sous l'un de ces systèmes.

?VALID

: ?VALID ( b -- )

ABORT" nom de fichier incorrect" ;

Sur versions ATMOS uniquement. Délivre le message d'erreur "nom de fichier incorrect" si le drapeau booléen b placé au sommet de la pile de données est vrai.

?WILDCARDS

: ?WILDCARDS ( -- b )

0 C035 C029 DO DROP RAM/ROM I C@ RAM/ROM ASCII ? = DUP ?LEAVE LOOP ;

Sur versions ATMOS uniquement. Délivre un drapeau booléen vrai si au moins un joker "?" figure dans le nom du fichier courant.

EXT

( versions ATMOS: )

3 CCF7 2CONSTANT EXT ( -- adr 3 )

( version TELESTRAT: )

3 55D ( EXTDEF ) 2CONSTANT EXT ( -- adr 3 )

Délivre sur la pile de données la chaîne de caractères explicite de l'extension courante.

DRV

: DRV ( drv -- )

( versions ATMOS: )

3 AND DUP C039 + RAM/ROM C@ RAM/ROM 0= ABORT" lecteur absent " RAM/ROM DUP C000 C! C009 C! RAM/ROM ;

( version TELESTRAT: )

3 AND DUP 208 ( TABDRV ) + C@ 0= ABORT" lecteur absent " DUP 500 ( DRIVE ) C! 20C ( DRVDEF ) C! ;

Change le lecteur par défaut; si le lecteur demandé n'est pas connecté, un message "lecteur absent" est généré.

Voir aussi .DRV.

DRV?

: DRV? ( -- drv )

RAM/ROM C000 ( DRIVE ) C@ RAM/ROM ;

Sur versions ATMOS uniquement. Délivre le numéro du lecteur courant. Voir aussi DRV.

.DRV

: .DRV ( -- )

( versions ATMOS: )

DRV? ASCII A + EMIT ." -: " RAM/ROM C202 @ RAM/ROM . ." secteurs libres " ;

( version TELESTRAT: )

BNK @ 500 ( DRIVE ) C@ ASCII A + EMIT ." -: " 0 BANK C202 ? ." secteurs libres " BANK ;

Affiche le lecteur courant ainsi que le nombre de secteurs libres. Voir aussi DRV.

Exemple:

.DRV affiche "A-: 210 secteurs libres", s'il y a 210 secteurs inutilisés sur le disque bien sûr.

EXT:

: EXT: <mot> ( -- )

( versions ATMOS: )

RAM/ROM BL EXT BLANK WORD COUNT EXT DROP SWAP CMOVE RAM/ROM ;

( version TELESTRAT: )

BL EXT BLANK WORD COUNT EXT DROP SWAP CMOVE ;

Change l'extension par défaut. Voir aussi EXT.

Exemple:

EXT TYPE affiche "FTH" (extension par défaut).

EXT: COM

EXT TYPE affiche "COM".

BDOS

: BDOS ( fun -- b )

XSAVE STX, 04FD STY, ( ERROR ) BOT 1+ STY, BOT LDA, 04F0 STA, ( EXEVEC+1 ) FF # LDA, 04F1 STA, ( EXEVEC+2 ) 7A LDA, 7B LDY, 7C LDX, 04EC JSR, ( EXERAM ) 7A STA, 7B STY, 7C STX, PHP, PLA, 7D STA, BEGIN, XSAVE LDX, 04FD LDA, ( ERROR ) BOT STA, NEXT,

LABEL SPBDOS

04F2 JSR, ( RAMROM ) CLI, AGAIN, ;C

Versions ATMOS. BDOS est la primitive d'appel, dans la banque mémoire du DOS de l'adresse de la fonction a exécuter, dont la forme est FFxx hexa, avec xx = fun (Y est toujours nul à l'entrée d'une primitive); un code différent de zéro est retourné dans ERROR s'il y a eu erreur; comme pour BIOS, les registres sont passés et retournés à travers les variables #7A-#7C et #7D. Voir aussi XSAVE, XLOAD, SEARCH et SEARCH-.

XNFA

: XNFA ( adr1 cnt1 adr2 cnt2 -- )

0 C! -ROT DUP 0 ?DO SWAP DUP I + C@ DUP ASCII A ASCII Z BETWEEN OVER ASCII 0 ASCII 9 BETWEEN OR 0= IF DUP ASCII * = OVER ASCII ? = OR 0= ?VALID THEN DUP ASCII * = IF DROP SWAP DUP 1+ <> ?VALID 0 C@ I DO ASCII ? 3 PICK I + RAM/ROM C! RAM/ROM LOOP LEAVE THEN 3 PICK I + RAM/ROM C! RAM/ROM SWAP LOOP 2DROP DROP ;

Sur versions ATMOS uniquement. Mot utilisé par le mot NAME! (voir ce mot).

NAME!

: NAME! ( adr cnt -- )

( versions ATMOS: )

RAM/ROM C029 0B BLANK RAM/ROM DUP 1 > IF OVER 1+ C@ 2D = IF OVER C@ ASCII A - DRV 2- SWAP 2+ SWAP THEN THEN DUP 0= IF 2DROP " *.*" THEN DRV? RAM/ROM C028 C! RAM/ROM 2DUP 2E SCAN DUP IF DUP >R 1- SWAP 1+ SWAP DUP 3 > ?VALID C032 3 XNFA R> - ELSE 2DROP RAM/ROM EXT C032 SWAP CMOVE RAM/ROM THEN DUP 09 > ?VALID C029 09 XNFA ;

( version TELESTRAT: )

CE ( <AYX+2 ) C! CC ( <AYX ) ! 24 ( XNOMFI ) BIOS CE ( <AYX+2 ) C@ 2 > ABORT" nom de fichier incorrect " 517 ( BUFNOM ) C@ DRV ;

Charge BUFNOM STRATSED (sur version TELESTRAT) ou SEDORIC (sur versions ATMOS) avec la chaîne explicite spécifiée au sommet de la pile de données et y ajoute l'extension. Voir aussi FILENAME.

FILENAME

: FILENAME <mot> ( -- )

?DOS BL WORD COUNT NAME! ;

FILENAME prend le mot qui le suit dans le flot d'entrée et le place dans BUFNOM du STRATSED (sur version TELESTRAT) ou du SEDORIC (sur versions ATMOS). Voir aussi NAME!.

BDOS

CODE BDOS ( fun -- b )

XSAVE STX, ERRNB STY, PHP, BOT LDA, >MARK STA, TSX, DEX, DEX, SAVES STX, SEI, V2DRA LDA, 7 # AND, N 1- STA, V2DRA LDA, F8 # AND, V2DRA STA, PLP, PHP, AYX LDA, AYX 1+ LDY, AYX 2+ LDX, 1 PC +! >RESOLVE -1 PC +! XTRVNX JSR, AYX STA, AYX 1+ STY, AYX 2+ STX, PHP, PLA, PIO STA, SEI, V2DRA LDA, N 1- ORA, V2DRA STA, PLP, XSAVE LDX, ERRNB LDA, BOT STA, NEXT, ;C

Version TELESTRAT. BDOS est la primitive d'appel, dans la banque mémoire du DOS de l'adresse de la fonction a exécuter, dont la forme est FFxx hexa, avec xx = fun (Y est toujours nul à l'entrée d'une primitive); un code différent de zéro est retourné dans ERRNB s'il y a eu erreur; comme pour BIOS, les registres sont passés et retournés à travers les variables AYX et PIO. Notez l'utilisation du couple >MARK ... 1 PC +! >RESOLVE -1 PC +! pour créer une référence en aval. Voir aussi XSAVE, XLOAD, SEARCH et SEARCH-.

SEARCH

: SEARCH ( -- b )

( versions ATMOS: )

9A BDOS DISK-ERR? 7D C@ 2 AND 0= ;

( version TELESTRAT: )

7D ( <XTRVNM ) BDOS DISK-ERR? CF ( PIO ) C@ 2 AND 0= ;

Fonction STRATSED (sur version TELESTRAT) ou SEDORIC (sur versions ATMOS) prédéfinie recherchant la première occurrence du nom contenu dans BUFNOM sur le lecteur courant. Voir aussi BDOS et SEARCH-.

SEARCH-

: SEARCH- ( -- b )

( versions ATMOS: )

94 BDOS DISK-ERR? 7D C@ 2 AND 0= ;

46 C,

( version TELESTRAT: )

80 ( <XTRVNX ) BDOS DISK-ERR? CF C@ 2 AND 0= ;

Fonction STRATSED (sur version TELESTRAT) ou SEDORIC (sur versions ATMOS) prédéfinie recherchant, comme SEARCH un fichier sur disque, mais à partir de la position courante, soit l'occurrence suivante du nom contenu dans BUFNOM sur le lecteur courant. Voir aussi BDOS.

XSAVE

: XSAVE ( org fin ftype -- )

( versions ATMOS: )

RAM/ROM C051 C! 2DUP SWAP - 1+ C04F ! C054 ! C052 ! C0 C04D C! RAM/ROM ?WILDCARDS ?VALID 7C BDOS DISK-ERR? ;

( version TELESTRAT: )

52C ( FTYPE ) C! 52F ( FISALO ) ! 52D ( DESALO ) ! C0 ( SAVEU ) 528 ( VSALO0 ) C! 6B ( <XSAVE ) BDOS DISK-ERR? ;

Sauve (SAVEU) le contenu de la mémoire des adresses org à fin (incluses), dans un fichier de type ftype dont le nom doit se trouver dans BUFNOM (après utilisation de NAME! par exemple). Voir aussi BDOS et XLOAD.

XLOAD

: XLOAD ( vsalo0 -- )

( versions ATMOS: )

RAM/ROM C04D ! RAM/ROM 73 BDOS DISK-ERR? ;

( version TELESTRAT: )

528 ( VSALO0 ) ! 62 ( <XLOAD ) BDOS DISK-ERR? ;

Charge le contenu d'un fichier en mémoire; le nom du fichier doit être dans BUFNOM, comme pour XSAVE.

Voir aussi BDOS et NAME!.

FILE!

: FILE! ( -- )

( versions ATMOS: )

?DOS RAM/ROM FILE @ C300 C027 C@ + OVER 1+ 10 CMOVE C025 OVER 11 + 3 CMOVE C000 C@ SWAP C! RAM/ROM ;

( version TELESTRAT: )

?DOS BNK @ 0 BANK FILE @ C400 ( BUF3 ) 516 ( POSNMX ) C@ + OVER 1+ 10 CMOVE 514 ( POSNMP ) OVER 11 + 3 CMOVE 500 ( DRIVE ) C@ SWAP C! BANK ;

Rend courant le fichier pointé par le STRATSED (sur version TELESTRAT) ou le SEDORIC (sur versions ATMOS).

?FILE

: ?FILE <mot> ( -- )

FILENAME SEARCH NOT ABORT" fichier inexistant " ;

Cherche et rend courant le fichier dont le nom est spécifié après ?FILE dans le flot d'entrée. Voir aussi SEARCH.

OPEN-FILE

: OPEN-FILE ( -- )

FILE @ DUP C@ DRV DUP 0D + C@ OVER 0E + C@ C100 ( BUF1 ) RD# DISK-ERR? 0F + C@ 1- 4 / CAPACITY ! ;

Ouvre le fichier courant. Voir aussi RD#.

(DEFAULT)

: (DEFAULT) ( -- )

CR " *" NAME! SEARCH NOT ABORT" pas de fichier par defaut " FILE! OPEN-FILE ." fichier par defaut " .FILE ;

Mot utilisé par défaut par le mot d'exécution vectorisée DEFAULT. Ouvre le premier fichier d'extension par défaut. Voir aussi SEARCH et OPEN-FILE.

RECORD#

: RECORD# ( n -- piste secteur )

( versions ATMOS: )

RAM/ROM 2* DUP C10C + C@ SWAP C10D + C@ RAM/ROM ;

( version TELESTRAT: )

BNK @ SWAP 0 BANK 2* DUP C10C + C@ SWAP C10D + C@ ROT BANK ;

Délivre l'adresse physique d'un enregistrement STRATSED (sur version TELESTRAT) ou SEDORIC (sur versions ATMOS). Voir aussi FILE-READ et FILE-WRITE.

FILE-READ

: FILE-READ ( adr -- )

( versions ATMOS: )

FILE @ C@ DRV DUP 4 + @ SWAP @ DUP 1 CAPACITY @ ?RANGE 1- 4 * 4 0 DO 2DUP RECORD# ROT RD# DISK-ERR? 1+ SWAP 0100 + SWAP LOOP 2DROP ;

( version TELESTRAT: )

DUP 4 + @ SWAP @ DUP 1 CAPACITY @ ?RANGE 1- 4 * 4 0 DO 2DUP RECORD# ROT RD# DISK-ERR? 1+ SWAP 0100 + SWAP LOOP 2DROP ;

Mot utilisé par défaut par le mot d'exécution vectorisée READ-BLOCK en STRATSED (sur version TELESTRAT) ou en SEDORIC (sur versions ATMOS). Voir aussi RD# et RECORD#.

FILE-WRITE

: FILE-WRITE ( adr -- )

( versions ATMOS: )

FILE @ C@ DRV DUP 4 + @ SWAP @ DUP 1 CAPACITY @ ?RANGE 1- 4 * 4 0 DO 2DUP RECORD# ROT WR# DISK-ERR? 1+ SWAP 0100 + SWAP LOOP 2DROP ;

( version TELESTRAT: )

DUP 4 + @ SWAP @ DUP 1 CAPACITY @ ?RANGE 1- 4 * 4 0 DO 2DUP RECORD# ROT WR# DISK-ERR? 1+ SWAP 0100 + SWAP LOOP 2DROP ;

Mot utilisé par défaut par le mot d'exécution vectorisée WRITE-BLOCK en STRATSED (sur version TELESTRAT) ou en SEDORIC (sur versions ATMOS). Voir aussi WR# et RECORD#.

RDM-FILE

: RDM-FILE ( -- )

['] RDBLOCK IS READ-BLOCK ['] WRBLOCK IS WRITE-BLOCK FILE OFF 78 CAPACITY ! ;

Configure en accès direct de secteur. Voir aussi RDBLOCK et WRBLOCK.

DOS-FILE

: DOS-FILE ( -- )

['] FILE-READ IS READ-BLOCK ['] FILE-WRITE IS WRITE-BLOCK FCB FILE ! ;

Configure en STRATSED (sur version TELESTRAT) ou en SEDORIC (sur versions ATMOS). Voir aussi FILE-READ et FILE-WRITE.

FCB1

VARIABLE FCB1 ( -- adr )

12 ALLOT

FCB1 14 BLANK

Tableau pointant sur le bloc de contrôle de fichier utilisé par défaut. Une zone de 20 octets est réservée sur les versions pour ORIC. Voir aussi FCB.

(FROM)

: (FROM) ( -- )

FCB FCB1 B/FCB CMOVE ;

Transfert FCB -> FCB1. Voir aussi (TO).

(TO)

: (TO) ( -- )

FCB1 FCB B/FCB CMOVE ;

Transfert FCB1 -> FCB. Voir aussi (FROM).

CREATE-FILE

: CREATE-FILE <mot> ( n -- )

( versions ATMOS: )

1 ?ENOUGH DUP (FROM) FILENAME SEARCH ABORT" fichier existant" DUP 1 1E ?RANGE EMPTY-BUFFERS 400 * 4FF ( ORIGIN-1 ) + 500 ( ORIGIN ) SWAP 40 XSAVE FILE! OPEN-FILE 1+ 1 DO I CLEAR LOOP FLUSH (TO) OPEN-FILE ;

( version TELESTRAT: )

1 ?ENOUGH DUP (FROM) FILENAME SEARCH ABORT" fichier existant" DUP 1 1E ?RANGE EMPTY-BUFFERS 400 * 8FE ( ORIGIN-2 ) + 900 ( ORIGIN ) SWAP 40 XSAVE FILE! OPEN-FILE 1+ 1 DO I CLEAR LOOP FLUSH (TO) OPEN-FILE ;

Définition d'un fichier de blocs écran de n blocs de longueur et nommé <mot>. Par convention, le nom de fichier est suivi de l'extension .FTH.

Exemple:

20 CREATE-FILE CPU6502.FTH

crée un fichier de 20 blocs nommé CPU6502.FTH sur le disque actif.

Par la suite, pour réouvrir le même fichier lors d'une prochaine session de travail sous FORTH, il suffira de taper: OPEN CPU6502.FTH.

.NAME

: .NAME ( -- )

( versions ATMOS: )

CR RAM/ROM C300 C027 C@ + DUP PAD 9 CMOVE RAM/ROM PAD 9 TYPE ." ." RAM/ROM DUP 9 + PAD 3 CMOVE 0E + C@ 1- 4 / RAM/ROM PAD 3 TYPE 4 .R ." .K" ;

( version TELESTRAT: )

BNK @ 0 BANK CR C400 ( BUF3 ) 516 ( POSNMX ) C@ + DUP 9 TYPE ." ." DUP 9 + 3 TYPE 0E + C@ 1- 4 / 4 .R ." .K" BANK ;

Est utilisé par DIR pour afficher sur l'écran le catalogue de la disquette courante.

(.FILE)

: (.FILE) ( -- )

( versions ATMOS: )

FILE @ ?DUP IF DUP C@ ASCII A + EMIT ASCII - EMIT DUP 1+ 9 -TRAILING TYPE ." ." 0A + 3 TYPE ." / " THEN ;

( version TELESTRAT: )

FILE @ ?DUP IF DUP C@ ASCII A + EMIT ASCII - EMIT DUP 1+ 9 -TRAILING TYPE ." ." 0A + 3 TYPE SPACE ." / " THEN ;

Mot utilisé par défaut par le mot d'exécution vectorisée .FILE; affiche le nom du fichier courant. Voir aussi FILE.

OPEN

: OPEN <mot> ( -- )

?FILE FILE! OPEN-FILE ;

Ouverture d'un fichier déjà existant et résidant sur le disque actif.

TAKE

: TAKE <mot> ( -- )

(FROM) OPEN EMPTY-BUFFERS 1 LOAD FLUSH (TO) OPEN-FILE ;

Charge un fichier-package et revient au fichier courant. Voir aussi LOAD et THRU.

CAT

: CAT ( -- )

.FILE 1 CAPACITY @ INDEX ;

Affiche l'index du fichier courant. Voir aussi INDEX.

DIR

: DIR (<masque>) ( -- )

FILENAME SEARCH IF .NAME BEGIN SEARCH- ?STOP NOT AND WHILE .NAME REPEAT THEN CR CR .DRV ;

( version TELESTRAT: )

' DIR >LINK SWAP ! HERE SWAP ! HERE SWAP !

Affiche le contenu du disque actif, toutes extensions confondues par défaut. Il est possible de spécifier un masque tout comme en BASIC (sur versions ATMOS, HYPER-BASIC ou TELE-ASS sur version TELESTRAT). Par convention, les fichiers contenant les blocs FORTH sont définis avec l'extension .FTH.

VERSION

: VERSION ( -- adr cnt )

" V3.1 KERNEL " ;

Versions ATMOS. Retourne la chaîne de caractères explicite spécifiant la version en cours. Voir aussi HELLO.

(TERMINAL)

: (TERMINAL) ( -- )

504 ( ORIGIN+4 ) 1B ! STATLINE 23 BLANK 0A 26A C! QWERTY CR VERSION TYPE RAM/ROM " FTH" DROP EXT CMOVE SPBDOS C01D ! RAM/ROM FCB FILE ! DEFAULT ;

' (TERMINAL) >LINK SWAP ! HERE SWAP ! HERE SWAP !

Versions ATMOS. Vecteur standard de TERMINAL.


Previous Next Table of Contents