	UN INTERPRETEUR FORTH EN GFA (3)
	********************************

	Voici la suite du programme. Aujourd'hui nous allons crer nos
propres mots et multiplier ainsi les possibilits du FORTH. Comme tout
bon langage, il va sans dire que l'appel devra etre rcursif: un
exemple en fin d'article.

MODIFICATIONS GENERALES
-----------------------

	Un nouveau tableau fait son apparition: DEFI$. Chaque mot (on
dirait procedure ou fonction dans un autre langage) dfini par
l'utilisateur aura dans le tableau DEFI$() sa dfinition (l encore,
on parlerait plus volontiers du corps de la procdure ou de la
fonction). Modifiez donc ainsi la ligne de dimension des tableaux:

DIM pile%(100),retour%(100),mot$(100),defi$(100)

	Quelques ordres supplmentaires ont t ajouts:
	: pour crer des mots
	vlist pour la liste des mots
	." pour afficher une chaine
	mod pour le reste d'une division
	over un nouveau mouvement de pile
	Voici les nouvelles lignes de DATA:

DATA +,-,*,/,.,dup,swap,drop,system,ndo,nloop,timer,cr
DATA >,<,=,<>,if,else,then,:,vlist,.",mod,over
DATA "---"

CREATION D'UN MOT
-----------------

	En forth, la syntaxe est simple:

	: XXX bla bla bla ;

	La dfinition commence par deux points, ensuite XXX est le nom
du nouveau mot. Tout le blabla jusqu'au point virgule suivant
correspond  la dfinition. Ainsi:

	: bis 2 * ;

	Cette ligne cre le mot "bis" qui devient un quivalent de "2
*". C'est a dire que le mot "bis" multiplie par deux le sommet de la
pile. Les deux points qui initialisent une cration sont associs  la
procdure "cree":

PROCEDURE cree
  GOSUB motsuivant
  IF finligne!=FALSE
    INC o2%
    mot$(o%+o2%)=mot$
    i%=INSTR(strptr%,b$,";")
    defi$(o2%)=MID$(b$,strptr%,i%-strptr%)
    strptr%=i%
  ENDIF
RETURN

	Procdure simple: motsuivant nous renvoit XXX, nous
incrmentons o2% qui contient le nombre de mots crs par
l'utilisateur (zro en dbut de programme). La chaine XXX est
conserve dans le tableau MOT$() comme un nouvel ordre et, aprs avoir
repr le point virgule dans la chaine, la dfinition de XXX est
range dans DEFI$(). On met  jour STRPTR% puisqu'il faut sauter la
dfinition.

INTERPRETATION D'UN MOT UTILISATEUR
-----------------------------------

	Une nouvelle fois, la procdure INTERPRETE est modifie pour
s'adapter aux nouvelles exigences. D'abord la ligne ON GOSUB s'est
allonge puisqu'elle contient en plus:
	creer associ au mot (:)
	vlist associ au mot (vlist)
	aff associ au mot (.")
	reste associ au mot (mod)
	over associ au mot (over)

	Mais surtout, remarquez les petites modifications de la boucle
FOR/NEXT de recherche du mot: l'indice va maintenant jusqu' o%+o2%
(c'est  dire les ordres de base plus ceux de l'utilisateur). En
sortie de cette boucle:
	si i%<=o%, c'est un ordre de base, on passe  ON GOSUB
	si i%<=o%+o2% c'est un mot utilisateur, on lance alors
l'interprtation de sa dfinition (qui dclanche fatalement un
finligne!=TRUE qu'on annule au retour).
	sinon, on considre que le mot est un nombre.

PROCEDURE interprete(b$)
  LOCAL strptr%
  b$=b$+" "
  strptr%=1
  finligne!=FALSE
  DO
    GOSUB motsuivant
    EXIT IF finligne!
    FOR i%=1 TO o%+o2%
      EXIT IF mot$=mot$(i%)
    NEXT i%
    IF i%<=o%
      ON i% GOSUB plus,moins,fois,divise,point,duplique,permute,jette,quitte,ndo,nloop,chrono,cr,sup,inf,egal,dif,si,sinon,ensuite,cree,vlist,aff,reste,over
    ELSE
      IF i%<=o%+o2%
        GOSUB interprete(defi$(i%-o%))
        finligne!=FALSE
      ELSE
        INC pileptr%
        pile%(pileptr%)=VAL(mot$)
      ENDIF
    ENDIF
    EXIT IF fin!
  LOOP
RETURN

	L'utilisation de LOCAL STRPTR% permet d'avoir un pointeur 
chaque chaine et d'assurer la rcursivit des appels de mots.

AJOUTS COMPLEMENTAIRES
----------------------

	En Forth, le mot vlist donne la liste des mots crs par
l'utilisateur. Au dpart, cette liste est vide (ce qu'on teste avec la
variable o2% nulle). Vous pouvez facilement le modifier pour qu'il
affiche galement la dfinition de chaque mot:

