• Keine Ergebnisse gefunden

Verhalten von Operationen

operator PresentExtract(TargetAddress t) -> anonPresent{

return anonPresentExtract(t);

}

method virtual profileExtract() -> TaggedProfile{

return this.anon.profile;

}

method profileModify(TaggedProfile val){

this.present := profile;

this.anon := Make(, val, );

}

method profilePresent()->Boolean{

return this.anon.profilePresent;

} }

6.6 Verhalten von Operationen

Sofern es sich nicht um Operationen vordefinierter Typen handelt (siehe Abschnitt 8.4), wird das Verhalten einer Operation durch Operationsdefinitionen festgelegt:

<operation definitions> =

<operation definition> | <external operation definition>

Erfolgt die Operationsdefinition nicht im Körper der Datentypdefinition, muss statt der Opera-tionsdefinition ein Knoten <textual operation reference> angegeben werden. Die Parameterliste der Operationssignatur kann weggelassen werden, wenn sich aus dem Namen eindeutig ergibt, welche Operation referenziert wird.

<textual operation reference> :: <operation kind> <operation signature>

Soll für eine Operation überhaupt kein Verhalten (in SDL) spezifiziert werden, so kann die Ope-rationsdefinition in der Form <external operation definition> angegeben werden.

<external operation definition> :: <operation kind> <operation signature>

Eine solche Definition verwendet in der konkreten Syntax das Schlüsselwort external, wie bei-spielsweise in der Definition

operator fork -> Integer; external;

Eine solche externe Operationsdefinition hat keine formale Semantik. Damit hat auch die ge-samte SDL-Spezifikation, in der die Operation definiert wird, keine formale Semantik. Mit die-sem Konstrukt können beispielsweise Operationen deklariert werden, deren Implementierung in einer anderen Programmiersprache vorliegt.

Alle anderen Operationsdefinitionen folgen der Regel <operation definition>

<operation definition> ::

<package use clause>* <operation heading> <entity in operation>*

{ <operation body> | <statement list> }

Mit dem Knoten <package use clause> kann wiederum auf Pakete Bezug genommen werden, die innerhalb der Operationsdefinition verwendet werden. Um welche Operation es sich bei der Operationsdefinition handelt, wird durch den Knoten <operation heading> angegeben.

<operation heading> ::

<operation kind> <operation preamble> <qualifier> <operation name>

<formal operation parameter>* [<operation result>] <raises>

<operation kind> = operator | method

Zunächst legt der Autor fest, ob es sich um eine Operation oder eine Methode handelt. Innerhalb von Methoden kann auf einen zusätzlichen impliziten Parameter durch das Schlüsselwort this zugegriffen werden. Dieser Parameter bezeichnet das Objekt, für das die Methode aufgerufen wurde.

Durch den Knoten <qualifier> wird auf den Datentyp Bezug genommen, dessen Operation definiert wird. Dies ist lediglich bei refererenzierten Operation erforderlich. Auf den Operati-onsnamen folgen die formalen Operationsparameter:

<formal operation parameter> ::

[<argument virtuality>] <parameter kind> <parameters of sort>

Wie schon in der Definition der Operationssignatur wird durch <argument virtuality> festge-legt, ob ein Argument zur dynamischen Bindung verwendet wird. <parameter kind> legt fest, ob es ein Eingabe-, Ausgabe oder Ein-und-Ausgabeparameter ist. Anders als in der Signatur tra-gen die Parameter in der Definition jedoch Namen. Der Name des Rückgabewerts ist optional.

<parameters of sort> ::<variable<name>+ <sort>

<operation result> ::[<variable<name>] <sort>

Der Knoten <operation result> bestimmt den Ergebnistyp und gibt optional den Namen der Rückgabevariablen an. Durch Definition einer Rückgabevariablen kann auf die Angabe eines Werts in der return-Aktion verzichtet werden; in diesem Fall ist der Wert der Rückgabevariab-len das Operationsergebnis.

<raises> deklariert, genau wie in der Signatur, die Menge der Ausnahmen, die diese Opera-tion auslösen kann.

Beispiel 18. Unter Ausnutzung aller optionalen syntaktischen Konstrukte kann eine Operations-definition mit folgendem Kopf eingeleitet werden:

method virtual protected append(virtual inout Charstring data) -> result collector raises OutOfMemory

Auf die Knoten <operation heading> folgt eine Liste von Definitionen, die in der Operations-definition enthalten und damit nur in der Operation sichtbar sind. Erlaubt sind an dieser Stelle alle Definitionsarten (entity kinds), die im Operationskörper verwendet werden können, also im Wesentlichen weitere Datendefinitionen, Variablen und Ausnahmen.

<entity in operation> =

<data definition>

| <variable definition>

| <exception definition>

| <select definition>

