Dieser Artikel ist das Ende einer Reihe von eForth-Artikeln auf einem programmierbaren Taschenrechner. Beginnen Sie hier .Befehle der Eingabesprache "Electronics MK-161" belegen nur die Hälfte der Datei eForth0.mkl. Die zweite Hälfte ist mit Tabellen besetzt, deren Entwicklung nicht weniger schwierig war als das Schreiben des algorithmischen Teils des Übersetzers. Versuchen wir herauszufinden, wie diese Tabellen verwendet werden.

Professor Wirth lehrt, dass „Programmieren im Kleinen“ aus der Entwicklung von zwei gleich wichtigen Komponenten besteht - Algorithmen und Datenstrukturen.
Wir haben bereits eine eForth-Datenstruktur gefunden. Dies ist der Körper von VCA (High-Level-Wörtern), der sich im Byte-Speicher befindet. Vier Handler interpretieren die Parameterfelder „ihres eigenen“ VCA unterschiedlich:
.DB DOVAR ; .DB … ; .DB DOCON ; .DW _ ; .DB DOCONM ; .DW _ ; .DB DOLST ; .DW 1, 2,… EXITT ;
Die folgende relativ einfache Datenstruktur ist mit TYPE "Standardnachrichten" verknüpft.
Alle eForth-Nachrichten werden nummeriert und in den billigen Programmspeicher übertragen. Wenn das Wort TYPE einen einzelnen Buchstaben druckt, kann sein Code die Nummer einer solchen Nachricht von 0 bis 7 sein.
; TYPE .BASE tblTYPE: .DBB str7,str6, str5, str4, str3, str2, str1, str0
In der erweiterten MK-Sprache legt der Pseudobefehl .BASE die "Basis" für den Befehl .DBB fest, der die Zeilenversätze str7, str6 nacheinander in Bytes platziert relativ zum Basislabel tblTYPE. Durch Hinzufügen von Zahlen von 0 bis 7 zur Tabellenadresse kann dieser Offset daraus gelesen werden. Wenn wir den gefundenen Offset zu tblTYPE hinzufügen, erhalten wir die Adresse der gewünschten Zeile.
Das erste Byte der Zeichenfolge enthält seine Länge. eForth nutzt solche Zähllinien in großem Umfang.
Wir sind auch auf die Tabelle tblTokens gestoßen, in der die Code-Adressen aller 208 eingebetteten Wörter aufgelistet sind. Wenn das Wort nicht primitiv ist, enthält die Tabelle 0. Wenn Sie zur Adresse 0 wechseln, wird eForth mit einem Quietschen neu gestartet.
Die Tabelle tblNames wurde ebenfalls erwähnt und bezog sich auf die Namen derselben 208 Wörter. Diese Namen in Form von Zählzeilen werden im gleichen "Gummi" -Programmspeicher gespeichert. Die Tabelle tblNames selbst ist nicht verfügbar, während eForth ausgeführt wird, aber die darin enthaltenen Informationen gehen nicht verloren. Zur Kompilierungszeit überträgt eForth.f die Adresse der Namen an eine bequemere Datenstruktur, die im Dezimalspeicher gespeichert ist (siehe 2).
Ich sprach auch über tblCHPUT, eine assoziative Tabelle von Steuercodes, wenn ein Buchstabe auf dem Bildschirm eines Taschenrechners angezeigt wird. Weitere sieben Tabellen, von tblKeyNum bis tblKeyRusF, übersetzen den Code einer in verschiedenen Tastaturmodi gedrückten Taste in einen 8-Bit-Buchstabencode. Die Adresse des für den aktiven Tastaturmodus verantwortlichen Unterprogramms befindet sich im Dezimalregister ptrKbdInt.
Insgesamt blieb nur eine Datenstruktur in der Datei eForth0.mkl nicht zusammengesetzt. Dies sind Namenserkennungstabellen. Lassen wir sie nach dem Hauptgericht zum Nachtisch (siehe 5) - zwei Überschriften-Tabellen, die im Dezimalspeicher gespeichert sind. Zuerst werden wir uns mit Werkzeugen ausrüsten, um diese Überschriften zu „stopfen“.
1. Arbeiten Sie mit Überschriften: HEAD! und HEAD @
HEAD! ( xt nfa r -- ) r, xt nfa. HEAD@ ( r -- xt nfa lex ) r, xt, nfa .
Ein Dezimalregister MK-161 kann 12 Dezimalstellen speichern. eForth verwendet dieses Register, um drei kleine Zahlen von jeweils 0 bis 9999 zu speichern. Die
drei „Felder“ zum Speichern dieser Zahlen heißen A, B und C: AAAABBBBCCCC. Das Dezimalzeichen bezieht sich nur auf Feld A.
Das HEAD @ -Primitiv erhält die Registernummer und teilt die Nummer von dort in Felder auf, und HEAD! sammelt Felder in einer langen Anzahl und schreibt das resultierende "Monster" in das angegebene Register. Aber es gibt Nuancen.
Die „Dezimalüberschrift“ des Wortes enthält im Feld A die Adresse seines Namens (nfa). Wenn diese Adresse negativ ist, wird der Name im Programmspeicher gespeichert. Feld B enthält das Wort Token (xt). Feld C wird als Lexikon bezeichnet. Es speichert das IMMEDIATE-Bit und ein Zeichen dafür, dass das Wort nur zur Kompilierung bestimmt ist.
HEAD @ teilt den Header in Teile. Am oberen Rand des Stapels befindet sich das Lexikonfeld C, darunter das Namensfeld A. Das Feld B, in dem das Token normalerweise gespeichert ist, befindet sich ganz unten.
KOPF! setzt Feld C zurück.
2. Inline-Überschriften

