FORTH
Úvod Výukové lekce  05 06 07 


   Lekce 6 - Definice, paměť, proměnné


   Forth je tvořen slovy a nová slova vytváří překladač z již existujících slov, která hledá ve slovníku. Tato slova byla nadefinována buď forthovským překladačem nebo jde o slova na nejnižší úrovni, tzv. primitiva, která jsou napsána např. v assembleru. Překladač se dá také nadefinovat, což dává Forthu velké možnosti. Překladač si pak určuje, jakým způsobem přečte zdrojový text, jaké se vytvoří datové struktury a jak se budou zpracovávat. 

Příklad 7: Na následujícím Obr. 7 jsou příklady v F-PC .

FPC06
Obr. 7

   Překladač pro definici nového slova (dvojtečka) čte slova oddělená mezerou, první bude jméno nového slova. Další slova hledá ve slovníku (pokud je nenalezne, ještě zjišťuje, zda jde o číslo) a vytváří strukturu, do které ukládá odkazy na tato slova. V každém slově je odkaz na strojový kód výkonné části překladače, který se spustí a slovo zpracuje. V primitivech je odkaz přímo na vlastní strojový kód. Definici slova ukončuje středník (návrat ze slova).
   : OBSAH  DUP  *  PI  *  100  /  ;    ( r -- pi*r^2/100 )

   Překladač pro definici proměnné (VARIABLE) přečte následující slovo, což bude jméno proměnné, rezervuje paměťové místo pro proměnnou a vytvoří datovou strukturu kam uvede adresu rezervované paměti. Po zavolání proměnné se na TOS ukládá adresa této paměti a my potom čteme obsah adresy, nebo na ni zapisujeme.
   variable VYSLEDEK         \ vytvoří proměnnou
   5 OBSAH VYSLEDEK !   \ spočítá obsah kruhu a ten uloží do proměnné VYSLEDEK
   VYSLEDEK @ .                \ zobrazí obsah proměnné VYSLEDEK

  Překladač pro definici konstanty (CONSTANT) pracuje podobně, ale neukládá do struktury adresu, ale přímo hodnotu konstanty, kterou si přečte při definici z  TOS. Po zavolání konstanty se na TOS ukládá hodnota konstanty.
   314 constant PI

  Na obrázku obr.8 je ukázka výpisu paměti procesoru ATmega. Nejdříve byla vytvořena konstanta PI, název je znázorněn zeleně, kde první byte je délka názvu (02). Tato délka leží na tzv. NFA - Name Field Adress. Modré 16-bitové číslo je link na začátek předchozího slova, tedy ukazuje na počet znaků názvu předchozího slova. Modré číslo leží na tzv. LFA - Link Field Adress, ukazuje na NFA předchozího slova. Toto spojení je nutné pro prohledávání slovníku. Růžové číslo $3896 ukazuje na výkonou část překladače, což je strojový kód, který v tomto případě následující číslo $013A (314) uloží na TOS. Leží na tzv. CFA - Code Field Adress.
  Dále byla nadefinována proměnná VYSLEDEK, délka názvu 08, na LFA je $1CBB, která ukazuje na NFA slova PI (na číslo 02). Na CFA je odkaz  na stejný překladač jako u konstanty PI, který následující číslo $01BB uloží na TOS. Je to adresa, na které je umístěna hodnota proměnné VYSLEDEK.
  Slovo OBSAH má délku názvu 05, na LFA je $1CC0, ukazuje na NFA slova VYSLEDEK (na číslo 08). Růžová adresa CFA ukazuje na jiný překladač, než v předešlých případech. Jde o překladač COLON (dvojtečka), který čte nasledující 16-bitové odkazy na CFA dalších slov. S velkou pravděpodobností tam najde odkaz zase na překladač COLON, který bude číst odkazy na CFAdalších slov a tak dál až k primitivu, kde na CFA bude odkaz na následující adresu se strojovým kódem. Šedé číslo je odkaz na slovo EXIT (středník), které ukončuje slovo a vrací běh slovu o úroveň výš.

Struktura
Obr.8: Výpis paměti





C!  ( x addr -- )


Vyhodnotí se příznak, pokud je true provedou se slova mezi IF .. THEN.
<flag> IF <při true jdi sem> THEN


Např.
: inc8  dup  8  <  if  1+  then ;
 \  přičte k TOS číslo 1, pokud na TOS je číslo menší než 8
7 inc8 .  9 inc8 .    zobrazí  8  9

