4D v16.3

Compiler Direktiven

Home

 
4D v16.3
Compiler Direktiven

Compiler Direktiven  


 

4D kennt drei Variablentypen:

  • Lokale Variablen,
  • Prozessvariablen,
  • Interprozessvariablen.

Weitere Informationen dazu finden Sie im Abschnitt Variablen. Prozess- und Interprozessvariablen sind von der Struktur her dasselbe für den Compiler.

Da der Compiler nicht den Prozess bestimmen kann, in welchem die Variable verwendet wird, sollten Sie Prozessvariablen mit mehr Bedacht als Interprozessvariablen verwenden. Alle Prozessvariablen werden systematisch dupliziert, wenn ein neuer Prozess beginnt. Eine Prozessvariable kann in jedem Prozess einen anderen Wert haben, sie ist dagegen für die gesamte Datenbank vom gleichen Typ.

Alle Variablen haben einen Typ. Wie im Abschnitt Datentypen beschrieben, gibt es folgende Typen:

Boolean
Datum
Lange Ganzzahl
Diagramm
Zeit
Bild
Numerisch (oder Zahl)
Zeiger
Text
BLOB
Objekt

Es gibt verschiedene Typen von Arrays:

Boolean
Datum
Ganzzahl
Lange Ganzzahl
Bild
Zahl
Zeit
Objekt
Zeiger
BLOB
Text

Hinweise:
- Der Typ Objekt ist seit 4D v14 verfügbar.
- Die älteren Typen Alpha (fester String) und Ganzzahl werden für Variablen nicht mehr verwendet. In vorhandenem Code werden sie automatisch umgeleitet zu den Typen Text und Lange Ganzzahl.

Im interpretierten Modus kann sich der Datentyp einer Variablen ändern. Das ist möglich, da der Code interpretiert und nicht kompiliert wird. 4D interpretiert jede Anweisung separat und versteht ihren Kontext.
Im kompiliertem Modus ist die Situation anders. Während die Interpretation Zeile für Zeile abläuft, betrachtet der Kompilierungsprozess die Datenbank in ihrer Gesamtheit.

Der Compiler arbeitet folgendermaßen:

  • Er analysiert systematisch die Objekte in der Datenbank. Das sind Datenbank-, Projekt-, Formular-, Objektmethoden und Trigger.
  • Er durchläuft die Objekte, um den Datentyp jeder in der Datenbank verwendeten Variablen zu bestimmen und generiert eine Tabelle mit den Variablen und Methoden. Das ist die Symboldatei.
  • Sind die Datentypen von allen Variablen festgelegt, übersetzt bzw. kompiliert der Compiler die Datenbank. Das ist jedoch nur möglich, wenn er den Datentyp für jede der Variablen bestimmen kann.

Trifft der Compiler auf denselben Variablennamen für zwei unterschiedliche Datentypen, kann er keine Entscheidung treffen. Er muss nämlich, um ein Objekt zu typisieren und eine Speicheradresse zu vergeben, die exakte Kennung dieses Objekts wissen, d.h. Name und Datentyp. Der Compiler erstellt für jede kompilierte Datenbank eine Übersicht, die für jede Variable Name (oder Identifier) und Platzierung (oder Speicheradresse) sowie den gemäß dem Datentyp belegten Platz angibt. Diese Übersicht heißt Symboldatei. In den Einstellungen der Datenbank können Sie festlegen, ob diese Übersicht während dem Kompilieren in Form einer Textdatei angelegt werden soll.
Diese Übersicht wird auch für die automatische Erstellung von Compiler-Methoden verwendet.

Soll der Compiler die Typisierung Ihrer Variablen prüfen oder sie selbst typisieren, ist die Platzierung der Direktiven einfach. Sie können je nach Ihrer Arbeitsweise zwischen zwei Möglichkeiten wählen:

  • Sie verwenden die Direktive in der Methode, wo die Variable zuerst erscheint, das hängt auch davon ob, ob es eine lokale, Prozess- oder Interprozessvariable ist. Stellen Sie sicher, dass die Direktive beim ersten Auftreten der Variablen in der zuerst auszuführenden Methode verwendet wird. Bedenken Sie, dass der Compiler beim Kompilieren die Methoden in der Reihenfolge hernimmt, wie sie in 4D erstellt wurden und nicht in der Reihenfolge, wie sie im Explorer angezeigt werden.
  • Bei systematischer Arbeitsweise gruppieren Sie alle Prozess- und Interprozessvariablen mit den verschiedenen Compiler Direktiven in der Datenbankmethode On Startup oder in einer Methode, die von der Datenbankmethode On Startup aufgerufen wird.
    Für lokale Variablen gruppieren Sie die Direktiven an den Anfang der Methode, in welcher sie erscheinen.

