4D v16.3

Einzelheiten zur Syntax

Home

 
4D v16.3
Einzelheiten zur Syntax

Einzelheiten zur Syntax  


 

 

Der Compiler geht davon aus, dass die üblichen Syntaxregeln für 4D Befehle angewandt werden. Für Datenbanken, die kompiliert werden sollen, sind keine besonderen Änderungen erforderlich.

Dieser Abschnitt weist auf bestimmte Eigenheiten und spezifische Details hin:

  • Einige Befehle, die den Datentyp einer Variablen beeinflussen, können bei Unachtsamkeit zu Datenkonflikten führen.
  • Da manche Befehle verschiedene Arten von Syntax oder Parameter zulassen, ist es von Vorteil, zu wissen, welche Variante sich am besten eignet.

Strings  

Für Befehle, die mit Strings arbeiten, benötigt nur die Funktion Character code besondere Aufmerksamkeit. Im interpretierten Modus können Strings Zeichen beinhalten oder leer sein.
Im kompilierten Modus können Sie keinen leeren String übergeben.
Übergeben Sie einen leeren String und ist das in Character code übergebene Argument eine Variable, kann der Compiler beim Kompilieren keinen Fehler entdecken.

SEND Variable(Variable)
RECEIVE VARIABLE(Variable)

Diese beiden Befehle dienen zum Schreiben und Empfangen von Variablen, die an die Festplatte gesendet wurden. Variablen werden in diesen Befehlen als Parameter übergeben.
Der übergebene Parameter muss immer vom selben Datentyp sein. Nehmen wir an, Sie wollen eine Liste mit Variablen an eine Datei senden. Um auszuschließen, dass der Datentyp versehentlich geändert wird, empfehlen wir, den Datentyp der Variablen in der Titelzeile der Liste anzugeben. So erhalten Sie beim Empfangen der Variablen zu Beginn immer einen Indikator. Rufen Sie dann den Befehl RECEIVE VARIABLE auf, wird der Transfert über eine Case of Anweisung ausgeführt.

Beispiel:

 SET CHANNEL(12;"Datei")
 If(OK=1)
    $Type:=Type([Client]Total_TO)
    SEND VARIABLE($Type)
    For($i;1;Records in selection)
       $Send_TO:=[Client]Total_TO
       SEND VARIABLE($Send_TO)
    End for
 End if
 SET CHANNEL(11)
 SET CHANNEL(13;"MeineDatei")
 If(OK=1)
    RECEIVE VARIABLE($Type)
    Case of
       :($Type=Is string var)
          RECEIVE VARIABLE($String)
  `Empfangene Variable bearbeiten
       :($Type=Is real)
          RECEIVE VARIABLE($Real)
  `Empfangene Variable bearbeiten
       :($Type=Is text)
          RECEIVE VARIABLE($Text)
  `Empfangene Variable bearbeiten
    End case
 End if
 SET CHANNEL(11)

Field (field pointer) oder (table number;field Numerisch)
Table(table pointer)
oder (table Numerisch) oder (field pointer)

Diese beiden Funktionen geben Werte mit verschiedenen Datentypen zurück, abhängig von den übergebenen Parametern:
  • Übergeben Sie der Funktion Table einen Zeiger, ist das Ergebnis vom Typ Zahl
  • Übergeben Sie der Funktion Table eine Zahl, wird als Ergebnis ein Zeiger zurückgegeben.
    Beide Funktionen reichen für den Compiler nicht aus, um den Datentyp des Ergebnisses zu bestimmen. Verwenden Sie in solchen Fällen eine Compiler Direktive, um jegliche Zweideutigkeit auszuschließen.

Beachten Sie, dass Referenzen auf Dokumente, die von den Funktionen Open document, Append document und Create document zurückgegeben werden, vom Typ Zeit sind.

Math  

Mod (value;divider)

Der Ausdruck “25 modulo 3” lässt sich auf zwei Arten in 4D darstellen:
 Variable:=Mod(25;3)

oder

 Variable:=25%3

Der Compiler erkennt den Unterschied zwischen ihnen: Mod gilt für alle Zahlen, der Operator % dagegen nur für Ganzzahlen und Lange Ganzzahlen. Übersteigt der Operand die Reichweite des Typs Lange Ganzzahl, ist das zurückgegebene Ergebnis falsch.

IDLE
ON EVENT CALL (Methode{; ProzessName})
ABORT

Der Befehl IDLE wurde in die Programmiersprache von 4D integriert, um Ausnahmen zu verwalten. Verwenden Sie diesen Befehl in Verbindung mit dem Befehl ON EVENT CALL.

Sie können ihn als Direktive zur Ereignisverwaltung verwenden.
Nur der Kernel von 4D kann ein Systemereignis ausfindig machen. (Mausklick, Aktivität auf Tastatur, usw.). In den meisten Fällen werden Aufrufe des Kernel vom kompilierten Code selbst initiiert, in einer für den Benutzer transparenten Weise.

Wartet 4D dagegen passiv auf ein Ereignis –– zum Beispiel in einer Warteschleife –– ist klar, dass es keinen Aufruf geben wird.

  `Methode Mausklick
 If(MouseDown=1)
    <>vTest:=True
    ALERT("Jemand hat die Maustaste betätigt")
 End if
 
  `Methode Warten
 <>vTest:=False
 ON EVENT CALL("Mausklick")
 While(<>vTest=False)
  `Warteschleife für Ereignis
 End while
 ON EVENT CALL("")