Die Überschriften der 208 integrierten Wörter (0 bis 207) sind in der richtigen Reihenfolge angeordnet, beginnend mit R44. Feld A enthält immer eine negative Zahl, da die Namen dieser Wörter im Programmspeicher fest codiert sind.
Die Felder B und C können bearbeitet werden. Daher kann der Benutzer die integrierten Wörter neu definieren und daraus das SOFORTIGE machen, das er benötigt (siehe 4).
3. Benutzerüberschriften

Das Arbeiten mit nur 208 vordefinierten Namen spart Byte-Speicher, ist jedoch ungewöhnlich langweilig. Aus diesem Grund habe ich eine andere Datenstruktur entwickelt, bei der die Fantasie bei der Auswahl eines Namens auf nur 32 Buchstaben beschränkt ist. Diese Struktur besteht aus 32
Listen , von denen jede für Benutzerwörter einer bestimmten Länge verantwortlich ist. Jede dieser 32 Listen hat eine persönliche Überschrift. Die Listen selbst springen über den Dezimalspeicher, aber ihre Header werden immer in R301 ... R332 gespeichert.
Das Sortieren von Wörtern nach Namenslänge ist ein wichtiges Highlight von 161eForth. Durch das Sortieren wird die Anzahl der Vergleiche bei der Suche nach einem Wort anhand seines Namens erheblich reduziert, wodurch die Kompilierung beschleunigt wird. Wer braucht Hash-Funktionen, wenn jeder Name eine bekannte Länge hat?
Der Einfachheit halber hat die
Überschrift der Liste dieselbe Struktur mit den Feldern A, B und C wie die Überschrift des Wortes. Der Zweck dieser Felder ist unterschiedlich. Feld A enthält die Nummer des ersten Registers in der Liste. Feld B enthält die Anzahl der Register, die der Liste zur Verfügung gestellt werden. Feld C speichert die Anzahl der Wörter, deren Überschriften bereits in der Liste enthalten sind.
Zu Beginn der Arbeit sind die Felder C gleich Null, Wörter fehlen in allen Listen. Die Felder B sind 2, jede Liste erhält zunächst ein paar Register. Felder A geben Blöcke von 2 Registern an, die mit R333 beginnen.
Jede Liste enthält Überschriften von Wörtern. Wir haben sie bereits zerlegt (siehe 1). Hier ist die Adresse des Namens (nfa) möglicherweise positiv und zeigt auf die Zähllinie, die traditionell vor dem Körper des VCA gespeichert ist. Das Token in Feld B ist auch die Adresse des Codefelds (cfa), das unmittelbar nach diesem Namen in den Binärspeicher gelangt. Es gibt eine Ausnahme:
Wenn das Wort bereits ermittelt wurde, zeigt Feld A auf den alten Namen. Warum die Zeichenfolge erneut speichern? Binärer Speicher ist teuer.
Wenn alle Register der Liste voll sind (B = C), bietet das Wort PUBLISH 5 weitere freie Stellen, wobei diese Datenstruktur an die richtige Stelle verschoben und die Links (A) in den Listenüberschriften angepasst werden.
4. Veröffentlichung eines neuen Wortes: WORK and PUBLISH
LAST ( -- a ) . WORK ( -- a ) . PUBLISH ( -- ) . $,n ( nfa -- ) , nfa. ?UNIQUE ( a -- a ) , .
Die für den MK-161 entwickelte Datenstruktur zum Speichern von Worttiteln erwies sich als praktisch und einfach in eForth zu integrieren. Wenn CREATE, CONSTANT oder: ein neues Wort erstellt, greifen sie auf das Systemwort $, n zu, um einen Titel für das Wort mit dem angegebenen Namen zu erstellen. $, n bezieht sich auf? EINZIGARTIG zur Verifizierung - erstellen wir ein neues Wort oder definieren wir das alte neu?
Wenn bereits ein gleichnamiges Wort vorhanden ist, warnt UNIQUE den Benutzer davor. Gleichzeitig wird die Adresse des neu definierten Headers in die LAST-Systemvariable eingetragen. Für ein neues Wort wird LAST auf Null zurückgesetzt.
In jedem Fall erstellt $, n einen neuen Header in der WORK-Variablen - es ist ein Dezimalregister, das 12 Bits des Headers speichern kann. Wenn der Name nicht gefunden wurde, wird er vor dem Codefeld in das Wörterbuch aufgenommen, wie dies in 86eForth und vielen anderen Forts der Fall ist.
Der MK-161 konnte auf ein „Kommunikationsfeld“ verzichten , dies spart auch Binärspeicher.
Das PUBLISH-Grundelement vervollständigt die Definition eines Wortes. Beim Kompilieren von Doppelpunktwörtern wird PUBLISH von; aufgerufen. Daher war das SMUDGE-Bit nicht erforderlich. Die Stelle, an der der Header von WORK kopiert wird, wird durch die Variable LAST bestimmt. Wenn LAST Null ist, wird in der entsprechenden Liste ein neuer Header erstellt (siehe 3). Ist die Liste vollständig? Dann wird PUBLISH 5 weitere Register hinzufügen, vier davon für die Zukunft.
Nach dem Ausführen von PUBLISH zeigt die Variable LAST immer auf den Titel des letzten Wortes. Dies hilft IMMEDIATE, seine Arbeit zu erledigen, indem das Lexikonfeld geändert wird.
5. (FIND) und Namenserkennungstabellen
(FIND) ( a -- r T | a F ) r, a. FIND ( a -- a F | xt 1 | xt -1) . 1, IMMEDIATE.
Ein Grundelement (FIND) verwaltet die Suche nach einem Wort anhand seines Namens. Zuerst sucht er nach einem Namen unter den eingebauten Wörtern mit zuvor bekannten Namen und überprüft dann die Liste der Benutzerwörter mit der gewünschten Namenslänge (siehe 3). Namenserkennungstabellen beschleunigen dieses „Erste“ erheblich. So funktionieren sie.
Zu Beginn (FIND) findet es im Array tblLen die Adresse der assoziativen Haupttabelle, in der bekannte Namen der erforderlichen Länge "vorbereitet" werden. In dieser Tabelle (FIND) wird nach dem ersten Zeichen des Namens gesucht. In den meisten Fällen können Sie so sofort die
Titelregisternummer des gesuchten Wortes ermitteln - anhand des ersten Buchstabens und der Länge.
Es kommt vor, dass mehrere Wörter gleicher Länge dieselben Anfangsbuchstaben haben. Anstelle der Registernummer (FIND) stößt es dann auf die Adresse der nächsten assoziativen Tabelle (die gelesene Nummer ist 300 oder mehr) und die Suche wird mit dem zweiten Buchstaben fortgesetzt. Und so weiter, bis das Wort gefunden ist oder festgestellt wird, dass es kein solches Wort gibt.
Natürlich wird nach einer Übereinstimmung mit den ersten Buchstaben (FIND) der gesamte Name überprüft. Aber
Erkennungstabellen machten eForth schnell . In diesem Frühjahr habe ich viel Zeit in sie investiert, und jetzt sparen sie Suchzeit. Die "Schlüssel" in ihnen sind sogar alphabetisch sortiert. Entschuldigung, die Firmware des MK-161 hat darauf gespuckt.
Aus Kompatibilitätsgründen habe ich das Wort FIND aus Fort ANS [4] implementiert, das dem Grundelement „Black Work“ (FIND) vertraut. Das bereits betrachtete Wort? UNIQUE sucht auch nach seiner Argumentation durch (FIND).
6. Externer Dolmetscher
Buch [1] enthält eine ausführliche Beschreibung von eForth, einschließlich eines externen „Text“ -Dolmetschers. Er ist es, der den Quelltext in der Fort-Sprache ausführt oder kompiliert. In den letzten Jahrzehnten sind Unterschiede zu Textinterpreten anderer Fort-Dialekte ([2], [3]) aufgetreten, von denen es jedoch nur wenige gibt.
Unten sehen Sie ein Blockdiagramm eines Textinterpreters aus [1]. Seien Sie vorsichtig - dieser "Interpreter" hat einen Kompilierungsmodus! Das Wort $ COMPILE ist für das Kompilieren von Forte-Text in „genähten Code“ verantwortlich, dessen Ausführung wir im ersten Artikel ausführlich untersucht haben. Wenn stattdessen $ INTERPRET ausgeführt wird, werden die eingegebenen Wörter sofort ausgeführt - Interpretationsmodus. EVAL "berechnet" die gesamte eingegebene Zeichenfolge und ruft für jedes eingegebene Wort eines dieser beiden Wörter auf.