Werden Variablen über eine Compiler Direktive typisiert, erhalten sie einen Standardwert, den sie während der Sitzung beibehalten, solange sie nicht zugewiesen sind.

Der Standardwert richtet sich nach Variablentyp und -kategorie, Ausführungskontext (interpretiert oder kompiliert), und im kompilierten Modus nach den definierten Optionen auf der Seite Compiler der Datenbank-Eigenschaften: 

  • Prozess- und Interprozessvariablen werden immer auf "auf Null" gesetzt, d.h. je nach Kontext, "0", Leerstring, leeres Blob, Nil pointer, leeres Datum (0000-00-00), etc.
  • Lokale Variablen werden wie folgt gesetzt:
    • im interpretierten Modus: auf Null
    • im kompilierten Modus, je nach gewählter Option für Lokale Variablen initialisieren auf der Seite Compiler der Datenbank-Eigenschaften:
      • auf Null, wenn "auf Null" gewählt ist,
      • auf einen zufälligen Wert, wenn "auf zufälligen Wert" gewählt ist (0x72677267 für Zahlen und Zeiten, immer True für Booleans, sonst genauso wie bei "auf Null",
      • auf einen zufälligen Wert (für Zahlen) wenn "NIcht" gewählt ist. 

Nachfolgende Tabelle zeigt diese Standardwerte:

TypInterprozessProzessLokal interpretiertLokal kompiliert "auf Null"Lokal kompiliert "zufällig"Lokal kompiliert "nicht"
BooleanFalseFalseFalseFalseTrueTrue (variiert)
Datum00-00-0000-00-0000-00-0000-00-0000-00-0000-00-00
Lange Ganzzahl00001919382119909540880 (variiert)
Diagramm00001919382119775946656 (variiert)
Zeit00:00:0000:00:0000:00:0000:00:00533161:41:59249345:34:24 (variiert)
BildBildgröße=0Bildgröße=0Bildgröße=0Bildgröße=0Bildgröße=0Bildgröße=0
Zahl00001.250753659382e+2431.972748538022e-217 (variiert)
ZeigerNil=trueNil=trueNil=trueNil=trueNil=trueNil=true
Text""""""""""""
BlobBlobgröße=0Blobgröße=0Blobgröße=0Blobgröße=0Blobgröße=0Blobgröße=0
Objektundefiniertundefiniertundefiniertundefiniertundefiniertundefiniert

Compiler Direktiven sind in folgenden Fällen sinnvoll:

  • Der Compiler kann den Datentyp einer Variablen nicht aus ihrem Kontext bestimmen,
  • Sie möchten nicht, dass der Compiler den Typ einer Variablen über ihre Verwendung bestimmt.

Außerdem sorgen Compiler Direktiven für eine Verringerung der Kompilierungszeit.

Manchmal kann der Compiler den Datentyp einer Variablen nicht bestimmen. Ist dies der Fall, generiert er eine entsprechende Fehlermeldung.
Es gibt drei Hauptgründe, die den Compiler den Datentyp nicht bestimmen lassen: Mehrfache Datentypen, Zweideutigkeit aufgrund einer gefolgerten Ableitung und keine Möglichkeit zur Bestimmung des Datentyps.

Mehrfache Datentypen
Hat eine Variable in den einzelnen Anweisungen unterschiedliche Datentypen, generiert der Compiler einen Fehler, der leicht zu beheben ist. Der Compiler wählt die zuerst gefundene Variable und weist deren Datentyp wilkürlich dem nächsten Auftreten der gleichnamigen Variablen mit einem anderen Datentyp zu. Hier ein einfaches Beispiel:

In Methode A

 
 Variable:=True

In Methode B

 Variable:="Der Mond ist rund"


Wird Methode A vor Methode B kompiliert, bewertet der Compiler die Anweisung Variable:="Der Mond ist rund" als Änderung des Datentyps gegenüber der zuvor gefundenen Variablen. Der Compiler meldet, dass eine Retypisierung stattgefunden hat und erstellt eine Fehlermeldung. In den meisten Fällen können Sie das Problem beheben, indem Sie das zweite Auftreten der Variablen umbenennen.

Zweideutigkeit aufgrund einer gefolgerten Ableitung
In manchen Fällen kann der Compiler anhand des Ablaufs ableiten, dass der Typ des Objekts nicht geeignet ist. In diesem Fall müssen Sie die Variable explizit mit einer Compiler Direktiven typisieren. Es folgt ein Beispiel, das mit Standardwerten für ein aktives Objekt arbeitet:

Sie können in einem Formular für folgende Objekte Standardwerte zuweisen: Combo Boxen, PopUp Menüs, Registerkarten, DropDown Listen, Menü/DropDown Listen und rollbare Bereiche unter Verwendung der Schaltfläche Bearbeiten für die Liste Werte (in der Eigenschaftenliste unter dem Thema Eingabekontrollen). Weitere Informationen dazu finden Sie im Abschnitt Standardwerte des Handbuchs 4D Designmodus. Die Standardwerte werden automatisch in ein Array geladen, das denselben Namen wie das Objekt hat.
Wird das Objekt nicht in einer Methode verwendet, kann der Compiler den Typ eindeutig als Array vom Typ Text ableiten.
Muss jedoch eine Initialisierung der Anzeige durchgeführt werden, könnte die Sequenz folgendermaßen lauten:

 Case of
    :(Form event=On Load)
       MyPopUp:=2
       ...
 End case

In diesem Fall tritt die Zweideutigkeit ein––beim Analysieren der Methoden leitet der Compiler für das Objekt MyPopUp als Datentyp Zahl ab. In diesem Fall ist es notwendig, das Array in der Formular- oder einer Compiler-Methode explizit zu deklarieren:

 Case of
    :(Form event=On Load)
       ARRAY TEXT(MyPopUp;2)
       MyPopUp:=2
       ...
 End case


Keine Möglichkeit zur Bestimmung des Datentyps
Dieser Fall tritt ein, wenn eine Variable ohne Typisierung in einem Kontext verwendet wird, der keine Angaben zum Datentyp liefert. Hier kann nur eine Compiler Direktive dem Compiler helfen. Dieses Phänomen tritt hauptsächlich in vier Kontexten auf:
  • bei Verwendung von Zeigern (Pointer),
  • wenn Sie einen Befehl mit mehr als einer Syntax verwenden,
  • wenn Sie einen Befehl mit optionalen Parametern mit unterschiedlichen Datentypen verwenden,
  • bei Verwendung einer 4D Methode, die über eine URL aufgerufen wird.
Zeiger
Von einem Zeiger wird nicht erwartet, dass er etwas anderes als seinen eigenen Datentyp zurückgibt.

Nehmen wir folgende Sequenz:
 Var1:=5.2(1)
 Zeiger:=->Var1(2)
 Var2:=Zeiger->(3)

Obwohl (2) den Variablentyp definiert, auf den der Zeiger zeigt, ist der Typ von Var2 nicht festgelegt. Der Compiler erkennt während der Kompilation zwar einen Zeiger, hat jedoch keine Möglichkeit, zu erkennen, auf welchen Variablentyp er zeigt. Deshalb kann er den Datentyp von Var2 nicht ableiten. Hier ist eine Compiler Direktive erforderlich, zum Beispiel C_REAL(Var2).

Befehle mit mehrfacher Syntax
Verwenden Sie eine Variable, der die Funktion Year of zugewiesen wurde, kann die Variable naturgemäß nur vom Typ Datum sein. Die Dinge liegen jedoch nicht immer so einfach. Nehmen wir folgendes Beispiel:

Der Befehl GET FIELD PROPERTIES lässt zwei Syntax-Arten zu:
GET FIELD PROPERTIES(TabelleNum;FeldNum;Typ;Länge;Indiziert)
GET FIELD PROPERTIES(FeldPtr;Typ;Länge;Indiziert)

Bei einem Befehl mit mehrfacher Syntax kann der Compiler nicht erraten, welche Syntax und Parameter Sie gewählt haben. Hier müssen Sie Compiler Direktiven einsetzen, um die im Befehl übergebenen Variablen zu typisieren, wenn diese nicht bereits an anderer Stelle in der Datenbank aufgrund ihrer Verwendung typisiert wurden.

Befehle mit optionalen Parametern mit unterschiedlichen Datentypen
Bei einem Befehl mit mehreren optionalen Parametern mit unterschiedlichen Datentypen kann der Compiler nicht bestimmen, welcher optionale Parameter verwendet wurde. Nehmen wir folgendes Beispiel:
Der Befehl GET LIST ITEM lässt zwei optionale Parameter zu; den ersten als Lange Ganzzahl, den zweiten als Boolean.

Der Befehl kann verwendet werden in Form von:
GET LIST ITEM(Liste;EintragPos;EintragRef;EintragText;Unterliste;Erweitert)

oder in Form von
GET LIST ITEM(
Liste;EintragPos;EintragRef;EintragText;Erweitert)
Hier müssen Sie Compiler Direktiven einsetzen, um die im Befehl übergebenen optionalen Variablen zu typisieren, wenn diese nicht bereits an anderer Stelle in der Datenbank aufgrund ihrer Verwendung typisiert wurden.

Über URL aufgerufene Methoden
Schreiben Sie 4D Methoden, die über eine URL aufgerufen werden müssen und verwenden Sie nicht $1 in der Methode, müssen Sie die Textvariable $1 explizit mit folgender Sequenz deklarieren:
C_TEXT($1)

In der Tat kann der Compiler nicht feststellen, ob die 4D Methode über eine URL aufgerufen wird.

Sind alle in der Datenbank vorkommenden Variablen explizit deklariert, muss der Compiler die Typisierung nicht überprüfen. In diesem Fall können Sie in den Einstellungen der Datenbank definieren, dass der Compiler nur die Übersetzung der Methode vornimmt. Das spart mindestens 50% an Zeit für die Kompilierung.

Über Compiler Direktiven können Sie Ihre Methoden beschleunigen. Weitere Informationen dazu finden Sie im Abschnitt Tipps zur Optimierung. Nehmen wir an, Sie müssen einen Zähler über eine lokale Variable erhöhen. Deklarieren Sie die Variable nicht, geht der Compiler vom Typ Zahl aus. Deklarieren Sie die Variable als Lange Ganzzahl, arbeitet die kompilierte Datenbank effizienter. Auf einem Rechner beansprucht der Typ Zahl 8 Bytes, deklarieren Sie den Zähler als Lange Ganzzahl, benötigt er nur 4 Bytes. Das Hochzählen eines 8-Byte Zählers dauert also länger als das eines 4-Byte Zählers.

Compiler Direktiven lassen sich auf zwei Arten verwalten, je nachdem ob der Compiler Ihre Variablen typisieren soll oder nicht.

Der Compiler muss die Kriterien zum Erkennen von Variablen beachten.
Es gibt zwei Möglichkeiten:

1) Wurden die Variablen nicht typisiert, kann der Compiler das automatisch erledigen. Er bestimmt nach Möglichkeit, d.h. solange keine Zweideutigkeit vorliegt, den Typ der Variablen, nach der Art ihrer Verwendung. Schreiben Sie z.B.

 V1:=True

