98 KAPITEL 6: VERBESSERUNGSMÖGLICHKEITEN• asSet(value)Erstellt eine Menge, die nur das Element value enthält: M = {value}Dieser Operator ist besonders dann nützlich, wenn Mengen verwendet werden müssen, dieauf keinem anderen Weg deklariert werden können; beispielsweise kann eine Stringmenge{”str1”,”str2”} über den Ausdruckunion( asSet(”str1”), asSet(”str2”) )erhalten werden. Eine näherliegende Deklaration{ s:String | s = ”str1” or s = ”str2” }ist nicht zulässig, da über die Werte des unendlichen Typs String nicht iteriert werden kann(<strong>und</strong> auch, wenn dies möglich wäre, so wäre diese Deklaration u.U. sehr ineffizient).• unite( var:type, expression( var ) )Punktweise Auswertung eines Ausdrucks: für alle Belegungen von var wird der Ausdruckexpression ausgewertet <strong>und</strong> alle Ergebnisse zu einer Menge vereinigt:unite(var:type,expression(var)) =⋃var∈typeexpression( var )Wie der Operator asSet ist dieser Operator nützlich, um Mengen zu deklarieren, die nichtüber die Restriktion eines Datentyps erhalten werden können. Beispielsweise kann man demBenutzer alle Komponentennamen zur Auswahl anbieten:context compName: unite( c:Component, asSet( c.Name ) ).trueDie Abfragecontext compName:{ s:String |exists c:Component. c.Name = s}. trueüber die Restriktion des Typs String sieht auf den ersten Blick äquivalent aus, hat aber eineganz andere Wirkung: anstatt die Namen aller Komponenten in einer Liste zur Auswahlanzubieten, wird im Eingabedialog für diese Abfrage lediglich ein Eingabefeld für den Strings angezeigt – die Eingabe kann hier nur dann abgeschlossen werden, wenn der eingegebeneString gleich dem Namen einer existierenden Komponente ist.Die Operatoren union, intersection <strong>und</strong> difference sind mit geringem bis mittlerem Aufwandimplementierbar. Der Operator asSet ist sehr einfach zu implementieren. Die Implementierungvon unite ist von mittlerer Schwierigkeit.6.1.3 Dynamische Informationen in context-AbfragedialogenIn context-Abfragen kann in der aktuellen Version ein fest vorgegebener Hinweistext angezeigtwerden. Eine Verbesserungsmöglichkeit würde die Anzeige dynamischer Informationen darstellen,die von den aktuellen Variablenbelegungen abhängen, beispielsweise würde im Eingabedialog für dieAbfragecontext [ Hint=”Hinweistext” Info=”Anzahl der ausgewähltenPorts:”: size( portSet )] portSet:set Port. trueneben dem statischen Hinweistext auch die Größe der Portmenge angezeigt, die sich während derEingabe dynamisch ändern kann.
6.1 ERWEITERUNGEN DES SPRACHUMFANGS 996.1.4 Arithmetische DivisionBei der Auswertung von <strong>ODL</strong>-Abfragen ist es von essentieller Bedeutung, dass alle <strong>ODL</strong>-Terme eindefiniertes Ergebnis zurückgeben. Insbesondere dürfen auch die arithmetischen Ausdrücke nur totaleOperationen verwenden. Genau aus diesem Gr<strong>und</strong> unterstützt <strong>ODL</strong> zurzeit nur die arithmetischenOperationen Addition, Subtraktion <strong>und</strong> Multiplikation. Da die Division auf reellen Zahlen nur partielldefiniert ist, wurde sie bis jetzt nicht in den <strong>ODL</strong>-Sprachumfang aufgenommen.Damit die Division in <strong>ODL</strong> verwendet werden kann, muss sie totalisiert werden. Hierfür mussder Fall der Division durch Null gesondert behandelt werden: ein <strong>ODL</strong>-Ausdrück soll auch dannausgewertet werden können, wenn im Laufe der Auswertung eine Division durch Null auftritt.Um die Division zu totalisieren, erweitern wir ihre Wertemenge um den Wert <strong>und</strong>ef, der immerdann als Ergebnis eines Ausdrucks zurückgegeben wird, wenn das Ergebnis nicht definiert ist. Es giltdann div:Int × Int → Int ⋃ {<strong>und</strong>ef}, wobei a/0 = <strong>und</strong>ef für alle a ∈ Int ist.Ergibt ein arithmetischer Ausdruck anstatt einer Zahl den Wert <strong>und</strong>ef, so muss dieser bei derAuswertung des <strong>ODL</strong>-Terms besonders behandelt werden. Da arithmetische Ausdrücke in <strong>ODL</strong> nurinnerhalb von booleschen Termen vorkommen dürfen (s. Abschnitt 4.1), muss bei booleschen Termendie Möglichkeit berücksichtigt werden, dass das Ergebnis eines Operanden <strong>und</strong>ef ist. Dabei entstehtfolgendes Problem: das Ergebnis eines booleschen Terms kann darüber entscheiden, ob eine bestimmteTransformation am Modell durchgeführt wird oder nicht. Hierbei kann sowohl das Ergebnis trueals auch das Ergebnis false zu einer Transformation führen, abhängig davon, welches Termergebnisdas gewünschte ist. Wir wollen das am Beispiel zweier Abfragen demonstrieren:- exists c:Component.(size( c.Channels ) = 0 andresult has Name( c, ”NoChannels” ) )Diese Abfrage benennt alle Komponenten um, die keine Kanäle besitzen: eine Modelltransformationwird durchgeführt, wenn der Term size( c.Channels ) = 0 zu true ausgewertetwird. Das gewünschte Ergebnis, das zur Modelltransformation führt, ist hier also true.- exists c:Component.(neg size( c.Channels ) > 0 andresult has Name( c, ”NoChannels” ) )Diese Abfrage has diegleiche Auswirkung, wie die vorherige – nur wird hier eine Modelltransformationdann durchgeführt, wenn der Term size( c.Channels ) > 0 zu false evaluiert.Damit ist das gewünschte Ergebnis in diesem Fall false.Ein <strong>und</strong>efiniertes Ergebnis eines booleschen Terms darf nie zu einer Modelltransformation führen,denn ein <strong>und</strong>efiniertes Ergebnis ist in Wirklichkeit eine Exception im Laufe der Auswertung. Wieman an dem angeführten Beispiel sieht, kann das Ergebnis <strong>und</strong>ef weder wie true noch wie falsebehandelt werden, denn beide Ergebnisse können eine Änderung am Modell nach sich ziehen. Damitist zur korrekten Behandlung <strong>und</strong>efinierter Ergebnisse von booleschen Termen die Erweiterung deraktuell verwendeten Logik notwendig.Eine Möglichkeit besteht in der Verwendung einer dreiwertigen Logik, wie sie beispielsweisein SQL eingesetzt wird ([Kemper], S.110-111). Sie enthält neben den üblichen booleschen Wertentrue <strong>und</strong> false den Wert <strong>und</strong>ef (diesmal als logischen Wert) – dieser Wert tritt als Ergebnis einesbooleschen Ausdrucks auf, dessen Auswertung nicht erfolgreich durchgeführt werden konnte <strong>und</strong>dessen Ergebnis somit <strong>und</strong>efiniert ist. Für die dreiwertige Logik gelten die in Tabelle 6.1 aufgeführtenWahrheitstabellen. Die Verknüpfungen Implikation <strong>und</strong> Äquivalenz lassen sich auf die VerpknüpfungenAND, OR <strong>und</strong> NOT zurückführen, ihre Wahrheitstabellen werden aber der Vollständigkeit halberangegeben.Der Auswertungsalgorithmus für <strong>ODL</strong>-Ausdrücke bleibt für die Fälle, wo ein boolescher Term zutrue oder false ausgewertet wird, unverändert. Liefert ein Term als Ergebnis <strong>und</strong>ef zurück, sohängt die Vorgehensweise von dem aufrufenden Term ab: