Merkmale der Implementierung der MSH-Sprache

Ich setze die Artikelserie über die Programmiersprache MSH fort. In einem früheren Artikel habe ich bereits die Spezifikation dieser Sprache beschrieben. Die Spezifikation enthüllt jedoch nicht alle Merkmale der Sprache. Ich möchte diese Lücke mit diesem Artikel schließen. Natürlich habe ich nicht alles beschrieben, aber im Grunde habe ich die Hauptmerkmale beschrieben. Wir werden den Rest auf bessere Zeiten verschieben.

Wenn das Bild der Sprache gerade Gestalt annimmt, scheint alles logisch und konsistent zu sein. Aber am Eingang zur Implementierung der Sprache gibt es Probleme, die durch die Wahl der einen oder anderen Strategie gelöst werden müssen. Nachdem der Sprachinterpreter bereit ist, können Sie sehen, wie er das eine oder andere Implementierungsproblem gelöst hat.

MSH-Programmiersprachenkonzepte


Inhaltsverzeichnis


Einführung 2
Organisation des Programms. 2
Laufzeit. 2
Datenverwaltung. 3
Datenlokalisierung. 3
Kurzschrift-Syntax. 5
Konstanten. 5
Merkmale einiger Teams. 5
Befehl CONSTANT. 5
XECUTE-Befehl. 6
Befehle KOPIEREN und BEWEGEN. 6
Ressourcensynchronisation. 7
Kurzform des Befehls SET. 8
Blockteams. 8
IF-Befehl. 8
Befehl CASE. 9
WHILE-Befehl. 10
Blockschleifeniteratoren. 10
NÄCHSTES Team. 11
Befehl ZURÜCK. 12
QUERY Team. 12
Nicht blockierte Befehle Datenbaum-Durchlaufbefehle. 12
NEXT1 Team. 12
Befehl ZURÜCK1. dreizehn
FRAGE Team1. 13
Programmausführungsverwaltung. 13
Parameter übergeben. 14
Ereignisbehandlung. 15
EVENTTRAP-Befehl. 15
Team EVENTDELETE. 16
EVENTCALL-Team. 16
EVENTWAIT-Team. 16
Vektoren. 16
64-Bit-Vektoren. 16
32-Bit-Vektoren. 17
16-Bit-Vektoren. 17
8-Bit-Vektoren. 17
Operationen. 17
Objekte. 18
Vererbung von Objekten. 19
Mit der Datei austauschen. 20
Fazit. zwanzig

Einführung


Die MSH-Sprache basiert auf den Konzepten der MUMPS-Sprache. MUMPS ist eine wenig bekannte Sprache, die im letzten Jahrhundert entwickelt wurde. Es wird jedoch weiterhin in Informationsanwendungen verwendet. Informationen zu dieser Sprache finden Sie im Internet. Es gibt funktionierende Implementierungen dieser Sprache und eine Community von Programmierern, die sie unterstützen. MUMPS werden in den USA und in Russland entwickelt. Außerdem wird es meines Wissens in Lateinamerika, Deutschland, Australien und China verwendet. Im Allgemeinen ist dieses lebendige Konzept der Sprache. Beim Treffen mit MUMPS fällt seine archaische Natur auf. Diese Entwicklung soll die Mängel beseitigen und gleichzeitig die Vorteile, die Einfachheit, die Konsistenz und die Datenorganisation bewahren.
Organisation des Programms.

Die Übersetzungseinheit ist das MSH-Sprachmodul. Das Modul beginnt mit den Standard-8-Bytes, die die Sprachversion identifizieren. Am Anfang der Zeile kann sich eine Beschriftung oder Leerzeichen befinden. Die Beschriftung endet mit einem „:“ und ist durch eine beliebige Anzahl von Leerzeichen vom Rest der Befehle getrennt. Zeilen bestehen aus Befehlen. Ein Zeichen für das Ende des Teams ist das Symbol „;“. Der Befehl ist durch Leerzeichen von den Argumenten getrennt. Der Fall der Zeichen spielt keine Rolle. Der Befehl kann mit Zeichen eines beliebigen Registers geschrieben werden. Darüber hinaus haben viele Teams eine Kurzform. Ein Befehl kann eine Bedingung für seine Ausführung haben. Wenn es eines gibt, folgt das Symbol "?" Dem Befehl ohne Leerzeichen und die Bedingung für die Ausführung dieses Befehls. Wenn die Bedingung zum Ausführen des Befehls nicht gleich 0 ist, wird der Befehl ausgeführt. Innerhalb der Bedingung sind Leerzeichen nicht zulässig, andernfalls werden sie als Trennzeichen zwischen dem Befehl und den Argumenten verarbeitet.

Zum Beispiel:

SET? [5]> 5 Val [1] = 25; // ist es richtig
SET? [2]> 5 Val [1] = 25; // Syntaxfehler
SET? ([1,2]> 5) Val [1] = 25; // Richtig, inside () Leerzeichen sind zulässig.

Argumente werden durch das Symbol "," getrennt. Innerhalb von Argumenten ist ein Leerzeichen kein Sonderzeichen und kann überall enthalten sein. Normalerweise kann ein Befehl eine beliebige Anzahl von Argumenten haben. Beschriftungen im Modul sind innerhalb des Moduls lokalisiert und müssen darin eindeutig sein, mit Ausnahme der Beschriftungen im Befehl CASE . Beschriftungen des in diesem Befehl lokalisierten CASE- Befehls sollten nur innerhalb dieses Befehls eindeutig sein und können Beschriftungen sowohl außerhalb dieses Befehls als auch in verschachtelten CASE- Befehlen duplizieren .

Laufzeit


Zur Laufzeit hat die Anwendung eine oder mehrere Aufgaben. Alle Aufgaben werden parallel ausgeführt. In jeder Aufgabe werden Programme nacheinander ausgeführt. Zu jedem Zeitpunkt wird nur ein Programmcode in der Task ausgeführt. Die Aufgabe endet mit dem Ende des zuletzt ausgeführten Programms. Die Hauptaufgabe wird von der Sprachlaufzeit gestartet. Die verbleibenden Jobs werden vom Befehl Job generiert .

Datenmanagement


Für diejenigen, die mit der MUMPS-Sprache vertraut sind, ist die Organisation der Daten in MSH ziemlich klar. Es gibt keine Beschreibung der Daten in MSH. Es gibt keine Datendeklaration. Daten können als Baum gespeichert werden. Der Zugriff auf die Baumknoten erfolgt über einen optionalen Namen und Index. Der Index ist in eckigen Klammern [] eingeschlossen. Der Name steht vor ihnen.

Zum Beispiel:

SET Pr [4,5, "rt"] = Is ["ty ^ 578"];
Hier sind Pr und Is die Namen der Bäume. 4,5, "rt" und "ty ^ 578" sind Knotenindizes.

