9 Gültigkeitsbereich zur besseren Typ-Prüfung

Benutzerdefinierte Attribute, Variablen, lokale Variablen (in Regeln bzw. Methoden), Parameter und Rückgabetypen von Regeln, benutzerdefinierten Methoden, extevent-Regeln und Applikationsfunktionen können um einen Gültigkeitsbereich erweitert werden. Dies wurde eingeführt, um eine striktere Typ-Prüfung schon beim Laden zu ermöglichen, um so frühzeitig Fehler in Dialogen aufzuzeigen. Konkrete Anwendung - die Restriktion von Attributen/Variablen auf Objekte die von einem bestimmten Modell abgeleitet sind.

Der Gültigkeitsbereich ist ein Zusatz zu einem „Wertebehälter“ wie einem Attribut oder einer Variablen (inkl. Parameter) und stellt keinen eigenen Typ dar. Mit einem definierten Gültigkeitsbereich kann sichergestellt werden, dass nur Setzungen erlaubt sind die dem Gültigkeitsbereich entsprechen, also der „Wertebehälter“ immer einen konsistenten Wert behält. Prüfungen hierzu passieren während des Ladens sowie beim Ausführen von Regelcode.

Zweitens kann der Gültigkeitsbereich auch den weiteren Zugriff vom „Wertebehälter“ aus einschränken. Mit Zugriff ist dabei der Zugriff auf ein Kind, Attribut oder Methode gemeint. Ein Zugriff kann dabei auch zur Rückgabe eines Wertes mit einem abgeleiteten Gültigkeitsbereich führen.

Beispiel

dialog D

// Basismodell mit einem Kind
model window MWi {

  statictext StHeader {}

}
// Modell abgeleitet und erweitert

MWi Wi {

  .StHeader {

    integer Width := 10;

  }

  edittext Et {
  }

}
// Ein zweites Modell
model window MWi2 {}
// Instanz aus zweitem Modell

MWi2 Wi2 {
  // Attribut das nur von MWi2 abgeleitetes Objekt beinhalten darf

  object[MWi2] Ref := Wi; // Syntaxfehler da Gültigkeitsbereich verletzt

}

// Regel die nur auf von MWi abgeleitete Objekte angewendet werden darf

rule void SetHeader(object[MWi] O, string Header) {

  O.StHeader.text := Header;  // O kann niemals Wi2 sein!

  O.Et.xauto := 0; // Syntaxfehler wegen Zugriffsverletzung

  O.StHeader.Width := 20; // Syntaxfehler wegen Zugriffsverletzung

}
on dialog start {

  variable object[MWi] O; // Variable nur für von MWi abgeleitete Objekte
  SetHeader(Wi,”First”);
  SetHeader(Wi2,”Second”); // Syntaxfehler da Gültigkeitsbereich verletzt

  O := D.child[2]; // Dynamische Verletzung des Gültigkeitsbereichs

}

9.1 Beschränkungen

Folgende Beschränkungen sind momentan für die aufgelisteten Datentypen möglich:

Datentyp

Gültigkeitswert

Wert- und Zugriffsbeschränkungen,
Ableitung des Gültigkeitsbereiches

string

Integerwert (>0)

Keine Einschränkungen. Dieser Gültigkeitswert dient zur bisherigen Repräsentation der String-Größe die für die Generierung von Trampolin-Dateien für COBOL nötig ist.

object

Objekt

Wert darf null sein oder muss identisch mit dem Gültigkeitswert bzw. davon Abgeleitet (vergleichbar zu instance_of-Methode) sein.

Zugriffsbeschränkungen bei benutzerdefinierten Attributen, Kinder und Methoden auf diejenigen die am Objekt vorhanden sind.

Ableitung des Gültigkeitsbereiches beim Zugriff auf ein Kind-Objekt.

object

Klasse

Wert darf null sein oder muss ein Objekt der entsprechenden Klasse sein.

Keine Zugriffsbeschränkungen.

Ein Gültigkeitsbereich kann für folgende Fälle definiert werden:

  1. Datentyp eines benutzerdefinierten Attributes
  2. Index-Datentyp eines benutzerdefinierten Assoziativen Feldes
  3. Datentyp einer globalen Variablen
  4. Rückgabetyp einer Applikationsfunktion, benannten Regel oder benutzerdefinierten Methode
  5. Parametertypen von Applikationsfunktionen, benannten Regeln und benutzerdefinierten Methoden sowie Ereignisregeln
  6. Datentyp von lokale Variablen in benannten Regeln und benutzerdefinierten Methoden sowie Ereignisregeln

