• Keine Ergebnisse gefunden

Repräsentation von Zuständen

Obwohl die Domäne STATE Teil der Schnittstelle der Datentypsemantik ist, ist ihre Definition es nicht: Die Konstruktion und Verarbeitung von STATE-Werten obliegt ausschließlich der Da-tentypsemantik.

Wie in Abschnitt 8.1.2 dargestellt, muss die Repräsentation von Zuständen folgende Aspekte berücksichtigen:

• Die Zustände von Agenten stellen eine Hierarchie dar. Innere Agenten und Prozeduren kön-nen auf die Variablen der äußeren Agenten zugreifen.

• Die Angabe des Variablennamens allein reicht nicht, um den Variablenwert zu identifizie-ren. Es ist auch die Kenntnis des Agenten nötig, in dem der Zugriff erfolgt.

Aus diesen Beobachtungen ergab sich die Forderung, dass der Zustand von Agenten stets mit dem äußersten Prozessagenten assoziiert sein muss.

Während der Realisierung des Zustandsmodells wurde beobachtet, dass weitere Aspekte be-achtet werden müssen:

27. Implementierungen von SDL-2000 können natürlich den Speicher für das Objekt freigeben, wenn es nicht länger referenziert wird.

• Verschachtelte Agenten und Prozeduren können Referenzen auf die gleichen Objekte besit-zen. Die Zuordnung von Objektidentität zu Objektwert muss also ebenfalls „global“ für den äußersten Prozessagenten erfolgen.

• Prozeduren können mit Ein- und Ausgabeparametern definiert werden. Die aktuellen Argu-mente für Ausgabeparameter müssen Variablen sein. Innerhalb des Prozedurrufs ist dann der Name des formalen Parameters ein Synonym für den Namen der Variable des Rufers:

Zuweisungen an den formalen Parameter ändern sofort die Variable des Rufers.

Um die Belegung von Variablen zu modellieren, ist es naheliegend, sie als Paare von Variablen-bezeichner und Wert zu betrachten. Da auch der zugreifende Kontext den Wert beeinflusst, müs-sen sie tatsächlich Tripel sein, bei denen ein Element aus der Domäne STATEID stammt.

Um jedoch Ausgabeparameter repräsentieren zu können, reicht das Modell, Variablennamen Werte zuzuordnen, nicht: Manche Variablen sind mit einem weiteren Variablennamen assozi-iert, und erst dieser ist dann an einen Wert gebunden. Daraus ergibt sich die Definition der Do-mäne BOUNDVALUE:

BOUNDVALUE =def VALUE ∪ Variable-identifier

Ein Wert aus BOUNDVALUE definiert den Wert einer Variablen. Berücksichtigt man, dass manche Variablen keinen Wert haben (also „undefined“ sind), so ergibt sich die Definition der Domäne NAMEDVALUE:

NAMEDVALUE =def STATEID × Variable-identifier × [BOUNDVALUE]

Mit einem Element aus NAMEDVALUE wird für einen Zustand und eine Variable ein Wert festge-legt.

Um die Verschachtelung von Zuständen zu repräsentieren, muss bekannt sein, welcher äuße-re Zustand Grundlage welchen inneäuße-ren Zustands ist. Diese Zuordnung wird durch die Domäne SuperState repräsentiert:

SUPERSTATE =def STATEID × STATEID

In dieser Domäne repräsentieren die ersten Komponenten den Basiszustand und die zweiten Komponenten den enthaltenen Zustand. Die Verschachtelungsstruktur der Zustände lässt sich dann durch eine Menge von SUPERSTATE-Werten darstellen: Will man beispielsweise zu einem Zustand z den Basiszustand ermitteln, muss man aus der Menge von SuperState-Werten denje-nigen ermitteln, dessen zweites Element z ist und von diesem Wert die erste Komponente aus-wählen.

Mit diesen Definitionen ist es nun möglich, die Struktur des Gesamtzustands eines äußersten Agenten definieren:

STATE =def NAMEDVALUE-set × SUPERSTATE-set × OBJECTVALUE-set

Die erste Komponente des Zustands fasst die Variablenbindungen. Die zweite repräsentiert die Hierarchie der Zustände, und die dritte die Objekte des Agenten.

Für die Werte der Domäne State müssen eine Reihe von Konsistenzbedingungen gelten, die durch die Definition nicht automatisch erfüllt sind:

• Für jedes Paar (STATEID, Variable-identifier) darf es höchstens ein NAMEDVALUE-Tripel geben. Anderenfalls hätte die Variable gleichzeitig mehrere assoziierte Werte. Gleicherma-ßen darf es für jeden OBJECT-Wert höchstens ein OBJECTVALUE-Paar geben.

• Falls ein BOUNDVALUE-Wert o aus der Domäne OBJECT stammt, muss es einen OBJECTVA

