PiF 4 | <terug> |
Het woord SCAN hebben we nodig voor "Menu's" in deel 2 van deze PiF.
Hoewel SCAN geen standaard Forthwoord is, heeft iedere Forth wel zo'n functie (in machinetaal). Die functie is namelijk nodig voor het lezen van de inputstroom. Als je geluk hebt, kent je Forth SCAN als los woord, als je pech hebt bestaat de functie alleen als onderdeel van een complexer woord waardoor je hem niet apart aan kunt spreken.
SCAN zoekt in de string 'a1,n1' naar de plek waar het karakter 'ch' voor de eerste keer voorkomt. SCAN kapt het stuk string weg dat voorafgaat aan het gevonden karakter. De reststring 'a2,n2' begint dus met karakter 'ch', behalve als 'n2' nul is, want dat betekent dat 'ch' niet gevonden is.
Voorbeelden:
S" Forth-gg" CHAR F SCAN TYPE [rtn] Forth-gg OK S" Forth-gg" CHAR g SCAN TYPE [rtn] gg OK S" Forth-gg" CHAR h SCAN TYPE [rtn] h-gg OK S" Forth-gg" CHAR i SCAN TYPE [rtn] OK 1000 500 55 SCAN DUMP [RTN] ...In het laatste voorbeeld hangt het resultaat natuurlijk af van de inhoud van [1000,1500).
Controleer of jouw Forth SCAN kent en of het net zo werkt als hier beschreven.
Hier volgen een paar SCAN definities om het gebruik van WHILE te demonstreren.
: scan1 ( a1 n1 ch -- a2 n2 ) \ n is unsigned >r \ a1 n1 r: ch begin dup \ Nog meer? while over c@ r@ <> \ Niet gevonden? while 1 /string \ Volgende positie again then then r> drop ;De laatste THEN hoort bij de eerste WHILE.
: scan2 ( a1 n1 ch -- a2 n2 ) \ n is unsigned >r over + swap \ Eindadres Beginadres begin 2dup - \ Nog meer? while count r@ = \ Gevonden? until 1- \ Laatste COUNT terugdraaien then tuck - \ a2 n2 r> drop ;Als WHILE een verschil van nul aantreft, springt hij naar THEN.
Wat gebeurt er als 'n1' nul is?
Wat zal er gebeuren als 'n1' gelijk aan -1 is?
Welke van de twee definities is de beste?
REPEAT is gelijk aan een AGAIN gevolgd door een THEN.
We gebruiken straks
: -positie ( ch a n -- -pos ) rot scan nip ;
Wat stelt die '-pos' voor?
\ ----- RISP - Windrichtingen in het Spaans decimal \ ----- Algemene menu tools ----- : hoofdletter ( ch -- CH ) dup [char] a - 26 u< bl and xor ; : -positie ( ch a n -- -pos ) rot scan nip ; : doexe does> ( index -- ) swap cells + @ execute ; \ ----- Menu-specifieke code ----- \ ( Commando) Token van de actie ( N) :noname ." Norte " ; ( O) :noname ." Este " ; ( Z) :noname ." Sur " ; ( W) :noname ." Oveste " ; create risp.exe , , , , \ 1a) doexe : risp ( -- ) cr ." Windrichtingen in het Spaans. N,O,Z,W: " begin key hoofdletter s" NOZW" -positie ?dup until 1- risp.exe ; \ 1b) \ ----- Einde -----
1a) In omgekeerde volgorde dus! Waarom gaat dit toch goed?
1b) Waarom 1- ?
Als je DOEXE uitvoert, komt DOES> in actie. DOES> zoekt het nieuwste woord op in het woordenboek (in dit geval RISP.EXE) en schrijft daar het adres in van de code die achter DOES> staat. Klaar. Die code zelf wordt op dat moment niet uitgevoerd!
DOES> vertelt aan een datastructuur wat het met zijn data moet doen. DOES> richt zich altijd tot het nieuwste woord in het woordenboek.
Wat doet RISP.EXE nu als je het aanroept?
Het is handig om de menu-specifieke code kort te houden,
want die moet je bij ieder menu opnieuw schrijven.
De algemene menu tools hoef je maar één keer te maken.
Met DOES> hevel je code over naar de algemene menu tools.
De voordelen hiervan merk je, als je meer menu's binnen een programma moet maken.
Groeten,
| <terug> |