13 KiB
ereignissteuerung Specification
Purpose
Die Ereignissteuerung bestimmt, woher Ereignisse kommen, wann ein
laufendes Programm sie zu sehen bekommt und wie es darauf reagiert:
Ereignisquellen (Tastatur, Maus, Zeit, benutzerdefiniert) und ihre
Warteschlange, die abschließende Liste der
Zustellpunkte, die Maskierung je Quelle und global, sowie die Zustellung
als GOSUB in das laufende Programm. Sie ist die gemeinsame Grundlage
der klassischen Ereignis-Traps und späterer Forms-Ereignisse.
Requirements
Requirement: Ereignisquellen mit Zeit vom Host
Die Laufzeit SHALL Ereignisse aus vier Quellen führen: Tastatur, Maus, Zeit und benutzerdefinierte Ereignisse. Die Zeit SHALL vom Host bezogen werden; die Laufzeit MUST NOT für die Ereigniszustellung selbst auf die Systemuhr zugreifen. Ein Host ohne Terminal MUST die Zeit frei stellen können, sodass zeitgesteuerte Programme ohne Wartezeit und mit reproduzierbarem Ergebnis prüfbar sind.
Auch Wartefristen der VM SHALL ausschließlich von der Hostzeit abhängen. Ein Host mit stehender virtueller Zeit MUST NOT durch reale verstrichene Zeit eine Frist scheinbar erreichen.
Scenario: Zeitgesteuerter Trap ohne echte Wartezeit
- WHEN ein Testhost die Zeit um 5 Sekunden vorstellt und ein Programm
ON TIMER(5) GOSUB MarkemitTIMER ONaktiv hat - THEN wird der Trap zugestellt, ohne dass der Test tatsächlich wartet
Scenario: Wiederholter Lauf liefert dasselbe Ergebnis
- WHEN dasselbe zeitgesteuerte Korpusprogramm zweimal mit demselben Zeitverlauf ausgeführt wird
- THEN ist die Ausgabe beide Male identisch
Scenario: Stehende virtuelle Zeit
- WHEN ein Host während SLEEP seine Zeit unverändert hält
- THEN endet SLEEP nicht wegen realer Zeit; eine vom Host gemeldete Frist oder ein zugestelltes Ereignis beendet das Warten
Requirement: Mausereignisse in Zellenkoordinaten
Die Darstellungsschicht SHALL Mausereignisse der Ausführungsumgebung an
die Laufzeit weitergeben: Drücken, Loslassen und Bewegung, jeweils mit
gedrückter Taste, Umschaltzustand und Position. Die Position SHALL in
Zellen des Textbildschirms angegeben werden, gezählt wie bei LOCATE,
also 1-basiert. Ereignisse außerhalb der aktuellen Bildschirmfläche MUST
verworfen werden. Die Reihenfolge zwischen Maus- und Tastenereignissen
SHALL der Reihenfolge ihres Eintreffens entsprechen. Solange kein
Verbraucher ein Mausereignis annimmt, MUST es am Zustellpunkt verworfen
werden, damit die Warteschlange nicht unbegrenzt wächst.
Die Reihenfolge SHALL bis zur beobachtbaren Ausführung der zugehörigen Handler erhalten bleiben; getrennte Quellarten MUST NOT nachträglich nach ihrer Art umgeordnet werden.
Scenario: Position als Zelle
- WHEN in der linken oberen Ecke der Darstellungsfläche die linke Maustaste gedrückt wird
- THEN trägt das Ereignis Zeile 1 und Spalte 1
Scenario: Reihenfolge bleibt erhalten
- WHEN eine Taste gedrückt und danach die Maus geklickt wird
- THEN liefert die Warteschlange erst das Tasten-, dann das Mausereignis
Scenario: Ereignis außerhalb der Fläche
- WHEN ein Mausereignis eine Position außerhalb der aktuellen Bildschirmgröße nennt
- THEN wird es verworfen und erreicht die Warteschlange nicht
Scenario: Kein Verbraucher, keine Anhäufung
- WHEN ein Programm ohne Verbraucher für Mausereignisse läuft und die Maus dauerhaft bewegt wird
- THEN wächst die Warteschlange nicht über ihre Grenze und das Programm läuft unverändert weiter
Scenario: Taste vor Maus bis zum Handler
- WHEN eine Taste vor einem Mausklick eintrifft und beide Handler eine Kennung anhängen
- THEN steht die Tastenkennung vor der Mauskennung
Scenario: Maus vor Taste bis zum Handler
- WHEN ein Mausklick vor einer Taste eintrifft
- THEN wird zuerst der Maushandler wirksam
Requirement: Abschließende Liste der Zustellpunkte
Ereignisse SHALL ausschließlich an folgenden Punkten zugestellt werden
— das Vorbild prüft die Ereignismarke „before executing the next
statement":
an einer Anweisungsgrenze, bei DOEVENTS, während SLEEP und vor einer
blockierenden Eingabe. Zwischen zwei Zustellpunkten MUST NOT ein
Trap-Handler beginnen; insbesondere MUST NOT eine Anweisung in ihrer
Mitte unterbrochen werden. Ein zugestelltes Ereignis SHALL ein laufendes
SLEEP beenden.
Forms-Ereignisse SHALL auch während SLEEP an dessen bestehenden Zustellpunkten verarbeitet werden. Eine für das Menü geltende Zustellsperre SHALL an jedem Zustellpunkt gleichermaßen gelten.
Scenario: Keine Zustellung innerhalb einer Anweisung
- WHEN ein Ereignis fällig wird, während eine mehrteilige Anweisung ausgewertet wird
- THEN läuft die Anweisung zu Ende und der Handler beginnt erst an der folgenden Anweisungsgrenze
Scenario: SLEEP endet durch Ereignis
- WHEN ein Programm
SLEEP 60ausführt und nach 2 Sekunden ein aktiver Trap fällig wird - THEN wird der Handler ausgeführt und
SLEEPkehrt danach zurück, ohne die vollen 60 Sekunden abzuwarten
Scenario: DOEVENTS stellt zu
- WHEN ein anstehendes Ereignis vorliegt und
DOEVENTSausgewertet wird - THEN läuft der zugehörige Handler, bevor
DOEVENTSeinen Wert liefert
Scenario: Forms-Timer beendet SLEEP
- WHEN während SLEEP ein aktiver Forms-Timer fällig wird
- THEN läuft dessen Handler und SLEEP kehrt danach zurück
Requirement: Maskierung je Quelle mit drei Zuständen
Jede Ereignisquelle SHALL drei Zustände kennen. ON stellt Ereignisse
zu. OFF verwirft sie; ein während OFF eingetretenes Ereignis MUST
NOT nachträglich zugestellt werden, und ein zuvor unter STOP gemerktes
Ereignis MUST von OFF verworfen werden. STOP merkt höchstens ein
anstehendes Ereignis und stellt es beim nächsten ON zu. Ohne
vorangehende ON …-Trap-Definition MUST eine Steueranweisung wirkungslos
bleiben, aber keinen Fehler auslösen.
Scenario: OFF verwirft
- WHEN
TIMER OFFgilt, die Frist verstreicht und danachTIMER ONausgeführt wird - THEN wird kein Handler ausgeführt
Scenario: STOP merkt genau eines
- WHEN
KEY(1) STOPgilt, F1 dreimal gedrückt wird und danachKEY(1) ONausgeführt wird - THEN läuft der Handler genau einmal
Scenario: OFF verwirft das unter STOP Gemerkte
- WHEN
TIMER STOPgilt, die Frist verstreicht, danachTIMER OFFund dannTIMER ONausgeführt werden - THEN läuft kein Handler
Requirement: EVENT klammert Abschnitte ohne Ereignisprüfung
EVENT OFF SHALL die Ereignisprüfung für den folgenden Abschnitt
abschalten, EVENT ON sie wieder einschalten; die beiden klammern einen
Abschnitt, in dem keine Ereignisse erkannt werden müssen. Ein dritter
Zustand MUST NOT bestehen: EVENT STOP ist im Vorbild nicht
dokumentiert und MUST namentlich abgewiesen werden. Der Schalter SHALL
die Zustände der einzelnen Quellen überlagern, ohne sie zu verändern:
nach EVENT ON gilt für jede Quelle wieder ihr eigener Zustand.
Ereignisse, die während EVENT OFF eintreten, MUST NOT nachträglich
zugestellt werden.
Scenario: Klammer überlagert Einzelzustand
- WHEN
TIMER ONgilt und danachEVENT OFFausgeführt wird - THEN wird kein Zeit-Trap zugestellt, und nach
EVENT ONwird wieder zugestellt, ohne dassTIMER ONerneut nötig ist
Scenario: EVENT STOP gibt es nicht
- WHEN ein Modul
EVENT STOPenthält - THEN wird es namentlich abgewiesen
Requirement: Zustellung als GOSUB ohne Wiedereintritt
Ein zugestelltes Ereignis SHALL das GOSUB-Ziel seines Traps ausführen
und danach an die unterbrochene Stelle zurückkehren; der unterbrochene
Zustand (aufrufende Prozedur, Schleifen, Variablen) MUST erhalten
bleiben. Beim Eintritt in den Handler SHALL für seine eigene Quelle
selbsttätig STOP wirken, sodass keine rekursiven Traps entstehen; das
RETURN SHALL für sie selbsttätig ON ausführen — es sei denn, im
Handler wurde ausdrücklich OFF für diese Quelle ausgeführt, dann bleibt
sie aus. Ein RETURN label aus einem Handler MUST erlaubt sein.
Scenario: Rückkehr in die unterbrochene Schleife
- WHEN ein Trap während einer
FOR-Schleife zugestellt wird - THEN läuft die Schleife nach
RETURNmit unverändertem Zählerstand weiter
Scenario: Kein Wiedereintritt
- WHEN ein Zeit-Trap läuft und die nächste Frist während des Handlers verstreicht
- THEN wird der Handler nicht erneut betreten, sondern das Ereignis nach
RETURNeinmal zugestellt
Scenario: OFF im Handler überlebt das RETURN
- WHEN ein Handler
TIMER OFFausführt und danachRETURNerreicht - THEN bleibt die Quelle aus und kein weiterer Zeit-Trap wird zugestellt
Requirement: Getrappte Tasten verlassen den Eingabestrom
Eine Taste, für die ein aktiver ON KEY-Trap besteht, SHALL dem Trap
zugestellt werden und MUST NOT zusätzlich über INKEY$, INPUT,
LINE INPUT oder INPUT$ sichtbar werden. Bei OFF oder STOP der
Quelle SHALL die Taste dem normalen Eingabestrom erhalten bleiben.
Unter STOP SHALL die Taste normal lesbar bleiben und zugleich höchstens ein Ereignis für das spätere ON gemerkt werden.
Scenario: Getrappte Taste erscheint nicht bei INKEY$
- WHEN
ON KEY(1) GOSUB MarkemitKEY(1) ONgilt und F1 gedrückt wird - THEN läuft der Handler und ein anschließendes
INKEY$liefert den leeren String
Scenario: Nicht getrappte Taste bleibt im Strom
- WHEN derselbe Trap mit
KEY(1) OFFgilt und F1 gedrückt wird - THEN liefert
INKEY$die Sondertastenfolge für F1
Scenario: STOP merkt und erhält Eingabe
- WHEN unter KEY(1) STOP F1 gedrückt, per INKEY$ gelesen und danach KEY(1) ON ausgeführt wird
- THEN liefert INKEY$ die Sondertastenfolge und der Handler läuft nach ON genau einmal
Requirement: Benutzerdefiniertes Ereignis
SetUEvent SHALL ein benutzerdefiniertes Ereignis auslösen, das über
ON UEVENT GOSUB und die Steueranweisung UEVENT denselben Regeln für
Maskierung und Zustellung unterliegt wie die übrigen Quellen.
Scenario: SetUEvent löst den Handler aus
- WHEN
ON UEVENT GOSUB MarkemitUEVENT ONgilt undSetUEventaufgerufen wird - THEN läuft der Handler am nächsten Zustellpunkt genau einmal
Requirement: Reihenfolge bei mehreren fälligen Ereignissen
Sind an einem Zustellpunkt mehrere Ereignisse fällig, SHALL genau eines zugestellt werden; die übrigen bleiben anstehend und werden an folgenden Zustellpunkten zugestellt. Die Reihenfolge SHALL festgelegt und dokumentiert sein, sodass sie über Läufe hinweg gleich bleibt.
Scenario: Zwei gleichzeitig fällige Traps
- WHEN an einem Zustellpunkt ein Zeit- und ein Tasten-Trap zugleich fällig sind
- THEN läuft zuerst genau ein Handler und der andere am nächsten Zustellpunkt
Requirement: Fehler in einem Handler
Ein Laufzeitfehler in einem Trap-Handler SHALL der geltenden
Fehlerbehandlung unterliegen. RESUME und RESUME NEXT SHALL sich auf
die Anweisung im Handler beziehen, nicht auf die unterbrochene
Anweisung.
Scenario: Fehler im Handler erreicht den Handler des Moduls
- WHEN ein Trap-Handler eine Anweisung mit Laufzeitfehler ausführt und ein modulweiter
ON ERROR GOTO-Handler gesetzt ist - THEN wird dieser Handler betreten und
ERLnennt die Zeile im Trap-Handler
Requirement: Signal-Trap auf Betriebssystemsignalen
ON SIGNAL(n%) GOSUB und die Steueranweisung SIGNAL(n%) SHALL
denselben Regeln für Maskierung, Zustellung und Wiedereintritt
unterliegen wie die übrigen Quellen. n% SHALL auf
Betriebssystemsignale abgebildet werden, und zwar ausschließlich auf die
Menge, die auf allen Zielplattformen besteht: 1 auf den
Unterbrechungswunsch (SIGINT), 2 auf den Beendigungswunsch
(SIGTERM). Ein anderer Wert MUST namentlich abgewiesen werden — zur
Übersetzungszeit, wenn er konstant ist, sonst mit Laufzeitfehler 5. Ein
Signal MUST NOT im Signalkontext verarbeitet werden; es SHALL über den
Host als Ereignis in die Warteschlange gelangen. Die Abweichung zur
OS/2-gebundenen Quelle des Vorbilds SHALL in der Sprachreferenz
ausgewiesen sein.
Scenario: Signal-Trap folgt der Maskierung
- WHEN
ON SIGNAL(1) GOSUB MarkemitSIGNAL(1) STOPgilt und einSIGINTeintrifft - THEN läuft der Handler erst nach
SIGNAL(1) ON, und zwar genau einmal
Scenario: Unzulässige Signalnummer
- WHEN ein Modul
ON SIGNAL(7) GOSUB Markeenthält - THEN wird es namentlich abgewiesen und die Meldung nennt den zulässigen Bereich
Scenario: Signal ohne Trap bleibt Abbruch
- WHEN ein
SIGINTeintrifft, ohne dass einSIGNAL(1)-Trap aktiv ist - THEN bleibt es beim bisherigen Abbruchverhalten
Scenario: SIGTERM wird zugestellt
- WHEN SIGNAL(2) ON gilt und ein SIGTERM über den Host eintrifft
- THEN wird das Ziel von ON SIGNAL(2) GOSUB am nächsten erlaubten Zustellpunkt ausgeführt