bestimmt der Compiler für die Variable V1 als Datentyp Boolean.

Schreiben Sie:

 V2:="Dies ist ein einfacher Satz"

bestimmt der Compiler für die Variable V2 als Datentyp Text.

Der Compiler kann den Datentyp einer Variablen auch in nicht so klaren Situationen bestimmen:

 V3:=V1 `V3 ist vom selben Typ wie V1
 V4:=2*V2 `V4 ist vom selben Typ wie V2

Der Compiler bestimmt den Datentyp Ihrer Variablen auch über Aufrufe von 4D Befehlen und über Ihre Methoden. Übergeben Sie z.B. in einer Methode einen Parameter vom Typ Boolean und einen vom Typ Datum, weist der Compiler in der aufgerufenen Methode den lokalen Variablen $1 und $2 die Typen Boolean und Datum zu.

Bestimmt der Compiler den Datentyp durch Schlussfolgerung, weist er nie die eingrenzenden Typen Ganzzahl, Lange Ganzzahl oder Text zu, sondern standardmäßig immer den größtmöglichen Typ. Schreiben Sie z.B.:

 Nummer:=4

weist der Compiler als Datentyp Zahl zu, obwohl 4 eine Ganzzahl ist. Dadurch kann der Wert in einem anderen Zusammenhang auch den Wert 4,5 haben.
Ist es sinnvoll, eine Variable als Ganzzahl, Lange Ganzzahl oder Text zu typisieren, können Sie eine Compiler Directive verwenden. Der Vorteil dabei ist, dass diese Datentypen weniger Speicher belegen und Operationen damit rascher ablaufen.

