|
| 1 | +# Definition der semantischen Spracheigenschaften von Mini-Python |
| 2 | + |
| 3 | +Ihre Umsetzung des Compiler-Frontends soll die in diesem Dokument definierten semantischen |
| 4 | +Sprachelemente der Sprache “Mini-Python” unterstützen. Als Grundlage werden die semantischen |
| 5 | +Sprachelemente der Sprache Python 3 verwendet. Da die gesamte Sprache zu umfangreich ist, |
| 6 | +wird in diesem Kapitel ein kleinerer und vereinfachter Sprachumfang festgelegt. |
| 7 | + |
| 8 | +Die syntaktischen Eigenschaften der Sprache “Mini-Python” und die Abweichungen zu Python 3 |
| 9 | +werden im Kapitel [Definition der syntaktischen Spracheigenschaften](syntax_definition.md) |
| 10 | +beschrieben. |
| 11 | + |
| 12 | +Einige Angaben zur Semantik sind für den AST und die Symboltabelle noch nicht relevant und |
| 13 | +werden erst bei der Verwendung des CBuilders wichtig. Um die Verwendung des CBuilders zu |
| 14 | +erleichtern, sollten Sie diese Punkte allerdings schon in der semantischen Analyse |
| 15 | +betrachten. |
| 16 | + |
| 17 | +Die Verwendung des CBuilders wird im Kapitel [Verwendung des CBuilders](usage_cbuilder.md) |
| 18 | +beschrieben. (Wird rechtzeitig ergänzt.) |
| 19 | + |
| 20 | +## Scopes |
| 21 | + |
| 22 | +Die Scopes sind im Vergleich zu Python 3 deutlich vereinfacht. Es gibt den globalen Scope, |
| 23 | +und es gibt weitere (lokale) Scopes für die Funktionen, für Klassen und Klassenobjekte |
| 24 | +(`self`). |
| 25 | + |
| 26 | +Die Hierarchie der Scopes kann an dem folgenden Graphen abgelesen werden: |
| 27 | + |
| 28 | +``` mermaid |
| 29 | +graph BT; |
| 30 | + Klasse_A-->Global; |
| 31 | + Funktion-->Global; |
| 32 | + Klasse_B_geerbt-->Klasse_B_super; |
| 33 | + Klasse_B_super-->Global; |
| 34 | + Objekt_A-->Klasse_A; |
| 35 | + Objekt_B_geerbt-->Klasse_B_geerbt; |
| 36 | + Objekt_B_super-->Klasse_B_super; |
| 37 | +``` |
| 38 | + |
| 39 | +Sollte das jeweilige Symbol nicht in einem Scope gefunden werden, muss im übergeordneten |
| 40 | +Scope danach gesucht werden. Dies erfolgt, bis der globale Scope erreicht wird. Eventuelle |
| 41 | +Besonderheiten zu den Scopes werden bei der jeweiligen Funktionalität in diesem Dokument |
| 42 | +beschrieben. |
| 43 | + |
| 44 | +## Objekte |
| 45 | + |
| 46 | +Wie in Python 3 werden intern alle Datentypen als Objekte der Klasse `Object` betrachtet. |
| 47 | +Zur Laufzeit soll eine dynamische Typisierung realisiert werden, d.h. die Variablen werden |
| 48 | +ohne Typdeklaration angelegt und können zur Laufzeit ihren Typ verändern. |
| 49 | + |
| 50 | +## Builtin-Datentypen |
| 51 | + |
| 52 | +Die in der syntaktischen Definition festgelegten [eingebauten |
| 53 | +Datentypen](syntax_definition.md#datentypen) sollen implizit angelegt werden können. Sie |
| 54 | +verhalten sich zur Laufzeit wie Objekte mit einem festgelegten Umfang unterstützter Methoden |
| 55 | +(u.a. `to_string`, Operatoren). |
| 56 | + |
| 57 | +``` python |
| 58 | +a = 1 # Integer |
| 59 | +b = "foo" # String |
| 60 | +c = True # Boolean |
| 61 | +``` |
| 62 | + |
| 63 | +## Funktionen |
| 64 | + |
| 65 | +Alle Funktionen besitzen einen eigenen Scope. In diesem müssen die Parameter sowie die in |
| 66 | +der Funktion definierten Variablen zugreifbar sein. |
| 67 | + |
| 68 | +Um eine Funktion zu verwenden, muss diese zuerst definiert werden. |
| 69 | + |
| 70 | +Es müssen nur einfache Funktionen unterstützt werden - verschachtelte Funktionen können Sie |
| 71 | +ignorieren. |
| 72 | + |
| 73 | +### Globale Builtin-Funktionen |
| 74 | + |
| 75 | +Die folgenden Funktionen sind immer vorhanden und global verfügbar. Abweichend zu den selbst |
| 76 | +definierten Funktionen müssen Builtin-Funktionen nicht vor der Verwendung definiert werden. |
| 77 | + |
| 78 | +| Python-Funktion | Beschreibung | Rückgabe | |
| 79 | +|:----------------|:---------------------------------------------------------------------|:---------| |
| 80 | +| `print()` | Gibt ein oder mehrere übergeben String-Literale auf der Konsole aus. | `void` | |
| 81 | +| `input()` | Liest eine Zeile von der Konsole ein. | `String` | |
| 82 | + |
| 83 | +### Funktionen für Builtin-Datentypen |
| 84 | + |
| 85 | +Die Funktionen für Builtin-Datentypen verhalten sich intern wie Methodenaufrufe auf dem |
| 86 | +Datenobjekt. Sie können unter der Verwendung der passenden Methodennamen auch für Klassen |
| 87 | +überladen werden. Die folgende Liste stellt die unterstützten Datentypen sowie die |
| 88 | +Methodennamen dar: |
| 89 | + |
| 90 | +| Python-Funktion | Beschreibung | Integer | String | Boolean | Methodenname | |
| 91 | +|:----------------|:---------------------------------------------------------------|:-------:|:------:|:-------:|:------------:| |
| 92 | +| `str()` | Gibt die String Representation des übergebenen Objekts zurück. | ✓ | ✓ | ✓ | `__str__` | |
| 93 | +| `int()` | Cast zu Integer | ✗ | ✓ | ✓ | `__int__` | |
| 94 | + |
| 95 | +Der CBuilder unterstützt keine direkte Übergabe dieser Funktionen, sondern erwartet die |
| 96 | +Übergabe als Methodenaufruf auf dem Datenobjekt. Sie können diese Funktionsaufrufe bereits |
| 97 | +bei der semantischen Analyse durch passende Methodenaufrufe ersetzen. |
| 98 | + |
| 99 | +``` python |
| 100 | +a = "5" |
| 101 | + |
| 102 | +b = int(a) # Verwendung als Funktion |
| 103 | +b = a.__int__() # äquivalent als Methodenaufruf |
| 104 | +``` |
| 105 | + |
| 106 | +## Operatoren |
| 107 | + |
| 108 | +Die Builtin-Datentypen unterstützen jeweils nur einige der vorhandenen Operatoren. Zudem |
| 109 | +sind die Operatoren für die Builtin-Datentypen nur jeweils für die Verwendung mit den selben |
| 110 | +Datentypen vorgesehen. |
| 111 | + |
| 112 | +Für Klassen können alle Operatoren überladen werden, indem die Methode für den jeweiligen |
| 113 | +Operator implementiert wird (beispielsweise `__add__()` für den Operator `+`, siehe unten). |
| 114 | + |
| 115 | +Im Folgenden sehen Sie Listen, welche Operatoren von welchen Datentypen unterstützt werden |
| 116 | +sollen. Hier sind auch die Methodennamen zur Verwendung bei Klassen mit angegeben. |
| 117 | + |
| 118 | +Der CBuilder unterstützt keine direkte Übergabe von Operatoren, sondern erwartet die |
| 119 | +Übergabe als Methodenaufruf auf dem linken Wert (Objekt) mit dem rechten Wert (Objekt) als |
| 120 | +Parameter. Sie können also bereits bei der semantischen Analyse die Operatoren durch |
| 121 | +passende Methodenaufrufe ersetzen. |
| 122 | + |
| 123 | +Der Zuweisungsoperator und die logischen Operatoren besitzen explizite Aufrufe und müssen |
| 124 | +nicht umgewandelt werden. |
| 125 | + |
| 126 | +``` python |
| 127 | +a = 3 |
| 128 | +b = 4 |
| 129 | + |
| 130 | +c = a + b # Verwendung eines Operators |
| 131 | +c = a.__add__(b) # äquivalent als Methodenaufruf |
| 132 | +``` |
| 133 | + |
| 134 | +### Logische Operatoren |
| 135 | + |
| 136 | +Die logischen Operatoren stellen eine Abweichung dar und sollen nicht in Methodenaufrufe |
| 137 | +umgewandelt werden. Im CBuilder sind dafür explizite Aufrufe vorgesehen. |
| 138 | + |
| 139 | +In Python 3 können Sie über die Methode `__bool__` Bool-Werte für eigenen Klassen |
| 140 | +implementieren. Allerdings wird die Methode `__bool__` dabei nicht implizit aufgerufen. Sie |
| 141 | +müssen diese Methode explizit aufrufen. Überlegen Sie sich, wie Sie den Methodenaufruf von |
| 142 | +`__bool__` dennoch vor dem Nutzer ihres Compilers verbergen können. |
| 143 | + |
| 144 | +| Operation | Operator | Integer | String | Boolean | |
| 145 | +|:------------|:--------:|:-------:|:------:|:-------:| |
| 146 | +| Disjunktion | `or` | ✗ | ✗ | ✓ | |
| 147 | +| Konjunktion | `and` | ✗ | ✗ | ✓ | |
| 148 | +| Negation | `not` | ✗ | ✗ | ✓ | |
| 149 | + |
| 150 | +### Vergleichsoperatoren |
| 151 | + |
| 152 | +| Operation | Operator | Integer | String | Boolean | Methodenname | |
| 153 | +|:---------------|:--------:|:-------:|:------:|:-------:|:------------:| |
| 154 | +| Gleichheit | `==` | ✓ | ✓ | ✓ | `__eq__` | |
| 155 | +| Ungleichheit | `!=` | ✓ | ✓ | ✓ | `__ne__` | |
| 156 | +| Größer gleich | `>=` | ✓ | ✓ | ✗ | `__ge__` | |
| 157 | +| Größer | `>` | ✓ | ✓ | ✗ | `__gt__` | |
| 158 | +| Kleiner gleich | `<=` | ✓ | ✓ | ✗ | `__le__` | |
| 159 | +| Kleiner | `<` | ✓ | ✓ | ✗ | `__lt__` | |
| 160 | + |
| 161 | +### Arithmetische Operatoren |
| 162 | + |
| 163 | +| Operation | Operator | Integer | String | Boolean | Methodenname | |
| 164 | +|:-------------------------------------|:--------:|:-------:|:------:|:-------:|:------------:| |
| 165 | +| Addition / String-Literal-Verkettung | `+` | ✓ | ✓ | ✗ | `__add__` | |
| 166 | +| Subtraktion / negative Werte | `-` | ✓ | ✗ | ✗ | `__sub__` | |
| 167 | +| Multiplikation | `*` | ✓ | ✗ | ✗ | `__mul__` | |
| 168 | +| Division | `/` | ✓ | ✗ | ✗ | `__div__` | |
| 169 | + |
| 170 | +## Klassen |
| 171 | + |
| 172 | +Die Klassen müssen wie die Funktionen vor der Verwendung definiert werden. |
| 173 | + |
| 174 | +Alle Klassen besitzen einen eigenen Scope in dem die Methoden definiert sind. Der |
| 175 | +übergeordnete Scope von Klassen ist der Scope der Superklasse oder der globale Scope. |
| 176 | + |
| 177 | +Statische Methoden und Attribute müssen nicht unterstützt werden. |
| 178 | + |
| 179 | +### Konstruktor |
| 180 | + |
| 181 | +Alle Klassen erben implizit von `Object`. |
| 182 | + |
| 183 | +Die Objekte von Klassen sollen wie in Python 3 üblich über den Konstruktor, also die Methode |
| 184 | +`__init__`, erzeugt werden. Der Aufruf des Konstruktors der Superklasse soll im Gegensatz zu |
| 185 | +Python 3 vereinfacht und abweichend realisiert werden. Dieser Aufruf entspricht syntaktisch |
| 186 | +einem Funktionsaufruf mit einer Parameterliste, die auch leer sein kann. Semantisch ist |
| 187 | +dieser Aufruf allerdings ein Sonderfall und entspricht dem Aufruf des nächst höheren |
| 188 | +Superkonstruktors für das aktuell zu erzeugende Objekt. |
| 189 | + |
| 190 | +``` python |
| 191 | +class A: |
| 192 | + def __init__(self, x): |
| 193 | + ... |
| 194 | + #end |
| 195 | +#end |
| 196 | + |
| 197 | +class B(A): |
| 198 | + def __init__(self, x): |
| 199 | + super(x) |
| 200 | + #end |
| 201 | +#end |
| 202 | +``` |
| 203 | + |
| 204 | +Der CBuilder erwartet für alle Klassen die Methode `__init__` mit dem Aufruf des |
| 205 | +Konstruktors der Superklasse als erste Anweisung. Sie können also zur Vorbereitung für den |
| 206 | +nächsten Schritt bereits bei allen Klassen die Methode `__init__` mit dem Aufruf von |
| 207 | +`super()` ergänzen. |
| 208 | + |
| 209 | +Klassen ohne selbst definierte Superklasse müssen im CBuilder explizit von der Klasse |
| 210 | +`__MPyType_Object` erben. |
| 211 | + |
| 212 | +### Klassenobjekte |
| 213 | + |
| 214 | +Klassenobjekte besitzen jeweils einen eigenen Scope, der über das Schlüsselwort `self` |
| 215 | +zugreifbar ist. |
| 216 | + |
| 217 | +``` python |
| 218 | +class A: |
| 219 | + def __init(self, x): |
| 220 | + self.x = x |
| 221 | + #end |
| 222 | + |
| 223 | + def foo(self): |
| 224 | + return self.x |
| 225 | + #end |
| 226 | +#end |
| 227 | +``` |
| 228 | + |
| 229 | +### Methoden |
| 230 | + |
| 231 | +Die Methoden verhalten sich im Wesentlichen wie Funktionen. Folgende Unterschiede zu |
| 232 | +Funktionen müssen beachtet werden: |
| 233 | + |
| 234 | +1. Bei der Definition von Methoden muss der Parameter `self` immer als erster Parameter |
| 235 | + definiert/übergeben werden. |
| 236 | + |
| 237 | + Somit wird nicht wie in Python 3 der erste Parameter implizit als Objektreferenz |
| 238 | + interpretiert, sondern immer der erste Parameter mit dem festgelegten Namen `self`. |
| 239 | + |
| 240 | +2. Abweichend zu Funktionen sind Methoden immer Aufrufe auf einem Objekt und besitzen als |
| 241 | + übergeordneten Scope den Scope ihrer Klasse bzw. den Scope des Objekts, falls auf `self` |
| 242 | + zugegriffen wird. |
| 243 | + |
| 244 | +3. Beim Aufruf von Methoden darf der Parameter `self` im Gegensatz zur Definition nicht |
| 245 | + vorhanden sein bzw. übergeben werden. Der CBuilder ergänzt `self` implizit mit der |
| 246 | + Objektreferenz, auf dem die Methode aufgerufen wurde. |
0 commit comments