Der Baum kann eine beliebige Anzahl von Ebenen haben, und dementsprechend hat der Index die entsprechende Anzahl von Feldern, die durch Kommas getrennt sind. Das Indexfeld kann einen beliebigen Wert vom Basistyp haben. Die Grundtypen in MSH sind Zahlen und Zeichenfolgen. Nur Knoten, zu denen die Aufzeichnung erstellt wurde, werden direkt im Baum gespeichert. Der Name, das Indexfeld und der Index selbst können ein Ausdruck sein. Nach der Berechnung kann der Name nur eine Kennung sein.

Die Daten können auch als fortlaufendes Array gespeichert werden. Ein Zugriff auf das Array-Element besteht dann aus einem optionalen Symbolnamen "$" und einem Index. Ein Index ist eine Ganzzahl. Der kleinste Array-Index ist 1. Der Name und der Index können Ausdrücke sein. Nach der Berechnung kann der Name nur ein Bezeichner und der Index eine Ganzzahl sein. Ein Array kann in beliebiger Reihenfolge ausgefüllt werden, aber wenn Sie geschrieben habenmc $ 1000 , dann wird ein mc- Array mit 1000 Elementen erstellt . Undefinierte Elemente enthalten keine Werte, sind jedoch vorhanden. Die Anzahl der Elemente im Array kann unter Bezugnahme auf das Nullelement dieses Arrays ermittelt werden.

Beispiel: mc $ 0 Die
Größe des Arrays kann geändert werden, indem eine neue Array-Länge in dieses Element geschrieben wird. Im allgemeinen Fall ist dies jedoch nicht erforderlich, da das Array automatisch erweitert wird.

Baumknoten und Array-Elemente enthalten Daten grundlegender Typen. Dies sind entweder Zeichenfolgen oder Zahlen. Wie Programmierdaten gespeichert werden, spielt keine Rolle. Die Speicherung von Datentypen und deren Manipulation liegt in der Verantwortung der Implementierung der MSH-Sprache.

Datenlokalisierung


MSH-Daten sind in globale und lokale Daten unterteilt. Sie unterscheiden sich in der Art des Namens. Globale Daten werden im Langzeitspeicher gespeichert und hängen nicht von der Lebensdauer der Anwendung ab. Sobald sie erstellt wurden, können sie von der Anwendung geändert werden und bleiben bestehen, bis die Anwendung sie mit dem Befehl KILL zerstört . Alle globalen Daten haben das Präfix "^" im Namen.

Der Zugriff auf globale Daten ist gleichzeitig über verschiedene Aufgaben möglich. Daher ist beim Zugriff auf Globals eine Synchronisierung erforderlich. Eine solche Synchronisation erfolgt immer automatisch. Der globale Deskriptor enthält immer ein Synchronisationsprimitiv, das den Zugriff auf das globale Deskriptor steuert. Wenn das Lesen des Globalen durch Lesen blockiert wird, während es in das Globale schreibt, wird es durch Schreiben blockiert. Es ist keine zusätzliche globale Synchronisation erforderlich. Zugriffe auf globale Arrays werden ebenfalls synchronisiert.

Zum Beispiel:

^ gl [87,9] - Zugriff auf den globalen Baumknoten.

^ glar $ 45 - Zugriff auf das Element des globalen Arrays.

Lokale Daten sind nur vorhanden, während die Anwendung ausgeführt wird. Der nächste Anwendungsstart kann nicht auf die lokalen Daten des vorherigen Starts zugreifen.

Der Umfang der lokalen Daten hängt von ihrem Typ ab. Es gibt drei Arten der Datenlokalisierung.

1. Lokale Programmdaten. Sie sind innerhalb des Programms lokalisiert und existieren vom Start des Programms bis zu seinem Abschluss. Wenn das Programm das Unterprogramm aufruft, werden neue Unterprogrammdaten erstellt und die lokalen Programmdaten innerhalb des Unterprogramms sind nicht sichtbar. Wenn Sie zum Programm zurückkehren, werden die lokalen Programmdaten wieder verfügbar. Lokale Programmdaten haben keinen Namen.

Zum Beispiel:

[7,9] - Zugriff auf den im Programm lokalisierten Knoten des Baums.

$ 5 - Zugriff auf ein Array-Element, das im Programm lokalisiert ist.

Es gibt eine Ausnahme. Ein Array von Parametern, die an das A $ -Programm übergeben werden, ist ebenfalls im Programm lokalisiert.

2. Lokale Anwendungsdaten. Sie sind in allen Aufgaben der Anwendung sichtbar. Sie können sie von jeder Aufgabe aus kontaktieren. Sie existieren von dem Moment an, in dem sie von einer Aufgabe in der Anwendung erstellt werden, bis die Anwendung abgeschlossen ist oder bis sie vom KILL- Team zerstört werden . Den Namen solcher Daten wird " % " vorangestellt . Diese Variablen sind gleichzeitig in verschiedenen Aufgaben verfügbar, sodass sie so synchron wie globale Variablen sind.

Beispiel:

% dapp [87.9] - Zugriff auf den in der Anwendung lokalisierten Knoten des Baums.

% dapp $ 45 - Zugriff auf ein Array-Element, das in der Anwendung lokalisiert ist.

3. Lokale Auftragsdaten. Sie sind innerhalb der Aufgabe lokalisiert und existieren von dem Moment an, in dem sie in einem Aufgabenprogramm erstellt wurden, bis die Aufgabe vom KILL- Team abgeschlossen oder zerstört wird . Diese Daten müssen einen Namen haben und dürfen nicht die Präfixe " ^ " und " % " enthalten. Die Ausnahme ist das Array von Programmparametern A $ , das innerhalb des Programms lokalisiert ist.

Beispiel:

djob [87,9] - Zugriff auf den Knoten des Baums, der innerhalb der Task lokalisiert ist.
djob $ 45 - Zugriff auf das im Job lokalisierte Element des Arrays.
Der Zugriff auf Variablen kann nur die hier aufgeführten Typen haben.

Kurzsyntax


Dieser Begriff hat keine Beziehung zu einem ähnlichen Begriff in der MUMPS-Sprache. Die abgekürzte Syntax in MSH bezieht sich entweder auf den gesamten Baum oder auf das gesamte Array. Es wird nur in getrennten Teams verwendet und wo es zulässig ist, wird es immer ausgehandelt. Ein Aufruf an den gesamten Baum besteht aus einem Namen und erforderlichen eckigen Klammern. Für den lokalen Programmbaum ist kein Name angegeben.
Zum Beispiel:
us [] - Zugriff auf den gesamten us-Baum.
[] - Zugriff auf den lokalen Programmbaum.

Der Zugriff auf das gesamte Array besteht aus dem Namen und dem erforderlichen Zeichen " $ ". Für das lokale Array des Programms wird kein Name angegeben.

Zum Beispiel:
us $ - Zugriff auf das gesamte us-Array.
$ - Zugriff auf das lokale Programmarray.

Konstanten


Grundlegende Datentypen können entweder numerisch oder als Zeichenfolge sein. Die numerische Form ist entweder eine Ganzzahl oder eine reelle Zahl bei Vorhandensein eines Dezimalpunkts. Die Basis der Zahlen ist 10. Sie können entweder positiv oder negativ sein.
Beispiel:
25, -4, 789.56, -9.3 Zeichenfolgenkonstanten

sind beliebige Zeichenfolgen. Wenn eine Konstante nur aus Buchstaben und Zahlen besteht, können Sie sie nicht in Anführungszeichen setzen, da sie nicht mit einer Variablen verwechselt werden kann. Wenn die Konstante andere Zeichen enthält, muss sie entweder in einfache oder doppelte Anführungszeichen gesetzt werden.
Zum Beispiel:
"rt @ tty # 123"
'14 "5 * 7" 89 \? '
125Dsv

Merkmale einiger Teams


STÄNDIGES Team


Sie können einer Konstante mit dem Befehl CONSTANT einen Namen geben . Dies sind Sendezeitnamen. Broadcast ersetzt sie durch ihre Werte. Zur Laufzeit existieren diese Namen nicht mehr. Daher können Sie einem Namen im Befehl CONSTANT keinen Ausdruck zuweisen. Der Wert muss genau eine Konstante sein. Die Namen der Konstanten müssen so gewählt werden, dass sie nicht ohne Anführungszeichen mit den Werten der im Programm angegebenen Konstanten übereinstimmen.

Zum Beispiel:
Konstante ioInOut = "/ini/par.ini>, maxIs=25;
Den Konstanten ioInOut und maxIs werden Werte zugewiesen. Weiter im Programm können diese Namen anstelle dieser Werte verwendet werden. Ständiges
TeamEs hat 2 Formen. In diesem Fall fehlt die rechte Seite der Gleichheit. Die Bedeutung dieses Teams ist unterschiedlich. Der Name ist der Name des Moduls, das die Konstanten enthält. Die Konstanten dieses Moduls werden in das aktuelle Modul exportiert. Die Modulimportkonstanten enthalten keine zusätzlichen Beschreibungen zum Import. Das Importmodul kann nur Konstanten und Programme enthalten.
Zum Beispiel:
CONSTANT sysCnsNet, usrCnsByx;
sysCnsNet und usrCnsByx sind Modulnamen, die Konstanten enthalten.
Beide Formen können als Argumente für einen einzelnen CONSTANT- Befehl auftreten .

XECUTE Team


Der XECUTE- Befehl ist ein ziemlich exotisches Team, aber er ist in der MUMPS-Sprache vorhanden. In anderen Programmiersprachen traf sie mich nur in JavaScript. Dort heißt es eval. Wenn dieser Befehl ausgeführt wird, wird der Ausdruck des Arguments dieses Befehls berechnet, und dann wird dieser Ausdruck in eine Zeichenfolge konvertiert, als MSH-Befehl interpretiert und ausgeführt.

Zum Beispiel:
XECUTE "SET $ 1 = 89;";
Infolgedessen erhält die Variable $ 1 den Wert 89 .
Dies ist ein primitives Beispiel. In dieser Form ist es kaum sinnvoll, diesen Befehl zu verwenden. Die Argumente für den Befehl XECUTE sind Ausdrücke, mit denen Sie zum Zeitpunkt der Programmausführung verschiedene MSH-Befehle generieren können.
Der Befehl wird im Kontext des Programms ausgeführt, in dem sich der Befehl befindet. Alle Programmressourcen stehen ihr zur Verfügung, einschließlich lokaler Programmdaten.

Befehle KOPIEREN und BEWEGEN


Der Befehl COPY ähnelt dem Befehl MERGE MUMPS. Diese Befehle kopieren den Quellknoten zusammen mit allen Nachkommen auf den Empfängerknoten. Das Argument dieser Befehle besteht aus zwei Feldern, die durch das Symbol " = " getrennt sind. Rechts von diesem Zeichen befindet sich der Quellknoten, links der Empfänger. Eine abgekürzte Verknüpfung ist als Knoten zulässig. In diesem Fall wird der gesamte Baum verwendet. Diese Befehle kopieren nicht nur die Nachkommen, sondern auch die Knoten selbst. Der Befehl COPY führt die Datenzusammenführung durch. Die Quelldaten werden ohne Reinigung auf den Empfänger kopiert. Die Quelle ändert sich nicht. MOVE Teamführt tatsächlich bewegte Daten aus. Zuvor wurde der Empfänger bereinigt, dann werden alle Nachkommen des Quellknotens kopiert und der Quellknoten mit allen seinen Nachkommen gelöscht.

Zum Beispiel:
// Knoten us [5,6] wird auf Knoten [1] kopiert
COPY [1] = us [5,6];
// Der gesamte US-Baum wird auf den Knoten verschoben. [8]
MOVE [8] = us [];
Diese Befehle können auch zum Kopieren von Arrays verwendet werden. In diesem Fall dürfen nur verkürzte Links als Quelle und Empfänger verwendet werden.
Die Programmargumente werden in das Array arg kopiert.
COPY arg $ = A $;
Sie können den Befehl MOVE verwenden, um sich zu bewegen.
MOVE a1 $ = b1 $;
Sie können beliebige Arrays kopieren und verschieben.

Ressourcensynchronisierung


Wenn Sie mehrere Aufgaben ausführen, müssen Sie auf gemeinsam genutzte Ressourcen zugreifen. Die Synchronisation erfolgt über Sperrbefehle. Synchronisationsbefehle selbst blockieren nichts. Hierbei handelt es sich um eine Reihe von Vereinbarungen, mit denen der Zugriff auf gemeinsam genutzte Ressourcen differenziert werden kann. Wenn die Sperrbefehle nicht für mehrere Jobs gemeinsam genutzt werden, erfolgt keine Zugriffssynchronisierung. Die Synchronisation basiert auf Sperrnamen. Diese Namen sind in der Anwendung lokalisiert und in allen Aufgaben gleich. In Schlössern wird das Konzept vieler Leser und jeweils nur eines Schriftstellers akzeptiert. Dementsprechend gibt es Lese- und Schreibsperren. LockR

Teamblockiert das Lesen von Namen. Die in ihren Argumenten aufgeführten Namen werden durch Lesen blockiert. Eine beliebige Anzahl von Aufgaben kann dieselben Namen blockieren, aber eine Aufgabe, die versucht hat, einen dieser Namen zu blockieren, wartet darauf, dass alle diese Namen entsperrt werden. Nach dem Erfassen des Schreibnamens kann kein Lesesperrbefehl ausgeführt werden, bis die Schreibsperre den Namen freigibt. Wenn das Sperren nicht möglich ist, wartet der Befehl auf die Freigabe des Namens.

Zum Beispiel:
LockR Name1, Name2, Name3;
Diese Namen werden durch Lesen blockiert. Eine andere Aufgabe kann diese Namen auch sperren, ohne darauf zu warten, dass sie entsperrt werden.

Befehl LockWblockiert Namen nach Datensatz. Die in ihren Argumenten aufgeführten Namen werden durch Aufzeichnung blockiert. Wenn die in den Argumenten aufgeführten Namen bereits durch einen Sperrbefehl blockiert sind, wartet dieser Befehl auf die Freigabe dieser Namen.
Zum Beispiel:
LockW Name1, Name2, Name3;
Diese Namen werden durch Datensatz gesperrt.
Der Befehl LockUn entsperrt diesen Namen. Wenn der Name durch mehrmaliges Lesen blockiert wird, müssen Sie die gleiche Anzahl entsperren.
Zum Beispiel:
LockUn Name1, Name2, Name3;
Die Standardfunktionen haben Analoga dieser Befehle mit einer Zeitüberschreitung.

Kurzform des SET-Befehls


Der Befehl SET hat eine abgekürzte Form. In diesem Fall fehlt die linke Seite der Gleichheit, ihre Rolle spielt die letzte im Ausdruck erwähnte Variable.
Zum Beispiel:
SET $ 1 = 2, $ 1 + 3;
Die Variable $ 1 wird gleich 5 .
Wenn der Ausdruck mehrere Variablen enthält, wird das Ergebnis der letzten Variablen zugewiesen.

Zum Beispiel:
SET $ 1 = 1, $ 2 = 2, $ 3 = 3, $ 1 + $ 2 + $ 3;
Die Variable $ 3 wird zu 1 + 2 + 3 = 6. Obwohl dieses Formular besser geeignet ist, nur in sehr einfachen Fällen zu verwenden, ähnlich wie im ersten Beispiel. Das zweite Beispiel dient nur zur Veranschaulichung der Funktionen dieser Form des SET- Befehls .

Teams blockieren


Blockbefehle bilden einen Befehlsblock und dienen gleichzeitig als Überschrift des Blocks. Jeder Blockbefehl muss einen eigenen END- Befehl haben , auch wenn der Block nur einen Befehl enthält.

IF-Team


Der IF- Befehl bildet einen Block, der ausgeführt wird, wenn die Bedingungen für die Ausführung dieses Befehls erfüllt sind. Dieser Befehl hat keine Argumente. Dieser Block kann ELSE- Befehle enthalten . Der Befehl ELSE hat keine Argumente. Außerhalb des IF- Blocks haben diese Befehle keine Bedeutung und können nicht angewendet werden. Wenn der IF- Block ELSE- Befehle enthält , wenn die Bedingung des IF- Befehls erfüllt ist, werden nur die Befehle hinter dem IF- Befehl bis zum nächsten ELSE- Befehl ausgeführt . ELSE Teamkann eine Ausführungsbedingung enthalten, dann werden im Falle der Wahrheit in dieser Bedingung nur Befehle ausgeführt, die sich nach diesem Befehl befinden, bis zum nächsten ELSE- Befehl oder END- Befehl . Ein IF- Block kann nur einen ELSE- Befehl ohne Bedingung für seine Ausführung enthalten und muss der letzte unter den ELSE- Befehlen sein .

Zum Beispiel:
IF? [6] <0;
SET y [1] = 1;
SONST? [6] <5;
SET y [1] = 2;
SONST? [6] <10;
SET y [1] = 3;
SONST SET y [1] = 4;
ENDE
Die Bedingung für die Ausführung dieses Befehls kann fehlen, dann wird dieser Block in jedem Fall ausgeführt. Obwohl es schwer vorstellbar ist, warum dies nützlich sein könnte.

CASE Team


Die Semantik dieses Befehls unterscheidet sich etwas von der Semantik der anderen MSH-Teams. Die Bedingung für die Ausführung eines Befehls darin ist nicht so. Unter der Bedingung der Ausführung des CASE- Befehls sollte der Ausdruck die Bezeichnung berechnen, an die das Steuerelement übertragen wird. Dieser Befehl hat keine Argumente.

Jedes Etikett in diesem Befehl bildet einen Block von diesem Etikett zum nächsten. Wenn die Steuerung auf das Label übertragen wird, werden nur Befehle bis zum nächsten Label ausgeführt, und dann wird der aktuelle CASE- Block verlassen . Dieser Befehl ist näher an der Pascal-Notation als am Befehl C switch. Wenn bei der Berechnung des Namens des Etiketts ein Name gefunden wird, der im aktuellen CASE- Block fehlt, werden die Befehle ausgeführt , die sich nach dem CASE- Befehl vor dem ersten Etikett befinden .

FALL? L_ $ J; // label wird ausgewertet
SET x [1] = 1; // Wenn keine Bezeichnung gefunden wird, werden die Befehle dieses Blocks ausgeführt.
SET a [2] = x [1] +1;
L1: SET x [1] = 2; // Befehlsblock beschriften L1
SET a [2] = x [1] +2;
L2: SET x [1] = 3; // Befehlsblock beschriften L2
SET a [2] = x [1] +3;
ENDE
Beschriftungen in diesem Befehl bilden implizit einen internen Befehlsblock. Nach der Ausführung eines solchen Befehlsblocks wird die Steuerung außerhalb des Blocks des CASE- Befehls übertragen .

WHILE Befehl


Mit dem Befehl WHILE wird die Schleife organisiert. Die Bedingung für die Ausführung dieses Befehls legt die Bedingung für die Fortsetzung der Schleife fest. Solange die Bedingung für die Ausführung des Befehls nicht 0 ist, wird der durch diesen Befehl gebildete Block ausgeführt. Der Block endet mit dem Befehl END . Der END- Befehl eines solchen Blocks hat eine Funktion. Möglicherweise liegt eine Blockbeendigungsbedingung vor. Wenn die Bedingung nicht 0 ist, wird der Block abgeschlossen. Darüber hinaus können diese Bedingungen sowohl im WHILE- Befehl als auch im END- Befehl vorhanden sein .
Zum Beispiel:
WHILE? X [7]> 0; // Bedingung für die Fortsetzung des Zyklus
SET y [2] = x [7] +2;
BREAK? Y [2] <0;
SET x [7] = x [7] +1;
END? X [7]> 20; // Bedingung zum Beenden der Schleife
Innerhalb des Blocks kann die Schleife durch den Befehl BREAK unterbrochen werden.

Blockschleifeniteratoren


Blockschleifeniteratoren sind für den Zugriff auf Baumknoten optimiert. Sie verwenden eine interne Verbindung, um den Zugriff auf Bypass-Knoten zu optimieren. Dies führt zu einer Einschränkung der Verwendung von Blockiteratoren. Innerhalb des Blocks können Sie die Struktur des Baums nicht ändern. Sie können nicht in diesen Baum schreiben. In Blockschleifen-Iteratorbefehlen 2 Argumente.
Das erste Argument ist erforderlich, die Verknüpfung zu dem Knoten, dessen Nachkommen umgangen werden. Referenzindex. Es können verkürzte Links verwendet werden. Das zweite Argument ist die Verknüpfung zu dem Knoten, auf dem der Nachkommenindex gespeichert wird. Dieses Argument ist optional. Innerhalb des Blocks sollte sich das 2. Argument nicht ändern. Ausdrücke wie $$ 2 oder [[3]] sind nicht zulässig, wenn $ 2 oder [3]innerhalb des Iteratorblocks ändern. Änderungen an diesen Variablen werden nicht berücksichtigt. Der Zugriff auf den untergeordneten Index kann über die Systemvariable% queryKey und die Knotendaten über die Eigenschaft% queryData erfolgen . Wenn die Nachkommen nicht von Anfang an umgangen werden dürfen, ist das 2. Argument erforderlich und der Knotenindex muss darin platziert werden, wonach die Umgehung der Nachkommen beginnt. Wenn es ein zweites Argument gibt, Sie aber von Anfang an herumgehen müssen, müssen Sie diese Variable vor der Schleife mit dem Befehl KILL löschen .
Befehle können eine Blockausführungsbedingung haben. Dieser Zustand wird beim Betreten des Blocks nur einmal überprüft.

Sie können nicht nur die Knoten des Baums, sondern auch Arrays umgehen. In diesem Fall wird die Seriennummer des Array-Feldes in das zweite Argument eingegeben. Nur der verkürzte Link kann als erstes Argument verwendet werden.

NÄCHSTES Team


Der Befehl NEXT durchläuft die unmittelbaren Nachkommen eines Baumknotens. Nachkommen kosten in Vorwärtsrichtung vom minimalen zum maximalen Index.
Zum Beispiel:
NEXT us [4,5]; // 2 Argument ist nicht angegeben, der Index wird
// aus der Systemvariablen% queryKey genommen
SET $ 1 =% queryKey, $ 2 =% queryData;
ENDE? $ 1> 1000; // Bedingung zum Beenden der Schleife
Der Knotenindex wird sofort in die Daten
KILL $ 1;
NEXT us [4,5], $ 1;
SET $ 2 =% queryData;
ENDE

Ein abgekürzter Link wird als Referenzknoten verwendet. In diesem Fall wird die erste Ebene des Baums umgangen.
TÖTE 1 $;
NEXT us [], $ 1;
SET $ 2 =% queryData;
ENDE
Nach Index 3 kriechen.
SET $ 1 = 3;
NEXT us [4,5], $ 1;
SET $ 2 =% queryData;
ENDE
Beim Durchlaufen eines Arrays sind alle Felder in der richtigen Reihenfolge, auch diejenigen, in denen keine Daten definiert sind.
Zum Beispiel:
KILL $ 1;
NEXT us $, $ 1;
SET $ 2 =% queryData;
ENDE
Innerhalb des Blocks kann die Schleife durch den Befehl BREAK unterbrochen werden .

ZURÜCK Team


Der Befehl BACK unterscheidet sich vom Befehl NEXT nur in der Durchquerungsrichtung vom letzten zum ersten Scheitelpunkt.
Zum Beispiel:
KILL $ 1;
ZURÜCK uns [4,5], $ 1;
SET $ 2 =% queryData;
ENDE

FRAGE Team


Der Befehl QUERY durchläuft alle Nachkommen eines Knotens von links nach rechts und von oben nach unten bis zur vollen Tiefe in Vorwärtsrichtung. Das 2. Argument enthält den gesamten optionalen Index. Wenn dieser Index mehr als ein Feld enthält, wird die Liste in das zweite Argument eingefügt.

Andernfalls ähnelt dieser Befehl dem Befehl NEXT .

Der Befehl QUERY durchläuft das Array nur in Vorwärtsrichtung von links nach rechts.

Zum Beispiel:
KILL $ 1;
Fragen Sie uns [4,5], $ 1;
SET $ 2 =% queryData;
ENDE
Dieser Befehl umgeht jedoch nur die wichtigen Eckpunkte.

Nicht blockierte Befehle Datenbaum-Durchlaufbefehle


In diesen Befehlen sind beide Befehlsargumente erforderlich. Das zweite Argument speichert den Index. Danach findet der nächste Befehl den nächsten Scheitelpunkt. In diesen Befehlen werden interne Links nicht gespeichert und daher gibt es keine Einschränkung beim Anpassen des umgangenen Baums. Aus dem gleichen Grund kann die Zugriffszeit auf die Peaks viel länger sein. Mit diesen Befehlen können auch Arrays umgangen werden.

Befehl NEXT1 Der

Befehl NEXT1 gibt den nächsten Knoten auf derselben Ebene unter dem Referenzknoten an. Knotendaten
sind in der Systemvariablen% queryData verfügbar .
Zum Beispiel:
SET $ 1 = 2;
NEXT1 us [1,4], $ 1;
// gibt den Knoten auf Ebene 3 nach dem Knoten us [1,4,2]

BACK1 Team


Der Befehl BACK1 gibt den vorherigen Scheitelpunkt auf derselben Ebene unterhalb des Referenzknotens an.
Ansonsten ähnelt es dem Befehl NEXT1 .

QUERY1 Team


Der Befehl QUERY1 gibt den nächsten Scheitelpunkt eines Astes an, während der gesamte Knoten von oben nach unten und von links nach rechts durchlaufen wird. Das 2. Argument enthält den gesamten optionalen Index. Wenn dieser Index mehr als ein Feld enthält, wird die Liste in das zweite Argument eingefügt.

Ansonsten ähnelt es dem Befehl NEXT1 .

Programm-Management


Eine Modulbezeichnung kann abhängig vom Zugriff auf diese Bezeichnung ein Aufrufpunkt für ein Programm, eine Funktion, einen Aufrufpunkt für eine neue Aufgabe, eine Objekteigenschaft, eine Objektmethode und eine Bezeichnung sein.
Darüber hinaus kann auf das Etikett in verschiedenen Teilen des Moduls unterschiedlich zugegriffen werden.
Zum Beispiel:
LB: Setze Val [25] = 7 + A $ 1; Rückgabewert [25];
Do LB (78); // Zugriff auf das Programm. Der Rückgabewert wird ignoriert.
Setze Val [7] = 8 * LB (6); // Als Funktion aufrufen wird der Rückgabewert verwendet.
JOB LB (17, "yt"); // neuen Job aufrufen
Set Val [9] = Mod.LB (3); // Zugriff auf die Klassenmethode Mod - Der Name des Moduls wird in diesem Kontext als Name der Klasse des Objekts behandelt.
Setze Val [15] = Obj [1,2, A] .LB; // Zugriff auf die LB-Eigenschaft des Objekts Obj [1,2, A],
Gehen Sie LB; // Zur LB-Bezeichnung wechseln
In den obigen Beispielen wird der Aufruf zusätzlich zu 4 und 5 innerhalb des aktuellen Moduls ausgeführt. Der Aufruf von Programmen und Funktionen kann an jedes verfügbare Modul erfolgen. Dies gilt übrigens auch für das Go-Team.
Zum Beispiel gibt es im Mod-Modul eine Bezeichnung Lb. Dann sieht der Appell wie folgt aus:
Do Mod.Lb (78);
Setze Val [7] = 8 * Mod.Lb (6);
Setze Val [9] = Mod.Lb (3);
JOB Mod.Lb (78);
Go Mod.Lb;

Im Allgemeinen wird ein Label als Programm oder Funktion verwendet. Wenn das Modul als Objektklasse verwendet wird, ist die Bezeichnung eine Eigenschaft oder Methode dieses Objekts. Die Eigenschaften eines Objekts und seiner Methoden sind eine weitere Form des Zugriffs auf Programme und Funktionen. Daher gilt alles, was über Programme und Funktionen gesagt wird, gleichermaßen für Eigenschaften und Methoden. Es gibt keine signifikanten Nuancen beim Zugriff auf Objekte nur in Bezug auf die Vererbung. Dieses Problem wird nachstehend ausführlicher beschrieben.

Im allgemeinen Fall sind der Name des Moduls und der Name der Bezeichnung im Aufruf Ausdruck und können zum Zeitpunkt des Aufrufs berechnet werden.
Zum Beispiel:
Setzen Sie $ 1 = "Md", $ 2 = "Lb";
Mach $ 1. $ 2;

Das Programm wird mit dem Befehl Return beendet . Ein Modul kann mit dem Befehl End abgeschlossen werden.

Parameter übergeben


In MSH werden Parameter nur als Wert übergeben. Im Allgemeinen existieren im Prinzip keine Referenzen und Hinweise in Bezug auf die C ++ - Sprache und die enormen Probleme, die mit ihrer Verwendung hier verbunden sind. Ein Programm akzeptiert immer eine beliebige Anzahl von Parametern in einem A $ -Array . Ihre Nummer kann unter Bezugnahme auf das 0-Element des Arrays A $ 0 ermittelt werden . Der Programmierer ist für die Bedeutung dieser Parameter verantwortlich.

Zum Beispiel:
Wir haben ein Lb-Programm. Es kann angesprochen werden:
DO Lb (1,2,7);
DO Lb (25,7);
DO Lb ();
JOB Lb (8);
SET [7.8] = Lb (187, "Liguster");

Nicht übergebene Parameter im Programm sind nicht definiert.
Das Übergeben von Parametern nach Wert beeinträchtigt nicht das Übergeben von Variablennamen an das Programm und deren Verwendung dort.
Zum Beispiel:
Setzen Sie uns [5] = 48;
Do Lb ("wir");
...
zurück;
Lb: Setze par [8,1,9] = A $ 1 [5];
// A $ 1 - Der erste übergebene Parameter enthält den
Variablennamen //: us .
// [5] - Zugriff auf den Anfang dieses Baums
// als Ergebnis ist der Knotenwert us [5] = 48
Return;
Dadurch kann der Name der Variablen beliebig manipuliert werden.
Wenn Sie mit dem Befehl GO zum Label wechseln, ändert sich das Parameterarray nicht. MSH verfügt über ein GO-Befehlsformular mit der Übertragung neuer Parameter. In diesem Fall wird das aktuelle Parameterarray durch das im GO- Befehlsaufruf angegebene neue ersetzt .
Zum Beispiel:
GO Lb (1,2,7);

Handhabung des Events


Die Ereignisverarbeitung ist ein leistungsstarker Programmiermechanismus, der in Hochsprachen normalerweise nicht enthalten ist. Die Präsenz in Bibliotheken und im Betriebssystem spricht jedoch für seine Bedeutung. Auf diesem Mechanismus basieren Bibliotheken visueller Komponenten. Das Vorhandensein von Ereignisverarbeitung in der Sprache erweitert die Fähigkeiten der Sprache. Öffnet einen neuen ereignisgesteuerten Programmierstil. Übrigens hat eine so angesehene Programmiersprache wie Assembler solche Funktionen. Daher wurde dieser Mechanismus der MSH-Sprache hinzugefügt.

Die Basis dieses Mechanismus ist das Ereignis. Es ist in der Anwendung lokalisiert. Dementsprechend müssen diese Namen in der gesamten Anwendung eindeutig sein. Wenn der Ereignisname mit dem im Befehl CONSTANT deklarierten Namen übereinstimmtDann wird der Ereignisname durch den Wert der deklarierten Konstante ersetzt. Seien Sie vorsichtig. Bei der Benennung von Ereignissen ist es ratsam, eine Art Benennungsstrategie einzuhalten. Weisen Sie beispielsweise Ereignisnamen zu, die mit evu beginnen . Die Länge des Namens sollte unter Berücksichtigung der UTF8-Codierung 18 Byte nicht überschreiten. Diese Einschränkung ist nur mit der aktuellen Sprachimplementierung verbunden.

Ein in einer Aufgabe erstelltes Ereignis ist sichtbar und kann in beliebigen Aufgaben verarbeitet werden. Ereignishandler können eine beliebige Anzahl sein und unterschiedliche Aufgaben ausführen.
Nach dem Eintreten des Ereignisses wird geprüft, ob für dieses Ereignis Handler vorhanden sind. Wenn keine Handler vorhanden sind, wird das Ereignis gelöscht. Wenn Handler vorhanden sind, werden diese nacheinander ausgeführt. Ereignisse können System und Benutzer sein. Systemereignisse werden vom System generiert. Ein benutzerdefiniertes Ereignis wird vom Befehl EVENTTRAP generiert . Das Ereignis übergibt Parameter an die Handler, wie beim Aufrufen eines Programms. Nach der Verarbeitung werden Ereignishandler nicht gelöscht. Verwenden Sie den Befehl EVENTDELETE, um ein Ereignis zu löschen . Ein Ereignis kann mit den Befehlen EVENTCALL und EVENTWAIT behandelt werden .

EVENTTRAP-Team


Der Befehl erstellt ein benutzerdefiniertes Ereignis. Das Befehlsformat ähnelt einem Programmaufruf, anstelle des Programmnamens wird nur der Ereignisname verwendet. Ereignisnamen sind in der Anwendung lokal und daher in allen Aufgaben sichtbar.

Das Team erstellt ein Ereignis mit dem angegebenen Namen. Ereignishandlern werden die in den Befehlsargumenten aufgeführten Parameter übergeben.

Zum Beispiel:
EVENTTRAP? X [1]> 8 evuBoxData (us [7], $ 4), evuKorXY (us [X], us [Y], sh);
2 Ereignisse evuBoxData und evuKorXY werden als Variablen us [7], $ 4, us [X], us [Y] und die String-Konstante sh generiert .
Wenn für dieses Ereignis derzeit keine Handler vorhanden sind, wird das Ereignis nicht generiert.

EVENTDELETE Team


Der Befehl entfernt die in den Programmargumenten aufgeführten Ereignishandler.
Zum Beispiel:
EVENTDELETE? X [1]> 7 evuKorXY, evuBoxData;
Ereignisse werden in der Reihenfolge im Team gelöscht.

EVENTCALL Team


Der Befehl weist einen Ereignishandler zu. Ein Handler ist ein Programm. Dieses Programm wird von der laufenden Aufgabe asynchron aufgerufen und Parameter werden an sie übergeben. Nach Ausführung des Handlerprogramms wird die Steuerung an der Unterbrechungsstelle an die Hauptaufgabe zurückgegeben.

Zum Beispiel:
EVENTCALL evuBoxData = Mod1.intEvuBoxData, evuKorXY = Mod2.intevuKorXY;

EVENTWAIT Team


Das Team wartet auf Ereignisse. Dieser Befehl blockiert die aktuelle Aufgabe, bis die in den Argumenten aufgeführten Ereignisse eintreten. Alle in den Argumenten aufgeführten Ereignisse sollten auftreten, um die Ausführung des aktuellen Threads fortzusetzen. Die aktuellen Programmparameter werden durch die im Befehl zur Ereigniserstellung übertragenen ersetzt.
Zum Beispiel:
EVENTWAIT evuBoxData, evuKorXY;
Mit diesen Befehlen können Sie die asynchrone Ausführung von Programmen organisieren.

Vektoren


Vektoren sind eng mit der aktuellen Implementierung verbunden. Sie speichern vorzeichenbehaftete und vorzeichenlose Ganzzahlen. Die Dimension dieser Vektoren hängt von der Bittiefe der Vektorkomponente ab und ist fest.

64-Bit-Vektoren


Die Dimension eines solchen Vektors ist 2. Komponenten können 64-Bit-Ganzzahlen oder vorzeichenlose Ganzzahlen sein. Solche Zahlen werden in beliebigen Variablen gespeichert.
Die Anziehungskraft auf die ikonischen ganzzahligen Komponenten des Vektors.
SET us [5].% V64 (0) = ss $ 1.% v64 (1);
% v64 - Zugriff auf die vorzeichenbehaftete Ganzzahlkomponente des Vektors.
Ein Aufruf an vorzeichenlose Ganzzahlkomponenten eines Vektors.
SET us [5].% Vu64 (0) = ss $ 1.% vu64 (1);
% vu64 - Zugriff auf die gesamte vorzeichenlose Komponente des Vektors.

32-Bit-Vektoren


Die Dimension eines solchen Vektors ist 5. Die Komponenten können 32-Bit-Ganzzahlen oder vorzeichenlose Ganzzahlen sein. Solche Zahlen werden in beliebigen Variablen gespeichert.
Die Anziehungskraft auf die ikonischen ganzzahligen Komponenten des Vektors.
SET us [5].% V32 (0) = ss $ 1.% v32 (4);
% v32 - Zugriff auf die vorzeichenbehaftete Ganzzahlkomponente des Vektors.
Ein Aufruf an vorzeichenlose Ganzzahlkomponenten eines Vektors.
SET us [5].% Vu32 (0) = ss $ 1.% vu32 (4);
% vu32 - Zugriff auf die gesamte vorzeichenlose Komponente des Vektors.

16-Bit-Vektoren


Die Dimension eines solchen Vektors ist 11. Die Komponenten können ganzzahlige oder vorzeichenlose 16-Bit-Zahlen sein. Solche Zahlen werden in beliebigen Variablen gespeichert.
Die Anziehungskraft auf die ikonischen ganzzahligen Komponenten des Vektors.
SET us [5].% V16 (0) = ss $ 1.% v16 (10);
% v16 - Zugriff auf die vorzeichenbehaftete Ganzzahlkomponente des Vektors.
Ein Aufruf an vorzeichenlose Ganzzahlkomponenten eines Vektors.
SET us [5].% Vu16 (0) = ss $ 1.% vu16 (4);
% vu16 - Zugriff auf die vorzeichenlose Ganzzahlkomponente des Vektors.

8-Bit-Vektoren


Die Dimension eines solchen Vektors beträgt 22. Die Komponenten können ganzzahlige oder vorzeichenlose 8-Bit-Zahlen sein. Solche Zahlen werden in beliebigen Variablen gespeichert.
Die Anziehungskraft auf die ikonischen ganzzahligen Komponenten des Vektors.
SET us [5].% V8 (0) = ss $ 1.% v8 (21);
% v8 - Zugriff auf die vorzeichenbehaftete Ganzzahlkomponente des Vektors.
Ein Aufruf an vorzeichenlose Ganzzahlkomponenten eines Vektors.
SET us [5].% Vu8 (0) = ss $ 1.% vu8 (21);
% vu8 - Zugriff auf die gesamte vorzeichenlose Komponente des Vektors.

Operationen


Operationen in MSH spielen eine besondere Rolle. Sie steuern die Konvertierung von Datentypen. Abhängig von der Operation werden die Operanden in den gewünschten Datentyp umgewandelt. Die Art des Datenergebnisses entspricht eindeutig der Art der Operation. Zeichenfolgen- und numerische Operationen überschneiden sich nicht wie die + -Operation in C-ähnlichen Sprachen. Die Art der Operation in MSH hängt nicht von der Art der Operanden ab, alles ist genau umgekehrt. In MSH gibt es keine operativen Prioritäten, es ist ein historisches Erbe von MUMPS.

Zum Beispiel:
SET $ 1 = 2 + 3 * 4;
$ 1 ist 20, nicht 14.
Damit das Ergebnis 14 ist, werden Klammern verwendet.
SET $ 1 = 2 + (3 * 4);
Beim Verbinden von Zeichenfolgen wird das Symbol " _ " verwendet.
Die mangelnde Priorität der Operationen ist ungewöhnlich, aber recht praktisch. Der Hinweis auf die Natürlichkeit von Prioritäten, wenn Operationen mehr als addieren, wird sehr zweifelhaft. Nachdem Sie einmal erfahren haben, dass es keine Prioritäten gibt, müssen Sie sich nicht schmerzhaft an ihre Prioritäten erinnern, und wenn etwas in die Dokumentation aufgenommen wird. Im Allgemeinen ist dies eine Gewohnheitssache.

Die Objekte


Das Vorhandensein von Objekten in modernen Programmiersprachen ist eine gute Form. Im allgemeinen Fall bestehen Objekte aus 2 Teilen. Teile der deklarativen Beschreibung und Teile der Implementierung. In MUMPS-Systemen haben Variablen nicht den deklarativen Teil einer Typdeklaration. Klassen sind grundsätzlich Benutzerdatentypen. Um die Prinzipien von MUMPS nicht zu verletzen, fehlt MSH der deklarative Teil der Klassenbeschreibung. Und wie sich herausstellte, kann man perfekt darauf verzichten. Von der Klasse ist nur noch ein Teil der Implementierung übrig. Die Implementierung der Klasse kann durch das Standardmodul perfekt dargestellt werden. Nur für die Klasse mussten zusätzliche Konventionen eingeführt werden, die mit der Beschreibung der Eigenschaften des Objekts verbunden sind. Objekte können sich nur im Baum befinden. Das Platzieren eines Objekts in einem Array schlägt fehl, da die Eigenschaften des Objekts nirgends gespeichert werden können. Wenn das Objekt keine Eigenschaften hat, können Sie es versuchen.Obwohl was für ein Objekt es ist.
Um eine öffentliche Eigenschaft zu beschreiben, benötigen Sie eine Funktion, die den Wert dieser Eigenschaft zurückgibt. Es muss einen Eigenschaftsnamen haben und sich im Modul mit dem Klassennamen befinden. Ein Programm zum Schreiben in eine Eigenschaft. Diesem Programm steht ein Eigenschaftsname mit dem Präfix ".". Und ein Programm zum Entfernen von Eigentum. Diesem Programm wird ein Eigenschaftsname mit dem Präfix ".." vorangestellt.

Der Funktionsname im Modul kann der öffentlichen Eigenschaft zum Lesen entsprechen. In diesem Fall wird der Rückgabewert einer solchen Funktion als Wert der öffentlichen Eigenschaft an das aufrufende Programm übergeben.

Der Konstruktor der Klasse ist die% objNew-Datenmethode. Wenn beim Erstellen eines Objekts Eigenschaften ermittelt oder Ressourcen abgerufen werden müssen, kann ein beliebiges Klassenmodulprogramm (Klassenmethode) verwendet werden. Es ist jedoch ratsam, sich an jede Strategie zur Benennung von Klassenkonstruktoren zu halten. Beispielsweise muss der Name des Konstruktors mit dem Namen der Klasse übereinstimmen.

Der Zugriff auf die geschützten Eigenschaften der Klasse erfolgt über die Systemeigenschaft % this .

Der Destruktor ist das Entfernen des Objekts mit dem Befehl KILLD. Wenn Sie Ressourcen freigeben oder zusätzliche Manipulationen durchführen müssen, kann dies von jedem Programm dieser Klasse (Klassenmethode) durchgeführt werden. Wie im Fall des Konstruktors ist es ratsam, beim Benennen des Destruktors eine Namensstrategie einzuhalten.

Zum Beispiel:
// Klasse Person
// Eigentum Alter
// Lesen Sie das öffentliche Eigentum Alter
Alter: RETURN [% this, Alter];
// Aufzeichnung des öffentlichen Eigentums Alter.
Alter: SET [% this, Alter] = A $ 1;
Rückkehr
ENDE

Ein Aufruf von Programmen an ein Objekt und seine öffentlichen Eigenschaften sieht wie folgt aus.
// Objekt erstellen Person
SET us [1,2].% objNew = Person;
// schreibe den Wert 50 in die Age-Eigenschaft
SET us [1,2] .Age = 50;
// lies die Age
SET Eigenschaft u $ 1 = us [1,2] .Age + 5;
// Eigenschaft löschen Alter
KILL us [1,2] .Age;

Objektvererbung


MSH-Klassen unterstützen Mehrfachvererbung. Der Befehl PARENT legt alle Vorfahren dieser Klasse fest. Darüber hinaus bestimmt die Reihenfolge der Namen der Vorfahren dieser Klasse in den Befehlsargumenten die Priorität der Vererbung. Je später die Klasse erwähnt wird, desto niedriger ist ihre Priorität.

Zum Beispiel:
PARENT USER, BOX;
Die Klasse erbt von den Vorfahren von USER und BOX . Die Priorität der USER- Vorfahren ist höher. Was ist die Priorität. Beim Zugriff auf ein Objekt wird die öffentliche Eigenschaft oder Methode der Klasse in der Klasse selbst durchsucht. Wenn sie dort nicht gefunden werden, werden sie im Vorfahren mit der höchsten Priorität und dann in den Vorfahren dieser Klasse usw. nach Priorität durchsucht.

Datenaustausch

In MSH ist die Dateifreigabe auf der primitivsten Ebene organisiert. Dateien in MSH spielen eine unterstützende Rolle. Der Austausch wird nur mit Textdateien organisiert. Die Dateistruktur besteht aus Textfeldern, die durch ein angegebenes Trennzeichen getrennt sind. Das Trennzeichen befindet sich in der Systemvariablen% dlmIO . Standardmäßig ist diese Variable " , ". Es steht zum Lesen und Schreiben zur Verfügung. Beim Schreiben in eine Datei werden die Variablen in einen Zeichenfolgentyp konvertiert und über das Trennzeichen in die Datei geschrieben. Beim Lesen aus einer Datei werden Variablen durch ein Trennzeichen ausgewählt und in eine normalisierte Form gebracht. Wenn das Feld ein Datensatz einer Zahl ist, wird eine Zahl in die Variable eingefügt. Der Austausch mit der Datei erfolgt über das Array B $ . Beim Schreiben ist das Array B $über das Trennzeichen in die Datei geschrieben. Beim Lesen aus einer Datei werden die Felder im B $ -Array ausgewählt .

Dateiaustauschbefehle verwenden den Dateipfad als Argumente.
Beispiel:
Aus einem Array von B $ werden Daten in eine Datei geschrieben. Die Datei wird schriftlich geöffnet. Die Daten in der Datei werden ersetzt.
Schreiben Sie "txt / tt1.txt";
Daten werden in das B $ -Array eingelesen . Das Array ist vorab gelöscht.
Lesen Sie "txt / tt1.txt";
txt / tt1.txt - Pfad zur Datei.

Fazit


Dieses Dokument ist kein Ersatz für die MSH-Sprachbeschreibung, sondern ergänzt sie nur. Hier werden nicht alle Merkmale der MSH-Sprache berücksichtigt, sondern nur diejenigen, auf die ich Sie aufmerksam machen möchte.

Verfasser: Sharymov Mikhail Alekseevich. E-Mail: misha_shar53@mail.ru

Bei Verwendung dieses Materials ist ein Link zur Quelle und zum Autor erforderlich.

All Articles