-LUE geben, dessen erste Komponente o ist.

• Für jeden STATEID-Wert darf es höchstens einen Basiszustand geben. Genau ein StateId-Wert darf keinen Basiszustand haben.

• Jeder STATEID-Wert, der in einem NAMEDVALUE-Tripel auftaucht, muss gültig sein, dass

heißt, er muss als Komponente eines SUPERSTATE-Paares auftauchen. Wenn es keine SUPER -STATE-Paare gibt, müssen alle STATEID-Werte gleich sein.

Es ist eine Beweisverpflichtung, dass die Funktionen der Datentypsemantik nur Zustandswerte erzeugen, die diese Bedingungen erfüllen.

8.5 Vordefinierte Datentypen

Zur Definition vordefinierter Datentypen kann auf die Domänen zurückgegriffen werden, die als Basiskonzepte für den ASM-Formalismus definiert wurden (siehe Abschnitt 5.3.2). So ist beispielsweise die Menge der ganzen Zahlen, die Domäne NAT, als Teil des Formalismus vor-definiert. Da viele der Operatoren in SDL die „übliche“ mathematische Bedeutung haben, kann die Semantikdefinition dieser Operatoren auf die Operationen des Formalismus zurückgreifen.

Allerdings zeigt sich, dass es eine Reihe wesentlicher Abweichungen gibt:

• Die gleiche Domäne der formalen Semantik muss zur Definition verschiedener Sorten ver-wendet werden. So besitzen beispielsweise die SDL-Sorten Real, Time und Duration die gleiche algebraische Struktur, die Sorten sind jedoch disjunkt. Da SDL-2000 Mechanismen der Laufzeit-Typidentifikation bietet, muss jeder Wert Informationen über die Sorte besit-zen, der er entstammt.

• Manche Operationen haben in der Mathematik keine „übliche“ Bedeutung, und sind dem-zufolge nicht Teil des Formalismus. Beispielsweise gibt es verschiedene Definitionen einer Ganzzahldivision, falls einer der Operanden negativ ist. Die SDL-Semantik legt sich auf eine dieser Bedeutungen fest, in der formalen Semantik muss diese Bedeutung dann mit Hilfe der vorhandenen Operatoren modelliert werden.

Zur Berechnung des Werts eines vordefinierten Operators bietet die Datentypsemantik die Funktion compute (siehe Abschnitt 8.1.4). Diese Funktion ist wie folgt definiert

compute (procedure: PROCEDURE, values: VALUE* ) : VALUEOREXCEPTION =def

if intype (procedure, IntegerType.s-Name) then computeInteger(procedure, values) elseif intype (procedure, BooleanType.s-Name) then computeBoolean(procedure, values) elseif intype (procedure, CharacterType.s-Name) then computeChar(procedure, values) elseif intype (procedure, RealType.s-Name) then computeReal(procedure, values)

elseif intype (procedure, DurationType.s-Name) then computeDuration(procedure, values) elseif intype (procedure, TimeType.s-Name) then computeTime(procedure, values) elseif intype (procedure, Stringtype.s-Name) then computeString(procedure, values) elseif intype (procedure, Arraytype.s-Name) then computeArray(procedure, values)

elseif intype (procedure, Powersettype.s-Name) then computePowerset(procedure, values) elseif intype (procedure, Bagtype.s-Name) then computeBag(procedure, values)

else

OutOfRange endif

Diese Funktion ermittelt zunächst, um welchen Operator es sich bei der Prozedur handelt. Dazu bestimmt die Funktion intype, ob der Operator, der als erstes Argument übergeben wird, aus dem Datentyp stammt, der als zweites Argument übergeben wird. In Abhängigkeit davon wird dann eine Funktion gerufen, die die Operatoren dieses Datentyps unterscheiden kann.

Da diese Funktionen sich ähneln, wird hier lediglich ein Beispiel angegeben, nämlich für die Berechnung der Operatoren des Typs Integer.

8.5.1 Repräsentation von Integer-Werten

Der vordefinierte SDL-Typ Integer beschreibt die Menge ganzer Zahlen, er unterliegt also kei-ner Wertebeschränkung (anders als die Ganzzahltypen anderer Sprachen, wie etwa C oder Ja-va). Damit ist die vordefinierte ASM-Domäne NAT als Basis der Definition von Integer

geeignet. Ursprünglich war diese Domäne definiert als die Menge natürlicher Zahlen. Die SDL-Semantik hätte darauf basierend Integer-Werte als Paare (Vorzeichen, Wert) repräsentieren müssen. Die Definition von NAT wurde dann auf alle ganzen Zahlen erweitert, da sich bei der Erweiterung kein methodischer Nachteil ergab und die Definition der Datentypsemantik verein-facht werden konnte.

