Ausdrücke
Inhaltsverzeichnis
1. Ausdrücke
Ausdrücke sind Formeln, die ein berechnetes Ergebnis liefern.
Diese Formel kann aus einem einzelnen Operanden (Konstante, Variable
oder Funktion) bestehen oder aber mehreren Operanden,
die mit Operatoren verknüpft sind.
Bei Ausdrücken wird auch nach ihren Ergebnistyp unterschieden.
So sind z.B mit numerischen Ausdrücken alle Ausdrücke gemeint, die ein
numerisches Ergebnis (INT32, INT32 oder FLOAT, siehe auch isNum()) haben.
Eine Besonderheit sind Variablenausdrücke, die eine andere Sysntax
und Semantik haben und denen daher ein eigenes Kapitel gewidmet ist.
Bei der Auswertung wird der gesamte Ausdruck compiliert,
d.h. in ein optimiertes internes Format übersetzt.
Teilausdrücke der Operanden '&&', '||' und '?:' werden nur ausgewertet,
wenn sie noch relevant für den Gesammtausdruck sind.
Bei der Compilierung werden konstante Teilausdrücke optimiert;
dieses schließt deterministische Funktionen mit ein.
So wird z.B. 'sqrt(4)*3*A' zu '2*3*A' und anschließend weiter zu '6*A' optimiert.
Da gleichwertige Operatoren streng von links nach rechts berechnet werden,
können Ausdrücke wie z.B. '2*A*3' nicht optimiert werden.
Dazu müßten die Faktoren umgestellt und evtl. geklammert werden: 'A*(2*3)'.
Optimierungen werden insbesondere dort eingesetzt,
wo ein Ausdruck mehrfach zu Berechnung herangezogen wird.
(siehe unten)
1.1 Auswertung und Berechnung
Bei der Auswertung eines Ausdruckes wird diese Compiliert
und ein P-Code Programm mit den folgenden Eigenschaften erstellt:
-
Die Operationen werden so umgestellt, dass die Formel ohne spezielle
Klammern als Postfix-Notation angegeben werden kann.
Beispiel: aus 'A + B * C' wird 'A B C * +'
-
Die Operationen laufen (mit wenigen Ausnahmen) alle über einen Stack.
So wird z.B. aus 'A := A + B' der P-Code '"A" A B + := ',
was bedeutet:
- Lege Name "A" auf den Stack.
- Kopiere Wert der Variablen A auf den Stack.
- Kopiere Wert der Variablen B auf den Stack.
- Führe Addition mit den beiden letzten Werten des Stacks aus.
Diese beiden Werte werden entfernt und die Summe auf dem Stack abgelegt.
- Führe eine Variablen-Zuweisung aus. Nehme dabei Name und Wert vom Stack.
Ist jetzt A eine Liste oder Map mit vielen Elementen, dann wird eine Kopie
aller Element auf den Stack gelegt, obwohl der Wert von A nicht mehr benötigt wird.
Hierfür gibt es die Funktion move(A),
die den Wert von A auf den Stack verschiebt und gleichzeitig in A den Wert @NONE
hinterläßt; es wird also keine aufwendige Kopie erzeugt.
Bei der Zuweisung einer Variablen wird automatisch und implizit move() verwendet,
wenn das Ergebnis einer Zuweisung nicht mehr benötigt wird.
-
Gerade bei großen LISTEN und MAPS kann die Kopiererei der Werte sehr aufwendig sein.
Daher gibt es die Funktionen l$*() und m$*(),
die eine Liste oder Map bearbeiten, diese aber nicht als Ergebnis liefern.
1.2 Variablenausdrücke
Ein Variablenausdruck ist ähnlich wie die anderen Ausdrücke.
Als Operanden sind jedoch nur Variablennamen zugelassen.
Mit diesen Ausdrücken soll überprüft werden,
ob Variablen oder Kombinationen von Variablen definiert sind.
Als Vorzeichen ist nur das Minuszeichen '-'
und als Operatoren sind nur '&' und '|' zugelassen.
Außerdem ist die Klammerung '(...)' und die Verwendung von Funktionen möglich.
Ist eine Variable definiert, so ergibt das den Wert WAHR (==1),
andernfalls ist sie undefiniert und ergibt den Wert FALSCH (==0).
Durch das '-' vor dem Variablen wird diese Aussage invertiert.
Jedes neue Ergebnis wird mit dem vorherigen Ergebnis logisch
mit UND ('&') oder ODER ('|') verknüpft,
wobei UND gegenüber ODER eine höhere Priorität hat,
genauso wie '*' bei numerischen Ausdrücken ein höhere Priorität gegenüber '+' hat.
Teilausdrücke können mittels '()' geklammert werden.
Vor den Klammern darf auch '-' stehen
um die Aussage des Teilausdruckes zu invertieren.
Funktionen sind eine Schnittstelle zu den normalen Ausdrücken
und werden wie gewohnt durchgerechnet.
Anschließend wird das Ergebnis mittels bool() in einen Wahrheitswert gewandelt.
Umgekehrt können Variablenausdrücke in normalen Ausdrücken
durch die Funktion def() bzw. defined() verwendet werden.
1.2.1 Beispiele
Es sei die Variable 'W' definiert und die Variable 'F' undefiniert.
Beispiele für Variablenausdrücke |
Ausdruck |
Ergebnis |
Bemerkung |
F |
false |
- |
W |
true |
- |
-F |
true |
- |
-W |
false |
- |
F | W |
true |
- |
-( F | W ) |
false |
- |
F & W |
false |
- |
-( F & W ) |
true |
- |
-F & W |
true |
- |
W | W & F |
true |
- |
( W | W ) & F |
false |
- |
int(1+2) |
false |
numerisches Ergebnis == 3 <> 0 |
int(2-6/3) |
false |
numerisches Ergebnis == 2 - 2 == 0 |
2. Optimierungen
Bei der Auswertung von Ausdrücken werden diese vor der eigentlichen
Berechnung in ein internes Format übersetzt.
Diese Übersetzung kann dann einmal oder mehrfach ausgewertet werden.
Bei der mehrfachen Auswertung wird eine Optimierung eingesetzt,
damit unveränderliche Operationen nur einmal während der Übersetzung
berechnet werden müssen.
Beispiel: Aus 'a=4, 3*a*x' wird '12*x'.
Bei der Optimierung werden Operatoren und deterministische Funktionen,
bei denen alle Parameter Konstanten sind, sofort berechnet
und durch das Rechenergebnis ersetzt.
Bei der Optimierung werden keine Umstellungen vorgenommen.
Da bei Operatoren mit gleicher Priorität die Berechnung von links nach rechts erfolgt,
können Ausdrücke wie z.B. '3*X*4' nicht optimiert werden.
Stattdessen sollte entweder '3*4*X' oder 'X*(3*4)' verwendet werden.
2.1 Beispiele
Beispiele für Optimierungen |
vor Optimierung |
nach Optimierung |
Bemerkungen |
3+4+x |
7+x |
- |
3+x+4 |
3+x+4 |
Umstellungen werden nicht vorgenommen |
x+3+4 |
x+3+4 |
Berechne zuerst x+3 --> keine Optimierung |
x+(3+4) |
x+7 |
Optimierung wegen Klammerung |
a=4,max(1,a) |
4 |
a wird zur Konstanten --> Optimierung |
max(1,4,x) |
max(1,4,x) |
Ein Parameter unbekannt --> keine Optimierung |
max(max(1,4),x) |
max(4,x) |
Inneres max() kann optimiert werden |
sin(pi()/2) |
1.0 |
Sinus einer Konstanten --> Optimierung |
3. Referenzen
Siehe auch:
Operanden
Operatoren
Vorzeichen
Variablen