In diesem Fall fügen Sie den Befehl IDLE folgendermaßen ein:

  `Methode Warten
 <>vTest:=False
 ON EVENT CALL("Mausklick")
 While(<>vTest=False)
    IDLE
  `Kernel Aufruf, um ein Ereignis aufzuspüren
 End while
 ON EVENT CALL("")
ABORT  

Verwenden Sie diesen Befehl nur in Projektmethoden zur Fehlerverwaltung. Er arbeitet genauso wie in 4D, außer in einer Methode, die von folgenden Befehlen aufgerufen wurde: EXECUTE FORMULA, APPLY TO SELECTION oder _o_APPLY TO SUBSELECTION. Versuchen Sie, derartige Situationen zu vermeiden.

Arrays  

Der Compiler bestimmt den Datentyp eines Array über folgende 4D Befehle:

COPY ARRAY(Quelle;Ziel)
SELECTION TO ARRAY(Feld;Array)
ARRAY TO SELECTION(Array;Feld)
SELECTION RANGE TO ARRAY(Start;Ende;Feld;Array)
LIST TO ARRAY(Auswahlliste;Array{; itemRefs})
ARRAY TO LIST(Array;Auswahlliste{; itemRefs})
DISTINCT VALUES(Feld;Array)

Dieser Befehl akzeptiert zwei Arten von Array-Parametern. Ist einer der Array-Parameter nicht an anderer Stelle deklariert, bestimmt der Compiler den Datentyp des nicht deklarierten Array anhand des deklarierten Typs.
Die Ableitung erfolgt auf zwei Arten:

  • Das typisierte Array ist der erste Parameter. Der Compiler weist den Datentyp des ersten Array in dem zweiten Array zu.
  • Das deklarierte Array ist der zweite Parameter. Der Compiler weist hier den Datentyp des zweiten Array dem ersten zu.

Da der Compiler bei Datentypen strikt ist, lässt sich COPY ARRAY nur von einem Array eines bestimmten Datentyps zu einem Array desselben Typs ausführen.
Wollen Sie also ein Array mit Elementen kopieren, die einen ähnlichen Datentyp haben, z.B. Ganzzahl, Lange Ganzzahl und Zahl oder Text und String oder Strings mit unterschiedlichen Längen, müssen Sie die Elemente einzeln kopieren.

Nehmen wir an, Sie wollen Elemente von einem Array Typ Ganzzahl zu einem Array Typ Zahl kopieren. Gehen Sie folgendermaßen vor:

 $Size:=Size of array(ArrInt)
 ARRAY REAL(ArrReal;$Size)
  `Setzen Sie für das Array Typ Zahl dieselbe Größe wie für das Array Typ Ganzzahl
 For($i;1;$Size)
    ArrReal{$i}:=ArrInt{$i}
  `Kopieren Sie jedes Element
 End for

Bedenken Sie, dass Sie während dem Prozess die Anzahl der Dimensionen eines Array nicht verändern können. Kopieren Sie ein eindimensionales Array in ein zweidimensionales Array, erzeugt der Compiler eine Fehlermeldung.

Diese Befehle müssen im interpretierten Modus nicht deklariert werden. Ein nicht typisiertes Array erhält den Datentyp des Feldes, das im Befehl angegeben ist.
Schreiben Sie:

 SELECTION TO ARRAY([MyTable]IntField;MyArray)

ist MyArray eindimensional mit dem Typ Lange Ganzzahl (in der Annahme, dass IntField vom Typ Ganzzahl ist).

