<< | Inhaltsverzeichnis | Suchen | >> |
Anweisung
Syntax: |
Syntax Funktions-Deklaration: |
|
|
FUNCTION
FN<VARNAME> ( [<VARIABLE> [,<VARIABLE>]...] ) |
|
|
Syntax Funktions-Aufruf: |
|
|
FN<VARNAME> ( [<AUSDRUCK> [,<AUSDRUCK>]...] ) |
|
Bedeutung: |
Funktionen können an jeder beliebigen Stelle im Macro deklariert werden, aber nicht innerhalb von Blöcken IF ... THEN, WHILE ... DO, ON ERROR ... END, usw.). Um diese Funktionen von externen C- oder Assemblerfunktionen unterscheiden zu können, muß der Funktionsname mit FN... beginnen. Als Folge davon dürfen keine Hilfsvariablen mehr verwendet werden, die mit FN... beginnen. Denn dies führt zu Syntaxfehlern bei der Compilierung. Der Typ der Funktion (String, numerisch, integer) wird durch die Schreibweise definiert: Endet der Funktionsname mit '$', so definiert dies eine String-Funktion. '%' bedeutet integer, Buchstabe und Ziffer bedeuten numerisch (double). Es können beliebig viele Parameter angegeben werden. Der Typ der einzelnen Parameter ergibt sich wieder aus deren Schreibweise. Es sind auch Funktionen ohne Parameter zulässig. |
|
Beispiel: |
FUNCTION FN_DATUM_TIME$() |
|
|
Jede Funktions-Deklaration muß mit ENDFUNC abgeschlossen werden. In der Funktions-Deklaration können alle Anweisungen und Funktionen verwendet werden mit Ausnahme von: QUIT, MACRO, GOTO #..., FIELD, DIM, SHARED, ENDPROG, REPEAT, NEXTFIELD. |
|
|
Funktionen liefern als Ergebnis immer einen Wert und können deshalb nicht auf der linken Seite einer Zuweisung vorkommen. |
|
|
Mit der Anweisung RETURN <AUSDRUCK> wird der Ergebniswert festgelegt und die Funktion beendet. <AUSDRUCK> muß vom selben Typ wie die Funktion sein. Lediglich numerisch und integer können gegenseitig vertauscht werden. Die letzte Anweisung in der Funktions-Deklaration vor ENDFUNC muß die Anweisung RETURN <AUSDRUCK> sein. |
|
Beispiel: |
FUNCTION FNMAX%(I%,J) |
|
|
Dies ist nicht zulässig und führt zu einem Fehler. Der Macro-Compiler erkennt nicht, daß sowohl der THEN- als auch der ELSE-Zweig mit RETURN verlassen werden. Zulässig ist das vorhergehende Beispiel oder das Einfügen einer weiteren RETURN-Anweisung, die zwar nie ausgeführt wird, aber eine logisch konsistente Deklaration liefert: |
|
|
FUNCTION FNMAX%(I%,J) |
|
|
Alle in einer Funktions-Deklaration verwendeten nicht-dimensionierten Hilfsvariablen sind lokal bezüglich der Funktions-Deklaration. D.h. außerhalb der Funktions-Deklaration existieren diese Variablen nicht. Diese Variablen werden auf dem Stack angelegt und bei jedem Aufruf der Funktion neu initialisiert. |
|
|
|
|
|
Achtung: Auch lokale Variablen gleichen Namens, die im selben Macro wie die Funktions-Deklaration definiert wurden, unterscheiden sich von den Hilfsvariablen der Funktion. |
|
|
|
|
Beispiel: |
LOCAL I% |
|
|
Dimensionierte Hilfsvariablen sind immer global bezüglich des Programms. Es gibt keine lokalen DIM-Variablen! |
|
|
Sprungmarken sind in Funktions-Deklarationen zulässig, Sprünge aus der Funktions-Deklaration heraus aber nicht.
|
|
Beispiel: |
N1: I% = 0 |
|
|
Funktions-Aufruf: |
|
|
Funktionen können an jeder beliebigen Stelle in beliebiger Schachtelungstiefe aufgerufen werden. Als Parameter können beliebige Ausdrücke übergeben werden. Der Typ des Ausdrucks muß jeweils mit dem Typ des Parameters in der Funktions-Deklaration übereinstimmen. String-Parameter werden ‘by reference’ an die Funktion übergeben, numerische und integer Parameter ‘by value’. Dies hat zur Folge, daß bei einer Wertzuweisung an einen Stringparameter innerhalb der Funktions-Deklaration der Wert der aufgerufenen Variablen verändert wird. Numerische und integer Variable können dagegen durch Funktionsaufrufe nicht verändert werden. |
|
|
|
|
|
Achtung: Werden alphanumerische Indexdatei-Variablen an eine Funktion als Parameter übergeben, so darf die Funktion die Länge dieser Variablen nicht verändern. Indexdatei-Variable haben im EBUS-Programm stets eine feste Länge. Wird die Länge in einer Funktion geändert, so kann dies nicht wie bei den anderen Befehlen und Funktionen vom EBUS-GENERATOR-C erkannt werden. Die Folge sind unvorhersehbare Programmfehler. |
|
Beispiel: |
FUNCTION FNTEST(A%,B,C$) |
|
|
Für numerische Parameter können beim Funktionsaufruf auch integer-Werte und bei integer-Parametern numerische Werte übergeben werden. Der Macro-Compiler konvertiert die Parameter automatisch in das bei der Deklaration festgelegte Format. Da der Macro-Compiler des EBUS-GENERATOR-C ein 1-Pass-Compiler ist, können bei numerischen Parametern Probleme auftreten, wenn bei der Compilierung ein Aufruf der Funktion vor deren Deklaration compiliert wird. In diesem Fall versucht der Macro-Compiler, anhand der übergebenen Parameter den Typ der Parameter festzulegen. Bei numerischen Parameter kann dies zu nicht erwarteten Fehlermeldungen führen. |
|
Beispiel: |
Die Compilierung des Aufrufs der Funktion FNMAX(1,2) erfolgt vor der Compilierung der Funktions-Deklaration. Der Macro-Compiler geht davon aus, daß beide Parameter vom Typ integer sind. Lautet nun die später compilierte Funktions-Deklaration |
|
|
FUNCTION FNMAX(A,B) |
|
|
so führt dies zu einer Fehlermeldung, da die Parameter A und B numerisch (double) und nicht integer sind. Würde die Compilierung der Funktions-Deklaration vor der Compilierung des Aufrufs erfolgen, so wüßte der Macro-Compiler, daß die Parameter numerisch (double) und nicht integer sind, und würde bei der Generierung die Parameter 1 und 2 automatisch nach double konvertieren. Dies ist notwendig, da sonst der C-Compiler Typendeklarationsfehler meldet. |
|
|
Um dieses Problem zu vermeiden gibt es 2 Möglichkeiten: |
|
|
1. |
Man wartet ab, ob der Macro-Compiler einen Fehler meldet. Falls nicht, so ist alles in Ordnung. Wird ein Fehler gemeldet, so könnte man den obigen Funktionsaufruf ändern in FNMAX(1.0,2.0). Der Macro-Compiler erkennt 1.0 und 2.0 als numerische (double) Parameter. Ein weiterer Aufruf der Form FNMAX(I%,J%) müßte dann aber umständlich geändert werden: I = I% Alle derartigen Aufrufe zu ändern ist dann aber nicht sinvoll, wenn ein Parameter das Ergebnis einer anderen Funktion ist und die Funktionsaufrufe stark verschachtelt sind. Es müßten dann die verschachtelten Aufrufe in jeweils einzelne Anweisungen zerlegt werden, was mühsam und nicht sehr effizient ist. Deshalb empfiehlt sich die 2. Möglichkeit: |
|
2. |
Man sorgt dafür, daß die Deklaration vor dem Aufruf compiliert wird. Dazu muß man wissen, welche Macros wann compiliert werden. Dies ist nicht immer eindeutig vorhersebar. Deshalb genügt es zu wissen, daß die Init-Macros vor und nach Index-Open stets als erstes compiliert werden. Die sicherste Methode ist es also, alle Funktionen in den Init-Macros zu deklarieren. |
|
Im Hauptprogramm deklarierte Funktionen gelten auch für alle Unterprogramme, sind also global für das gesamte Programm. Im Unterprogramm deklarierte Funktionen gelten nur für das einzelne Unterprogramm. |
|
|
Um mehrfache Deklarationen und damit mehrfache Generierung der Funktionen zu vermeiden, empfiehlt es sich, stets alle in Unterprogrammen benötigten Funktionen im Hauptprogramm zu deklarieren. |
|
Beispiel: |
FUNCTION FNCAT$(H1$,H2$) |
|
|
FUNCTION FNMAX%(I%,J) |