Calling functions

Functions can be invoked, to execute the code they define.

How can functions be invoked?

A function can be invoked in different ways:
  1. with the CALL instruction,
  2. in an expression,
  3. in a callback mechanism.
Note: The symbol used to identify the function to be called can be a static function name, or a variable referencing a function.

Typical function invocation with CALL

In most cases, functions are invoked with the CALL instruction:
FUNCTION open_database(dbname STRING)
   ...
END FUNCTION

...
    CALL open_database("stock")

Function invoked as part of an expression

When a function returns a single value, it can be invoked in an expressions:
MAIN
    DEFINE r INTEGER
    LET r = 500 + add(50,5)
END MAIN

FUNCTION add(x,y) RETURNS INTEGER
    DEFINE x, y INTEGER
    RETURN (x + y)
END FUNCTION

Callback mechanisms

Genero BDL provides some callback mechanisms where functions are invoked when needed, for example:

Recursion

A function can invoke itself recursively:
MAIN
    CALL recursive(1)
END MAIN

FUNCTION recursive(x)
    DEFINE x INTEGER
    DISPLAY "x = ", x
    IF x<10 THEN
       CALL recursive(x+1)
    END IF
END FUNCTION
Important: Each time a function calls itself, parameters are pushed on the stack. A deep level of recursion can result in out of memory errors.

Calling a function from its reference variable

A function can be referenced by a variable, and be invoked through this variable in a CALL instruction, or in an expression:
TYPE t_func_ref FUNCTION (p1 INT, p2 INT) RETURNS INT
DEFINE fr t_func_ref
LET fr = FUNCTION add   -- Function with the same signature as t_func_ref
DISPLAY fr(100,200)

Naming parameters in a function call

To improve code readability, function parameters can be qualified with the name specified in the function definition:
MAIN
    CALL cleanup( mode: "full", verbose: TRUE )
END MAIN

FUNCTION cleanup( mode STRING, verbose BOOLEAN )
    IF verbose THEN
       DISPLAY "Cleanup mode: ", mode
    END IF
END FUNCTION
Built-in functions and class/object methods can also be invoked with named parameters:
DEFINE s STRING
DISPLAY s.subString(startIndex: 1, endIndex: 3)
...
DEFINE io base.Channel
LET io = base.Channel.create()
CALL io.openClientSocket(host: "localhost", port: 4711, mode: "u", timeout: 0)

If the parameter name in the function call does not match the parameter in the function definition, the compiler will produce error -8420.

Note: Named function call parameters does not imply free ordering, nor does it allow you to omit parameters. All parameters must be specified, in the same order as in the function declaration.

In order to check the parameter names, fglcomp needs to know the function definition. When the called function is defined in another module, use IMPORT FGL to let the compiler know the function definition.

Tip: Named function parameters are provided by the source code completer.