This page (revision-21) was last changed on 03-Feb-2023 15:21 by Carsten Strotmann 

This page was created on 29-Jul-2010 13:57 by Carsten Strotmann

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
21 03-Feb-2023 15:21 27 KB Carsten Strotmann to previous

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 518 added 170 lines
Statt der Primitivabsicherung über MIN und MAX wird eine "out of range" Fehlerbehandlung namens __schimpfen__ an der Tabellenposition maxIndex +1 durchgeführt.
!Einsatzmöglichkeiten
Dieser letzte Teil der Ausführungen über die Möglichkeiten, eine CASE-Situation zu handhaben, greift Anregungen aus der Literatur (E. Floegel, FORTH Handbuch (S. 109) und W. Waigaard, Menus in FORTH, Elektroniker, 9/88 (S.109 ff.)) auf.
Dazu werden zwei Worte definiert:
* CLS - löscht den gesamten Bildschirm und
* CELLS - macht die Berechnung des Tabellenzugriffs deutlicher
{{{
: cls full page ;
: cells 2* ;
}}}
Das Inhaltliche und die tabellarische Struktur bleiben unverändert, lediglich die Behandlung einer "out of range" Situation wird diesmal mit __min__ und __max__ und zweimaligem Eintragen der Fehler-Routine __schimpfen__ verwirklicht.
{{{
Create: Handlung
schimpfen nehmen links links
rechts recht trinken schimpfen ;
\ Die Ausführung einer Liste nach Floegel 7/86
: auswählen ( addr n -- *cfa ) 2 arguments
swap 0 max \ out of range MIN
7 min \ out of range MAX
cells + ;
: auswerten ( n -- ) 1 arguments
Handlung auswählen perform ;
: .all ( -- )
8 0 DO cr I dup . auswerten 2 spaces LOOP ;
}}}
__AUSWÄHLEN__ übergibt bei gegebenem Vektor und gegebenem Index einen Zeiger auf die "code field address" (cfa) des entsprechenden Wortes. __AUSWERTEN__ führt das so ausgewählte Wort aus und __.ALL__ diente nur zur Kontrolle. Solch ein Wort, das angelegte Datenstrukturen auf dem Bildschirm darstellt, sollte in der Entwicklungsphase eines Programmes immer dabei sein.
Eine weitere M5glichkeit, Werte in einen Vektor einzutragen, hat Herr Floegel in seinem Buch "FORTH Handbuch" dargestellt:
{{{
Create Tabelle 8 cells allot
:DOES> ( i -- addr ) swap cells + ;
' schimpfen 0 Tabelle !
' nehmen 1 Tabelle !
' links dup 2 Tabelle !
3 Tabelle !
' rechts dup 4 Tabelle !
5 Tabelle !
' trinken 6 Tabelle !
' schimpfen 7 Tabelle !
: auswerten ( i -- ) 0 max 7 min Tabelle perform ;
: .action ( i -- )
Tabelle @ >name bright .name normal ;
: .Tabelle ( -- ) cr 8 0 DO cr I .action LOOP ;
}}}
Hier besteht mit __.ACTION__ und __.TABELLE__ die Möglichkeit, sich den Vektor darstellen zu lassen. In ähnlicher Weise werden auch im Kommandozeilen-Editor CED die neuen Aktionen in die Eingabe-Vektoren eingetragen.
Eine geringfügige Modifikation aus "W. Waigaard, Menus in FORTH" soll die VerknQpfung eines Vektors von Worten und einer Menü-Option zeigen:
{{{
Create function
] noop noop noop noop
noop noop noop noop [
:DOES> ( i -- addr )
swap 0 max 7 min cells + ;
}}}
__function__ ist ein execution vector, der mit __NOOP__ vorbesetzt ist. Zur Laufzeit liefert er die Adresse des indizierten Elementes zurück.
{{{
: .action ( i addr -- )
@ >name bright .name normal ;
}}}
__.WORD__ gibt den Namen eines Wortes aus, dessen CFA in eine Adresse eingetragen wurde.
{{{
: option ( i -- )
R>
dup 2+ >R \ i *w.addr
@ \ i w.addr
stash swap function ! \ i w.addr i addr
function .action ; \ i addr
}}}
__option__ holt die Adresse des auf __option__ folgenden Wortes. Das Wort soll nicht ausgeführt werden, sondern das nachfolgende. Nur der Pointer auf das Wort soll ausgewertet werden. Nach dem übergebenen Index wird der Pointer in __function__ eingetragen. Der Name des so eingetragenen Wortes wird angezeigt!
{{{
\ Menü jrp 06feb89
: Menue
0 option schimpfen
1 option nehmen
2 option links
3 option links
4 option rechts
5 option rechts
6 option trinken
7 option schimpfen ;
}}}
Wenn das Wort __MENUE__ aufgerufen wird, werden nicht nur die Optionen in die Tabelle eingetragen, sondern auch namentlich auf dem Bildschirm dargestellt. Diese Technik bietet sich für eine Menüzeile an fester Bildschirmposition an, ähnlich der Statuszeile des volksFORTH. Zum Ändern solcher Menüpunkte bieten sich die Funktionstasten an:
''MS-DOS''
{{{
: fkey ( -- )
key &58 + abs function perform ;
}}}
FKEY liefert beim Druck einer Funktionstaste einen Wert von -59 bis -68 zu­rück. Dieser wird für 10 Funktionstasten in den Bereich von -1 bis -10 skaliert und der Absolutwert gebildet.
!!!Rekursion
Bevor die Technik der Rekursion für das volksFORTH dargestellt wird, soll ein anderes Wort __.LASTNAME__ zeigen, daß das Wort __LAST__ mit dem in der Literatur oft anzutreffenden __LATEST__ identisch ist: Beide Worte liefern die "name field address" (nfa) des zuletzt definierten Wortes im CURRENT-Vokabular. Das Wort __LAST'__ dagegen liefert die "code field address" (cfa) des zuletzt definierten Wortes.
{{{
: .lastname last @ .name ;
}}}
Die Rekursion ist eine Technik, bei der ein Wort sich immer wieder selbst aufruft. Eines der bekannten Beispiele dafür ist die Berechnung der Fakultät einer positiven ganzen Zahl. Hierbei ergibt sich n! aus dem Produkt aller ihrer Vorgänger.
Im volksFORTH ist der Selbstaufruf eines Wortes durch __RECURSIVE__ gekennzeichnet, so daß sich ein Programm zur Fakultätsberechnung wie folgt präsentiert:
{{{
: fakultät ( +n -- n! )
recursive
dup 0< IF drop ." keine negativen Zahlen! " exit
THEN
?dup 0= IF 1 \ spezialfall 0
ELSE dup 1- fakultät *
THEN ;
cr 4 fakultät .
cr 5 fakultät .
cr 6 fakultät .
}}}
Allerdings findet sich — vor allem in der fig-FORTH-Literatur — ein Wort __MYSELF__, das mit dem in FORTH83-Umgebungen anzutreffenden __RECURSE__ identisch ist. Da auch diese Konstruktion, bei der MYSELF/RECURSE als Platshalter für den Wortnamen dienen, gerne eingesetzt wird, werden die möglichen Definitionen und eine weitere Form von FAKULTÄT gezeigt:
{{{
: myself last @ name> , ; immediate
: myself last' , ; immediate
: recurse [compile] myself ; immediate
' myself Alias recurse immediate
: fakultät ( +n -- n! )
dup 0< IF ." keine negativen Zahlen erlaubt!"
ELSE ?dup 0= IF 1
ELSE dup 1- myself *
THEN
THEN ;
}}}
Bei der Verwendung von __RECURSE__ wird lediglich __MYSELF__ dadurch ersetzt:
{{{
...
ELSE ?dup 0= IF 1
ELSE dup 1- recurse *
THEN
THEN ;
...
}}}