Beispiel

dialog D
model window MWi {}                                 // Folgende Nummern
MWi Wi {                                            // beziehen sich auf
record Rec {                                        // vorangegangene Liste
  object[MWi] Ref := Wi;                            // 1)
  boolean AssArray[object[MWi]];                    // 2)
  .AssArray[Wi] := true;
}

variable object[MWi] GlobaleVariable := Wi;         // 3)

function object[color] GetBgc(object[MWi] Window);  // 4), 5)

rule object[MWi] GetModel(object[Wi] P) {           // 4), 5)

  return P.model;

}
on Wi extevent 123 (object[MWi] P) {                // 6

  variable object[MWi] V := P;
}

9.2 Zugriffs- und Werteprüfung

Statische Definitionen die Gültigkeitsbereiche beinhalten werden grundsätzlich zur Ladezeit geprüft, ebenso Zuweisungen und Zugriffe in Regeln die als Konstant erkennbar sind. In diesem Sinne sind auch Objektpfad (z.B. „Wi“ im Beispiel unten) als „konstant“ Wert anzusehen der zur Ladezeit geprüft werden kann.

Dynamische Prüfungen passieren grundsätzlich bei Zuweisungen auf Wertebehältern mit gesetztem Gültigkeitsbereich bzw. Werteholungen oder Zugriffen von diesen heraus und erzeugen ein Fail, können also über Klammerung in ein fail(…)-Konstrukt abgefangen werden. Aufrufparameter und Rückgaben von benutzerdefinierten Methoden u.U. nur dynamisch geprüft. Dies begründet sich aus der nicht zwangsläufig zum Ladezeitpunkt vorliegenden Gültigkeitsinformationen bei der Verwendung von Attributen und Methoden von importierten Objekten.

Grundsätzlich sind vordefinierte „Variablen“ wie this oder thisevent nicht an einen Gültigkeitsbereich gebunden. Ebenso wenig wie Rückgabetypen und Parameter von vordefinierten Attributen, Methoden und Builtin-Funktionen. Insofern hat die Verwendung mit besonderer „Umsicht“ zu geschehen.

Da der Gültigkeitsbereich keinen Typ darstellt, gibt es auch keine Typprüfung oder Typkonvertierung. Ein „Casting“ wie man es von anderen Programmiersprachen kennt ist meist nicht notwendig bzw. kann durch Zwischenspeicherung auf eine Variable vom Datentyp object geschehen.

Die Zugriffsprüfung betrachtet immer nur gerade aktuellen Zustand (Objekte, vorhandene Kinder und Attribute).

Nachfolgendes kurzes Beispiel beinhaltet korrekte und fehlerhafte Verwendungen und zeigt den erwarteten Prüfungszeitpunk (Ladezeit/Laufzeit) auf.

dialog D

:

model window MWi { child edittext Et{} }
MWi Wi { child pushbutton Pb {} }
model window MWi2 { }
MWi2 Wi2 { checkbox Cb {} }
:
variable object[MWi] I1 := Wi
variable object[MWi2] I2 := Wi2
variable object O;
:
O := I1; // Gültigkeitsprüfung nicht notwendig
I1 := O; // Gültigkeitsprüfung zur Laufzeit
I2 := I1; // Gültigkeitsprüfung zur Ladezeit – GÜLTIGKEITSFEHLER!
I2 := W1; // Gültigkeitsprüfung zur Ladezeit – GÜLTIGKEITSFEHLER!
:

// Gültiger/erlaubter Zugriff auf Kind-Objekt:
print I1.Et;

print O.Pb;

 

// ZUGRIFFSFEHLER auf Kind-Objekt und deren Prüfungszeitpunkt:
print I1.Pb;     // Zugriffsprüfung zur Ladezeit da I1 Gültigkeitbereich hat

print O.Unkown;  // Zugriffsprüfung zur Laufzeit

print I2.Cb;     // Zugriffsprüfung zur Ladezeit
print I2.Unkown; // Zugriffsprüfung zur Ladezeit
print getvalue(I2,. Unkown); // Zugriffprüfung zur Laufzeit

9.3 Ableitung des Gültigkeitsbereiches

Der Gültigkeitsbereich wird beim Zugriff auf Kinder/Attribute weiter abgeleitet.

Dies geschieht beim Zugriff auf ein Attribut mit Gültigkeitsbereich, sowie wenn ausgehenden von einem Wertebehälter mit Gültigkeitsbereich ein Zugriff auf ein Kind-Objekt erfolgt.

dialog D
model window MWi {

  child groupbox Gb {


    child edittext Et {
      rule void Apply() {}

    }
  }

}
MWi Wi {

  object[MWi] Ref := MWi;

  .Gb {

    checkbox Cb { rule void Apply(); }
  }

  rule void Apply() {

    variable object[MWi] This := this;

    This.Gb.Et:Apply();

    This.Gb.Cb:Apply(); // Zugriffsfehler da Cb nicht in MWi.Gb vorhanden

    this.Ref.Gb.Cb:Apply();// Zugriffsfehler da Cb nicht in MWi.Gb da

  }

}

9.4 Erweiterung der IDM-Syntax

Syntaktische Erweiterungen/Änderungen an der Regelsprache sind wie folgt (rote Markierung):

Allgemeine Definitionen

<Datentyp> ::= anyvalue | attribute | boolean | class | enum | event |
        index | integer | method | object | pointer
<Parameterart> ::= { input } { output }
<Rückgabetyp> ::=  void | <Datentyp>
<Gültigkeit> ::= '[' <Gültigkeitswert> ']'
<Gültigkeitswert> ::= <Klasse> | <Objekt> | null | <Integerwert>
<Objekt> ::= <Identifikator> [ .<Identifikator> { :'[' <Integerwert> ']' } ]

Definitionen für benannte Regeln und Methoden

<Regel> ::= { export | reexport } { public } { extern } rule
        <Rückgabetyp> { <Gültigkeit> } <Identifikator>
        '(' { <Parameter> [ , <Parameter> ] } ')' { <ReposId> }
        <OptionalerProgrammblock>
<Parameter> ::=
        <Datentyp> { <Gültigkeit> } <Identifikator> { := <Wert> } <Parameterart>
<OptionalerProgrammblock> ::= ';' | <Programmblock>

Definitionen für externe Ereignisse

<ExterneEreignisregel> ::= on <Objekt> extevent <KonstanterWert>
        { '(' { <Parameter> [ , <Parameter> ] } ')' }
        { <Regelbedingung> }
        <Programmblock>

Definitionen für lokale Variablen

<Variablenanweisung> ::= { static } variable <Variable> [ ',' <Variable> ] ';'
<Variable> ::= <Datentyp> { <Gültigkeit> } <Identifikator> { := <Wert> }

Definitionen für globale Variablen

<GlobaleVariable> ::= { export | reexport } { config } <Variablenart> <Datentyp>
        { <Gültigkeit> } <Identifikator> { <ReposId> } { := <Wert> } ';'
<Variablenart> ::= constant | variable

Definitionen für benutzerdefinierte Attribute

<Attributdefinition> ::=
        <Datentyp> { <Gültigkeit> } <Identifikator> <Attributart> ';'
<Attributart> ::= <SkalaresAttribut> | <IndiziertesAttribut> |
        <AssoziativesAttribut> | <ShadowAttribut>
<SkalaresAttribut> ::= { := <Wert> } ';'
<IndiziertesAttribut> ::= '[' <Integerwert> ']' { := <Wert> }
<AssoziativesAttribut> ::= '[' <Datentyp> { <Gültigkeit> } ']' { := <Wert> }
<ShadowAttribut> ::=
        shadows { instance } <Objekt> <Attribut> { '[' <Index> ']' }

Definitionen für Applikationsfunktionen

<Applikationsfunktion> ::= { export | reexport } function { <Sprache> }
        <Rückgabetyp> { <Gültigkeit> } <Identifikator>
        '(' { <Funktionsparameter> [ , <Funktionsparameter> ] } ')'
        { alias <String> } { <ReposId> } <OptionalerProgrammblock>
<Funktionsparameter> ::= <Parameter> | <RecordParameter>
<RecordParameter> ::= record <Objekt> { := <Wert> } <Parameterart>

9.5 Attribute zur Nutzung mit Gültigkeitsbereichen

Die folgenden Attribute sind zur dynamischen Abfrage der Gültigkeitsbereiche bestimmt. Näheres ist in der „Attributreferenz“ bei der jeweiligen Attributbeschreibung zu entnehmen.