Nach dem Blockdiagramm entschlüsselt der Autor, welcher der Blöcke dies tut. Hier ist ihre Übersetzung. Blocknamen stimmen normalerweise mit eForth-Wortnamen überein. Das Wort NAME? fehlt in meiner Implementierung, wird es erfolgreich durch fast (FIND) ersetzt (siehe. 5).
Das Buch enthält auch den Quellcode für jedes eForth-Wort in der Windows-Version mit kurzen Erläuterungen. Was ist die Version für MK-161 anders, habe ich dir schon gesagt. Der Quellcode für meine Implementierung befindet sich im Archiv:
the-hacker.ru/2019/161eforth0.5b.zipAbschließend
möchte ich die Implementierung des Wortes
(PARSE) in der Sprache MK-161 erwähnen - unter Windows ist es VCA. Das Debuggen dauerte eine Woche,
beschleunigte jedoch die Kompilierung um die Hälfte . Das Wort (PARSE) erledigt die gesamte „Drecksarbeit“ für PARSE, um einzelne Wörter vom eingegebenen Textstrom zu isolieren.
Meine Ergänzungen zum externen Interpreter bestehen neben dem üblichen QUIT-Zyklus aus zwei Wörtern: dem bereits erwähnten TLOAD, der aus älteren Versionen von FILE stammt. Das Wort FILE übersetzt E / A in die Konsole, liest jedoch Zeilen zur Interpretation vom RS-232-Port. Nach erfolgreicher Verarbeitung jeder Zeile wird ein Buchstabe mit dem Code 11 an den Port ausgegeben. Die vom Computer heruntergeladene Datei sollte mit dem Wort QUIT enden.
Ich habe das Wort DATEI noch nicht getestet. Wenn jemand es braucht, teilen Sie Ihre Eindrücke.
Die Überprüfung der engen Stellen durch 161eForth ist beendet, aber das Fort ist ein unglaublich flexibles Werkzeug, das jeder Besitzer anpassen kann. Selbst wenn Sie alles gründlich herausgefunden haben, wird jemand irgendwo auf dem Planeten einen anderen Trick finden, der Sie überraschen kann.
Hier sind die letzten Worte des Autors eForth aus [1]:
Seit 26 Jahren habe ich eForth viele, viele Male umgeschrieben. Bei jedem Überspielen habe ich versucht, es einfacher und klarer zu machen. Jetzt in 86eForth v5.2 denke ich, dass ich die Richtigkeit erreicht habe und bin daher sehr glücklich.
Wie Einstein sagte:
Alles sollte so einfach wie möglich gemacht werden, aber nicht einfacher.
86eForth v5.2 noch einfacher machen, vielleicht kaputt machen oder als Programmierwerkzeug nicht nützlich sein.
Literatur
- Dr. Chen-Hanson Ting. eForth und Zen - 3. Ausgabe, 2017. Verfügbar auf Amazon Kindle.
- Baranov S.N., Nozdrunov N.R. Fort Sprache und ihre Umsetzung. - L.: Maschinenbau. Leningrad Abteilung, 1988.
- Semenov Yu.A. Programmierung in der FORT-Sprache. - M.: Radio und Kommunikation, 1991.
- ANS Vierter Standard. X3.215-1994. Übersetzung
- SP-Forth-Dokumentation .
- Offete Enterprises (Dr. Chen-Hanson Ting) , Autor von 86eForth v5.2, ist in englischer Sprache.
- Die Geschichte von Mikhail Pukhov "True Truth" mit dem Programm "Moonwalker-1", wo ich KDPV bekam und die sowjetischen Taschenrechner liebte.