Trotzdem kann die Sorte Integer nicht als Synonym von NAT definiert werden, da bei Daten-typspezialisierung von Integer die spezialisierte Sorte von der Basissorte verschieden ist, aber die gleichen Operationen besitzt. Deshalb wird Integer definiert durch

SDLINTEGER =def NAT × Identifier

Der Bezeichner in einem SDLINTEGER-Wert bezeichnet die Datentypdefinition, der der Wert entstammt; üblicherweise also <<package Predefined>> Integer.

Der Zugriff auf den semantischen Wert (welcher auch Teil der Datentypschnittstelle ist), wird dadurch recht einfach; man muss lediglich die NAT-Komponente ermitteln.

semvalueInt(v:SDLINTEGER ): NAT=def v.s-NAT

8.5.2 Berechnung von Operatoren

Die Operatoren des Typs Integer werden durch die Operation computeInteger definiert.

computeInteger (procedure: PROCEDURE, values: VALUE*): VALUEOREXCEPTION =def letrestype = definingSort(procedure) in

if procedure Literal-signature then

integerLiteral(0,procedure.procName, restype) elseif procedure.procName = ì-ì values.length = 1 then

mk-SDLINTEGER (0 - values.head.semvalueInt, restype)

elseif procedure {"+", "-", "*", "/", "mod", "rem", "<", "<=", ">", ">=" } then let val1 = values[1]. semvalueInt in

let val2 = values[2]. semvalueInt in case procedure.procName of

| "+" => mk-SDLINTEGER (val1+val2, restype)

| "-"=> mk-SDLINTEGER (val1 – val2, restype)

| "*"=> mk-SDLINTEGER (val1 * val2, restype)

| "/" =>

if val2 = 0 then

raise(DivisionByZero) else

mk-SDLINTEGER (intDiv(val1,val2), restype) endif

| "mod" =>

if val2 = 0 then

raise(DivisionByZero) else

mk-SDLINTEGER (intMod(val1,val2), restype) endif

| "rem"=>

if val2 = 0 then

raise(DivisionByZero) else

mk-SDLINTEGER (intRem(val1,val2), restype) endif

| "power" =>

if val2 = 0 then

raise(DivisionByZero) else

mk-SDLINTEGER (intPower(val1,val2), restype)

endif

| "<" => mk-SDLBOOLEAN (val1 < val2, BooleanType)

| "<=" => mk-SDLBOOLEAN (val1 ≤ val2, BooleanType)

| ">" => mk-SDLBOOLEAN (val1 < val2, BooleanType)

| ">=" => mk-SDLBOOLEAN (val1 ≥ val2, BooleanType) endcase

endlet

else OutOfRange endif

endlet

Falls die SDL-Sorte durch Spezialisierung entstanden ist, ändert sich der Rückgabetyp in Ab-hängigkeit von den Argumenttypen.

Beispiel 43. Die Addition von Integer-Werten ist durch die Signatur

"+" ( this Integer, this Integer) -> this Integer;

definiert. Erfolgt nun eine Spezialisierung von Integer zum Typ Zahl durch die Definition valuetype Zahl inherits Integer {

}

so besitzt die Sorte Zahl ebenfalls einen Operator "+", dessen Ergebnistyp jedoch Zahl ist.

Für diese Operatoren ermittelt die Funktion restype die Sorte, in der der Operator definiert ist – die Ergebnissorte ist (für alle Operatoren von Integer) dann entweder restype oder der Typ Boolean.

Manche der Integer-Operatoren lassen sich nicht auf Operatoren des ASM-Kalküls abbilden, sie werden durch weitere Hilfsfunktionen berechnet.

Beispiel 44. Die Integer-Division von a und b ist in SDL durch Angabe der Axiome definiert.

a / 0 == raise DivisionByZero;

a >= 0 and b > a == true ==> a / b== 0;

a >= 0 and b <= a and b > 0 == true ==> a / b== 1 + (a-b) / b;

a >= 0 and b < 0 == true ==> a / b== - (a / (- b));

a < 0 and b < 0 == true ==> a / b== (- a) / (- b);

a < 0 and b > 0 == true ==> a / b== - ((- a) / b);

Diese aus SDL-92 übernommenen Axiome lassen sich durch folgende Funktion formalisie-ren (wobei bereits computeInteger den Fall der Division durch 0 behandelt):

intDiv(a: NAT, b: NAT):NAT =def if a ≥ 0 ∧ b > a then 0

elseif a ≥ 0 ∧ b ≤ a ∧ b > 0 then 1 + intDiv(a - b, b) elseif a ≥ 0 ∧ b < 0 then - intDiv(a, -b)

elseif a < 0 ∧ b < 0 then intDiv (-a, -b) elseif a < 0 ∧ b > 0 then - intDiv (-a, b) else 0

endif