Haben Sie Ihre Variablen typisiert und sind Sie sicher, dass Ihre Typisierung kohärent und vollständig ist, können Sie in den Einstellungen zum Kompilieren explizit festlegen, dass der Compiler diese Arbeit nicht mehr ausführen muss. Sollte Ihre Typisierung nicht hundertprozentig richtig sein, meldet der Compiler beim Kompilieren Fehler und nennt die erforderlichen Änderungen.

2) Über Befehle der Compiler Direktiven können Sie explizit die in Ihrer Datenbank verwendeten Variablen deklarieren.

Sie werden folgendermaßen verwendet:

 C_BOOLEAN(Var)

Solche Direktiven sagen dem Compiler, dass er eine Variable Var mit dem Typ Boolean anlegen soll. Eine Anwendung mit Compiler Direktiven erleichtert die Arbeit des Compilers und vermeidet Vermutungen. Eine Compiler Direktive hat Vorrang vor Ableitungen, die auf Anweisungen oder der Verwendungsart beruhen. Variablen, die mit der Compiler Direktive _o_C_INTEGER definiert wurden, sind in der Tat dasselbe wie Variablen mit der Compiler Direktive C_LONGINT. Das sind in beiden Fällen Lange Ganzzahlen zwischen –2147483648 und +2147483647.