Wurde das Array typisiert, stellen Sie sicher, dass das Datenfeld vom selben Datentyp ist. Ganzzahl, Lange Ganzzahl und Zahl sind zwar ähnliche Typen, jedoch nicht vollkommen gleich. Bei den Datentypen Text und String gibt es dagegen mehr Spielraum. Wurde ein Array nicht vorab typisiert und wenden Sie einen Befehl an, der als Parameter ein Feld vom Typ String enthält, wird dem Array standardmäßig als Typ Text zugewiesen. Wurde das Array zuvor als String bzw. Text typisiert, befolgen diese Befehle Ihre Direktiven.

Dasselbe gilt für Felder vom Typ Text –– Ihre Direktiven haben Vorrang.
Bedenken Sie, dass Sie die Befehle SELECTION TO ARRAY, SELECTION RANGE TO ARRAY, ARRAY TO SELECTION und DISTINCT VALUES nur in eindimensionalen Arrays verwenden können.

Der Befehl SELECTION TO ARRAY hat auch eine zweite Syntax, nämlich:
SELECTION TO ARRAY(Tabelle;Array).
In diesem Fall ist die Variable MyArray ein Array vom Typ Lange Ganzzahl. Dasselbe gilt auch für den Befehl SELECTION RANGE TO ARRAY.

Für die Befehle LIST TO ARRAY und ARRAY TO LIST treffen nur zwei Arten von Arrays zu:

  • Eindimensionales Array vom Typ String und
  • Eindimensionales Array vom Typ Text.
    Für diese Befehle muss das als Parameter übergebene Array nicht typisiert sein. Es wird standardmäßig als Array vom Typ Text typisiert. Wurde es zuvor als String bzw. Text typisiert, befolgen diese Befehle Ihre Direktiven.

Der Compiler kann keinen Datentyp aufspüren, wenn Sie in einem Befehl mit Array Deklaration einen dereferenzierten Zeiger als Parameter übergeben. Schreiben Sie:

 SELECTION TO ARRAY([Table]Field;Pointer->)

wobei Pointer-> für ein Array steht, kann der Compiler nicht prüfen, ob Feldtyp und Array-Typ identisch sind. Solche Konflikte müssen Sie selbst ausschliessen, indem Sie das Array typisieren, auf das sich der Zeiger bezieht.

Der Compiler zeigt eine Warnung, wenn er eine Anweisung mit einer Array-Deklaration findet, in der ein Parameter ein Zeiger ist. Diese Meldungen sind hilfreich beim Suchen solcher Datentypkonflikte.

Verwendet Ihre Datenbank lokale Arrays, d.h. sie werden nur in der Methode erkannt, in welcher sie erstellt wurden, müssen diese vor der Verwendung ausdrücklich in 4D typisiert werden.
Dazu verwenden Sie die Befehle für Arrays, z.B. ARRAY REAL, ARRAY INTEGER, etc.

Erstellt eine Methode z.B. ein lokales Array vom Typ Ganzzahl mit 10 Elementen, müssen Sie zuvor das Array wie folgt typisieren:

 ARRAY INTEGER($MyArray;10)

Get pointer(varName)
Typ (Objekt)
EXECUTE(statement)
TRACE
NO TRACE

Die Funktion Get pointer gibt einen Zeiger auf den ihm übergebenen Parameter zurück. Nehmen wir an, Sie möchten ein Array mit Zeigern initialisieren. Jedes Element im Array zeigt auf eine bestimmte Variable. Unser Beispiel enthält 12 Variablen mit Namen V1, V2, …V12. Sie können schreiben:

 ARRAY POINTER(Arr;12)
 Arr{1}:=->V1
 Arr{2}:=->V2
 
 Arr{12}:=->V12

Sie können auch schreiben:

 ARRAY POINTER(Arr;12)
 For($i;1;12)
    Arr{$i}:=Get pointer("V"+String($i))
 End for

Am Ende dieser Operation enthalten Sie ein Array mit Zeigern, in dem jedes Element auf eine Variable Vi zeigt.

Sie können beide Sequenzen kompilieren. Werden die Variablen V1 bis V12 jedoch nicht in der Datenbank an anderer Stelle ausdrücklich verwendet, kann der Compiler sie nicht typisieren. Sie müssen sie also explizit an anderer Stelle verwenden bzw. typisieren. Es gibt zwei Möglichkeiten:

  • Sie typisieren V1, V2, …V12 über eine Compiler Direktive:
 C_LONGINT(V1;V2;V3;V4;V5;V6;V7;V8;V9;V10;V11;V12)
  • Sie weisen diese Variablen in einer Methode zu:
 V1:=0
 V2:=0
 
 V12:=0