PROCEDURE vlist
  IF o2%
    FOR i%=1 TO o2%
      PRINT mot$(o%+i%);" ";
    NEXT i%
  ENDIF
RETURN

	Pour afficher une chaine de caractres, le Forth s'utilise
ainsi:

	." Texte  afficher"

	Remarquez l'espace obligatoire entre (.") et le premier
caractre du texte: c'est afin d'isoler (.") comme un mot  part
entire. La procdure "aff" qui lui est associe recherche le
guillemet final et affiche la chaine. STRPTR% est ensuite mis  jour:


PROCEDURE aff
  i%=INSTR(strptr%,b$,CHR$(34))
  PRINT MID$(b$,strptr%,i%-strptr%);
  strptr%=i%
RETURN

	La procdure "reste" est associe au mot "mod" qui donne le
reste de la division entire de deux nombres:

PROCEDURE reste
  i%=pile%(pileptr%)
  DEC pileptr%
  i%=pile%(pileptr%) MOD i%
  pile%(pileptr%)=i%
RETURN

	Le mot "over" permet de dupliquer le second lment de la pile
par dessus le premier (remarquez au passage que ce mouvement est
impossible  raliser avec de simples SWAP, DROP et DUP combins):

PROCEDURE over
  INC pileptr%
  pile%(pileptr%)=pile%(pileptr%-2)
RETURN

UN EXEMPLE RECURSIF
-------------------

	Il s'agit du calcul du PGCD (plus grand diviseur commun) de
deux nombres, indispensable  la simplification de fractions par
exemple. Voici la mthode pour 30 et 18:
	1) le reste de la division de 30 par 18 est 12
	2) 12 etant non nul, je dis que pgcd(30,18)=pgcd(18,12)
	3) le reste de la division de 18 par 12 est 6
	4) 6 tant non nul, je dis que pgcd(18,12)=pgcd(12,6)
	5) le reste de la division de 12 par 6 est 0
	6) 0 tant nul, le pgcd recherch est le dernier diviseur,
	c'est  dire 6.

	En effet, 6 est le plus grand diviseur commun  30 (5 fois 6)
et  18 (3 fois 6).

	Tapez alors ceci  l'invitation du miniforth:

	: pgcd swap over mod dup if pgcd else drop then ;

	Vous venez de crer le mot pgcd, vrifiez sa prsence  l'aide
de vlist. Ensuite, essayez-le:

	30 18 pgcd .

	Cette ligne doit aficher 6. Remarquez que pgcd s'appelle
lui-meme sans aucun problme: notre interprteur est bien rcursif. Si
vous dsirez que le mot affiche directement le rsultat, choisissez
plutot cette dfinition:

	: pgcd swap over mod dup if pgcd else drop ." PGCD=" . then ;

CONCLUSION
----------

	Me voil rendu  la fin de cette srie. Le but n'tait pas de
vous fournir un programme clfs en main mais de vous montrer les bases
d'un interprteur extensible.
	Sachez d'ores et dj que cette srie a donn des ides:
Emmanuel Baranger, dans une prochaine version, compte agrmenter
EB_MODEL d'un petit interprteur ddi  certaines fonctions
particulires comme la copie multiple rendant cette opration encore
plus puissante, plus souple et surtout automatisable (un mot cr
devient tout betement une macro!).

	Bonne programmation  tous,

	Guillaume Tello
	gtello@wanadoo.fr