Soll der Compiler Ihre Typisierung nicht prüfen, müssen Sie ihm einen Code vorgeben, um die Compiler Direktiven zu identifizieren.

Die Konvention ist folgende:
Compiler Direktiven für Prozess- und Interprozessvariablen und die Parameter sollten in einer oder mehreren Methoden gesetzt werden. Ihr Name muss mit dem Schlüsselwort Compiler beginnen.
Sie können mit dem Compiler standardmäßig fünf Arten von Compilermethoden generieren. Das sind die Direktiven für Variablen, Arrays und Methodenparameter. Weitere Informationen dazu finden Sie im Abschnitt Compilermethoden für ... des Handbuchs 4D Designmodus.

Hinweis: Die Syntax zum Deklarieren dieser Parameter lautet:
Direktive (MethodenName;Parameter). Sie lässt sich nicht im interpretierten Modus ausführen.

Besondere Parameter

  • Über Datenbankmethoden empfangene Parameter: Wurden diese Parameter nicht ausdrücklich deklariert, macht dies der Compiler. Wollen Sie diese deklarieren, müssen Sie das innerhalb der Datenbankmethoden ausführen. Sie können diese Parameter Deklaration nicht in einer Compiler Methode schreiben. Beispiel: Die Datenbankmethode On Web Connection empfängt sechs Parameter, $1 bis $6 vom Typ Text. Sie schreiben zu Beginn der Datenbankmethode: C_TEXT($1;$2;$3;$4;$5;$6)
  • Trigger: Der Parameter $0 (Lange Ganzzahl), welcher das Ergebnis eines Triggers ist, wird vom Compiler typisiert, wenn der Parameter nicht ausdrücklich deklariert wurde. Wollen Sie ihn deklarieren, müssen Sie das innerhalb des Triggers ausführen. Sie können diese Parameter Deklaration nicht in einer Compiler Methode schreiben.
  • Objekte mit dem Formularereignis “On Drag Over”: Der Parameter $0 (Lange Ganzzahl), welcher das Ergebnis des Formularereignisses “On Drag Over”ist, wird vom Compiler typisiert, wenn der Parameter nicht ausdrücklich deklariert wurde. Wollen Sie ihn deklarieren, müssen Sie das innerhalb der Objektmethode tun. Sie können diese Parameter Deklaration nicht in einer Compiler Methode schreiben. 
Hinweis: Der Compiler initialisiert nicht den Parameter $0. Sie müssen also, sobald Sie das Formularereignis "On Drag Over" verwenden, $0 initialisieren.

Beispiel
 C_LONGINT($0)
 If(Form event=On Drag Over)
    $0:=0
    ...
    If($DataType=Is picture)
       $0:=-1
    End if
    ...
 End if

Compiler Direktiven entfernen jede Zweideutigkeit bei Datentypen. Auch wenn eine gewisse Striktheit notwendig ist, muss das nicht heißen, dass der Compiler überhaupt keine Inkonsistenz toleriert.
Weisen Sie zum Beispiel einer Variablen, die als Ganzzahl deklariert wurde, einen Wert vom Typ Zahl zu, sieht der Compiler keinen Typkonflikt und weist die Werte gemäß Ihren Direktiven zu. Wenn Sie also schreiben:

 C_LONGINT(vInteger)
 vInteger:=2.6

betrachtet der Compiler das nicht als Konflikt des Datentyps, der eine Kompilierung verhindert; vielmehr rundet er einfach auf den nächstgelegenen Wert auf (3 anstatt 2.6).



Siehe auch 

Einzelheiten zur Syntax
Fehlermeldungen
Richtlinien zur Typisierung
Tipps zur Optimierung

 
EIGENSCHAFTEN 

Produkt: 4D
Thema: Compiler

 
GESCHICHTE 

 
ARTIKELVERWENDUNG

4D Programmiersprache ( 4D v16)
4D Programmiersprache ( 4D v16.1)
4D Programmiersprache ( 4D v16.2)
4D Programmiersprache ( 4D v16.3)