Da jede Variable in einer kompilierten Datenbank nur einen Datentyp hat, scheint diese Funktion überflüssig. Der Einsatz von Zeigern ist jedoch hilfreich, z.B. wenn Sie den Datentyp der Variablen benötigen, auf die sich ein Zeiger bezieht. Da Zeiger flexibel sind, können Sie nicht immer sicher sein, auf welche Objekte sie jeweils zeigen.

Dieser Befehl bietet im interpretierten Modus Vorteile, die nicht in den kompilierten Modus übernommen werden.
Hier wird ein Methodenname, der diesem Befehl als Parameter übergeben wird, interpretiert. Deshalb vermissen Sie einige der Vorteile, die der Compiler bietet, die Syntax Ihrer Parameter lässt sich nicht überprüfen.
Außerdem können Sie keine lokalen Variablen als Parameter übergeben.
Sie können diesen Befehl durch eine Reihe von Anweisungen ersetzen. Hierzu zwei Beispiele:

Wir gehen von folgender Sequenz aus:

 i:=FormFunc
 EXECUTE FORMULA("INPUT FORM (Form"+String(i)+")")

Sie lässt sich ersetzen durch:

 i:=FormFunc
 VarForm:="Form"+String(i)
 INPUT FORM(VarForm)

Anderes Beispiel:

 $Num:=SelPrinter
 EXECUTE FORMULA("Print"+$Num)

Hier lässt sich EXECUTE FORMULA ersetzen durch Case of:

 Case of
    :($Num=1)
       Print1
    :($Num=2)
       Print2
    :($Num=3)
       Print3
 End case

Der Befehl EXECUTE FORMULA lässt sich immer ersetzen. Da die auszuführende Methode aus der Liste der Projektmethoden in der Datenbank oder den 4D Befehlen ausgewählt wird, gibt es eine feste Anzahl an Methoden. Folglich lässt sich EXECUTE FORMULA immer durch eine Anweisung Case of oder einen anderen Befehl ersetzen. Dadurch wird Ihr Code auch rascher ausgeführt.

Diese beiden Befehle werden beim Debuggen verwendet. Sie haben in einer kompilierten Datenbank keine Funktion. Sie können sie jedoch in Ihren Methoden beibehalten, der Compiler ignoriert sie einfach.

Undefined(Variable)
SAVE VARIABLES(document;variable1{; variable2…})
LOAD VARIABLES(document;variable1{; variable2…})
CLEAR Variable(Variable)

Da der Compiler die Typisierung ausführt, kann eine Variable im kompilierten Modus nie undefiniert sein. Tatsächlich sind alle Variablen definiert, wenn die Kompilierung abgeschlossen ist. Von daher gibt die Funktion Undefined immer Falsch zurück, egal, welcher Parameter übergeben wurde.

Hinweis: Über die Funktion Is compiled mode können Sie feststellen, ob Ihre Anwendung im kompilierten Modus läuft.

Im interpretierten Modus können Sie prüfen, ob das Dokument vorhanden ist, indem Sie testen, ob eine der Variablen nach Ausführen des Befehls LOAD VARIABLES undefiniert ist. Das ist in einer kompilierten Datenbank nicht möglich, da die Funktion Undefined immer Falsch zurückgibt.

Diesen Test können Sie im interpretierten oder kompilierten Modus folgendermaßen durchführen:

  1. Sie initialisieren die Variablen, die Sie von einem Wert empfangen, der kein legaler Wert für irgendeine der Variablen ist.
  2. Sie vergleichen eine der empfangenen Variablen mit dem Wert der Initialisierung nach Ausführen von LOAD VARIABLES.