C@  ( addr -- x ) Vyhodnotí se příznak, pokud je true provedou se slova mezi IF .. ELSE, jinak mezi ELSE .. THEN.
<flag> IF <při true jdi sem> ELSE <jinak při false sem> THEN


Např.
:  koule 5  =
   if
     25
  else
      0
  then  ;  \  pokud je na TOS číslo 5, ulož na TOS číslo 25, jinak 0
3 koule .  5 koule .    zobrazí  0  25

!  ( x addr -- ) Smyčka pro opakování slov mezi DO ... LOOP  od n1 do n2-1.
?DO navíc testuje n2=n1, pak se smyčka neprovede.
+LOOP  zvyšuje index smyčky o n3.
max  min   DO  <zde opakuj od min do max-1>  LOOP
max  min   DO   <zde opakuj od min do max-1, s krokem n>  +LOOP

LEAVE  předčasně ukončí smyčku.
UNLOOP  EXIT  předčasně ukončí smyčku a opustí vykonávané slovo.

Např.
: test1  5  0  do  i  .  loop ;   \ zobrazi 0 1 2 3 4
: test1z  -5  0  do  i  .  -1 +loop ;  \ zobrazí 0 -1 -2 -3 -4 -5
: test2  9  6  do  2  4  do  i  .  j  .  loop  loop  ;  \ zobrazi 2 6 3 6 2 7 3 7 2 8 3 8
: test3  31  3  do  i  .  3  +loop  ;   \ zobrazi nasobilku čísla 3,  3 6 9 12 15 18 21 24 27 30
: test4
   5  0  do
      i  2 =  if  i  leave then
   loop  .   
 \  při indexu 2 ukončí smyčku, vytiskne 2
   5  0  do
       i  3 =  if unloop exit then
   loop 3 . ;
 \  při indexu 3 ukončí smyčku a slovo test4, k tisku čísla 3 nedojde.

@  ( addr -- x )

 
Vybere případ, pro x = xi se provedou slova mezi OF ... ENDOF.
OF
porovna TOS a NOS, pokud se rovnají provedou se slova mezi OF ... ENDOF a skočí se na ENDCASE.
Pokud se nerovnají, zachová se hodnota x na NOS pro další porovnání a smaže se hodnota xi na TOS.

Např.
: testcase  ( x -- x )
   case
   3 of  1  endof
   4 of  2  endof
   5 of  9  endof
   drop 0
   endcase ;
 \  zmeni cislo 3 na 1, 4 na 2, 5 na 9, ostatni hodnoty na 0.
5 testcase .  6 testcase .    zobrazí  9  0

2!  ( d addr -- )
( x1 x2 addr -- )
Nekonečná smyčka, opakovaně provádí slova mezi BEGIN ... AGAIN.
BEGIN  <opakovaná slova> AGAIN


Např.
 : testESC1
    begin
       1  .  key  27  =  if  exit  then
    again  2  .  
;  \  při stisku klávesy zobrazí číslo jedna, při ESC opustí slovo testESC1, nezobrazí číslo dvě.

2@  ( addr -- d )
( addr -- x1 x2 )
Opakuj do splnění podmínky.
BEGIN <opakovaná slova flag> UNTIL
Slova se provedou alespoň jednou, pokud UNTIL na TOS najde TRUE, ukončí smyčku.


Např.
: testESC2
   begin
      1  .  key 27 =
   until  2  . ;  \  při stisku klávesy zobrazí číslo jedna, při ESC ukončí smyčku, zobrazí číslo dvě.

CREATE
( -- )


DOES>  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

:  ( -- )
Zavolá právě definované slovo.

;  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

:NONAME  ( -- )
Zavolá právě definované slovo.

CODE  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

;CODE  ( -- )
Zavolá právě definované slovo.

MARKER  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

CONSTANT  ( -- )
Zavolá právě definované slovo.

2CONSTANT  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

VARIABLE  ( -- )
Zavolá právě definované slovo.

2VARIABLE   ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

LITERAL  ( -- )
Zavolá právě definované slovo.

2LITERAL  ( -- )
Ukončí právě definované slovo. Ve smyčce DO ... LOOP mu musí předcházet slovo UNLOOP.

____________________________________________________________________________________________________________________
05.11.2008 - Luboš Pěkný, čerpáno z  X3J14 dpANS-6.  Podléhá autorskému zákonu, šíření povoleno jen s uvedením autora.