
Because the FHDL macro processor provides variables, if statements and while statements, it has the full power of a general purpose programming language. One important feature of general purpose programming languages is the ability to define subroutines. The ability to nest macro calls is a type of subroutine feature, but there are times when the ability to define a function that can be used in an expression is helpful. Any macro may be used as a function by following the macro name with a parenthesized list of arguments. The following macro computes the "factorial" function recursively.
factorial: 'macro
'if '0'==0||'0'==1
'assign 'factorial,1
'else
'assign 'factorial,'0*factorial('0-1)
'endif
'endmacro
A macro that is used as a function should not contain text statements. As this example illustrates, a macro returns a value by assigning a value to a variable whose name is identical to the macro name. This variable, which is of type string, is a local variable that is created at the beginning of the function call. If the macro is called normally, the variable will not exist, therefore it is a good idea to avoid using a macro both as a function and as an ordinary macro. If, for some reason, you absolutely must do this, you can use the built-in variable 'callt to determine whether the macro has been called as a function or as a normal macro. When used as a string variable, 'callt has the value "FUNC" for a function call and the value "STMT" for a normal call. When used as a condition it has the value true for function calls and false for normal calls. When used in an arithmetic expression, it has the value one for function calls and zero for normal calls.
In the example above it is not possible to replace the function name "factorial" with an arbitrary expression. However, the "apply" operator, (@) allows you to use an arbitrary expression as a function name. The following is an example of the "apply" operator.
"fact"#"orial"@5
When the apply operator is evaluated, the expression on the left is evaluated and treated as a function name. The expression on the right is evaluated and treated as the argument list of the function. The value of the expression is the value returned by the function.