Eine Sonderstellung nimmt hier der Knotentyp <select definition> ein, da dieser potentiell be-liebige weitere Definitionen enthält. Durch den Knoten <select definition> können, abhängig von konstanten Bedingungen, Alternativen ausgewählt werden (die Kindknoten von <select de-finition> sind). Im Rahmen einer Transformationsregel wird die Bedingung in der <select defi-nition> ausgewertet und dann dieser Knoten entweder durch eine leere Liste oder durch die enthaltenen Definitionen.

Der eigentliche Körper der Operation wird durch den Knoten <operation body> definiert:

<operation body> ::

[<on exception>] <start> {<free action> | <exception handler>}*

Dabei gibt der optionale Knoten <on exception> an, welche Ausnahmebehandlung für den ge-samten Graph des Operators gelten soll. Der Knoten <start> gibt die Starttransition an. Anders als bei Zustandsautomaten (Agenten und Zustandstypen) üblich besteht der Graph eines Opera-tors lediglich aus der Starttransition. Der Operatoralgorithmus kann also nicht in einem Zustand verharren.

Allerdings können durch join-Konstrukte Marken angesprungen werden, die innerhalb von Knoten des Typs <free action> definiert sind. Außerdem kann durch <on exception>-Knoten auf Ausnahme-Behandler Bezug genommen werden, die in den Knoten <exception handler>

definiert werden.

Die Definition der Grammatikregeln für <start>, <free action> und <exception handler>

wird hier nicht angegeben. Die Ausdruckskraft ist die gleiche, wie sie auch in der Definition von Agenten verwendet werden kann, mit folgenden Einschränkungen:

• Es dürfen keine Zustände definiert werden.

• Es dürfen keine Knoten <imperative expression> (also now, Variablenimport, self, offspring, sender, active, any, und state) verwendet werden.

• Es dürfen nur Bezeichner verwendet werden, die innerhalb des Operators definiert wurden, sowie Bezeichner für Synonyme, Literale, Operationen, Ausnahmen und Sorten.

Beispiel 19. Der oben angegebene Operator append könnte wie folgt definiert sein:

object type collector {

struct

contents Charstring;

method virtual protected append(in virtual Charsrtring data) ->result collector raises OutOfMemory

{

if (length(data) > 1000) raise OutOfMemory;

result := this;

contents := contents // data;

return;

} }

Trotz der Einschränkung der möglichen Aktionen innerhalb einer Operationsdefinition können Operationsdefinitionen nun (anders als in SDL-92) Seiteneffekte haben. So ändert die Methode append aus Beispiel 19 den Zustand des Objekts, an dem sie gerufen wird. Dabei werden unter Umständen auch Variablen des rufenden Prozesses geändert.

Beispiel 20. Zur Definition von Transitionen können in SDL sogenannte continuous signals verwendet werden. Das sind Ausdrücke, die in einem Zustand immer wieder bewertet wer-den, bis sie erfüllt sind – dann wird die mit dem Signal assoziierte Transition ausgeführt. Un-ter Verwendung der Methode append aus Beispiel 19 kann man folgende Transition definieren:

dcl the_collector collector;

/* ... */

state EinZustand;

provided length(the_collector.append(’Mehr Text’).data) > 20;

stop;

Hier wird im Zustand EinZustand verharrt, bis die Länge der Zeichenkette the_collector.data größer als 20 wird. In SDL-92 hätte dieser Ausdruck, ist er initial falsch, seinen Wert nur da-durch ändern können, dass eine externe Änderung der Variablen erfolgt. Mit SDL-92 hat die

Berechnung einen Seiteneffekt, und wiederholte Berechnung führt dazu, dass der Ausdruck schließlich wahr wird. Für continuous signals stellt sich nun die Frage, wie oft der Ausdruck berechnet werden soll, während der Prozess im Zustand EinZustand verharrt.

In Analyse dieser Frage wurde im Standardisierungsgremium zunächst diskutiert, Methoden in solchen Zusammenhängen zu verbieten. Allerdings hätte man dann auch Operatoren ver-bieten müssen, die Methoden rufen. Da auch ein einfacher lesender Feldzugriff ein Metho-denruf ist, wäre die Sprache durch diese Forderung auf unakzeptable Weise eingeschränkt worden.

Alternativ zu dieser Strategie wurde vorgeschlagen, dass Programmen eine statische Bedin-gung auferlegt wird, in continuous signals keine Zustandsänderungen vorzunehmen. Die Be-stimmung, ob ein System diese Bedingung erfüllt, kommt allerdings im Allgemeinen dem Halteproblem gleich, weshalb von dieser Forderung wieder Abstand genommen wurde.

Schließlich wird nun in einer nicht-normativen Bemerkung im Text des SDL-Standards auf dieses Problem hingewiesen und erklärt, dass ein Programm, dass in den Ausdrücken von continuous signals Seiteneffekte enthält, undefiniertes Verhalten hat. Die formale Semantik-definition beschreibt das genauer: Die Berechnung des Ausdrucks kann beliebig oft erfolgen, bis er erfüllt ist.