Sie schreiben folgende Methode:

 Var1:="xxxxxx"
  `"xxxxxx" ist ein Wert, der nicht über LOAD VARIABLES zurückgegeben werden kann
 Var2:="xxxxxx"
 Var3:="xxxxxx"
 Var4:="xxxxxx"
 LOAD VARIABLES("Dokument";Var1;Var2;Var3;Var4)
 If(Var1="xxxxxx")
  `Dokument nicht gefunden
 
 Else
  `Dokument gefunden
 
 End if

Diese Routine verwendet im interpretierten Modus zwei unterschiedliche Syntaxarten:
CLEAR VARIABLE(variable)
CLEAR VARIABLE("a")
Im kompilierten Modus initialisiert die erste Syntax von CLEAR VARIABLE(variable) erneut die Variable (für Zahl Setzen auf Null; leerer String für Zeichenkette oder Text, etc.), da im kompilierten Modus keine Variable undefiniert sein kann.
Aus diesem Grund setzt CLEAR VARIABLE im kompilierten Modus keinen Speicher frei, mit Ausnahme von vier Fällen: Variablen vom Typ Text, Bild, BLOB und Array.
CLEAR VARIABLE bewirkt für ein Array dasselbe wie eine neue Deklaration des Array, dessen Größe auf Null gesetzt wird.

Für ein Array MyArray, dessen Elemente vom Typ Ganzzahl sind, bewirkt CLEAR VARIABLE(MyArray) dasselbe wie einer der folgenden Ausdrücke:

 ARRAY INTEGER(MyArray;0)
  `Wenn es ein eindimensionales Array ist
 ARRAY INTEGER(MyArray;0;0)
  `Wenn es ein zweidimensionales Array ist

Die zweite Syntax CLEAR VARIABLE("a") ist mit dem Compiler nicht kompatibel, da er auf Variablen über deren Adresse und nicht über deren Namen zugreift.

Nachfolgende Befehle haben folgendes gemeinsam: Sie erlauben einen optionalen ersten Parameter [Tabelle], der zweite Parameter kann ein Zeiger sein.

ADD TO SETLOAD SET
APPLY TO SELECTIONLOCKED BY
COPY NAMED SELECTIONORDER BY
CREATE EMPTY SETORDER BY FORMULA
CREATE SETFORM SET OUTPUT
CUT NAMED SELECTIONPAGE SETUP
DIALOGPrint form
EXPORT DIFPRINT LABEL
EXPORT SYLKQR REPORT
EXPORT TEXTQUERY
GOTO RECORDQUERY BY FORMULA
GOTO SELECTED RECORDQUERY SELECTION
_o_GRAPH TABLEQUERY SELECTION BY FORMULA
IMPORT DIFREDUCE SELECTION
IMPORT SYLKRELATE MANY
IMPORT TEXTREMOVE FROM SET
FORM SET INPUT

Im kompilierten Modus ist es leicht, den optionalen Parameter [Tabelle] zurückzugeben. Wird dagegen in einem dieser Befehle als erster Parameter ein Zeiger übergeben, weiss der Compiler nicht, auf was sich der Zeiger bezieht; er behandelt ihn als Zeiger auf eine Tabelle.

Nehmen wir den Befehl QUERY mit folgender Syntax:
QUERY({table{;formula{;*}})
Das erste Element des Parameters formula muss ein Feld sein.
Schreiben Sie:

 QUERY(PtrField->=True)

sucht der Compiler nach einem Symbol, das im zweiten Element ein Feld darstellt. Findet er das Zeichen "=", generiert er eine Fehlermeldung, da er den Befehl nicht mit einem Ausdruck identifizieren kann, der weiß, wie die Operation abläuft.

Schreiben Sie dagegen:

 QUERY(PtrTable->;PtrField->=True)

oder

 QUERY([Table];PtrField->=True)

vermeiden Sie jede Art von Zweideutigkeit.

Beim Arbeiten mit Zeigern gibt es eine Besonderheit bei Befehlen, in denen der erste Parameter [Tabelle] und der zweite Parameter optional sind. Aus internen Gründen erlaubt der Compiler hier nicht, dass ein Befehl, der einen Zeiger zurückgibt, wie z.B. Current form table, direkt als Parameter übergeben wird. Es wird ein Fehler generiert.

Das ist zum Beispiel beim Befehl FORM SCREENSHOT der Fall. Nachfolgender Code funktioniert im interpretierten Modus, wird aber während dem Kompilieren zurückgewiesen:

  //löst Kompilierungsfehler aus
 FORM SCREENSHOT(Current form table->;$formName;$myPict)

In diesem Fall können Sie eine Variable dazwischen setzen, damit der Compiler diesen Code korrekt bewertet:

  //Entsprechung kompilierbarer Code
 C_POINTER($ptr)
 $ptr:=Current form table
 FORM SCREENSHOT($ptr->;$formName;$myPict)

Erstellen Sie Ihre eigenen 4DK# Ressourcen (Konstanten), stellen Sie sicher, dass Zahlen als Lange Ganzzahl (L) oder Zahl (R) und Zeichenketten als Strings (S) angelegt werden. Jeder andere Typ generiert eine Warnung.



Siehe auch 

Compiler Direktiven
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)