Procedures

You can also use procedures (with their own local variables) in IntelliMacro.NET.

Procedure syntax

Procedure (subroutine) names look like variable names. The procedure syntax looks like this:
Sub subname(param1, param2, ...)
    ...
End

Parameter names look like variable names as well. In fact, they are local variables of the procedure. When control flow passes through the function definition, the function gets defined. You can define more than one function with the same name if you like to, but it is not recommended; if you do so, the function defined most recently will be called.

A procedure can be called like this:
Call subname(parameter1, parameter2, ...)

Note that a procedure can be called only after it has been defined. When the procedure is called, its body is executed (with the parameters assigned by the parameter values in the call), and control flow continues after the caller. Procedures may call themselves (be recursive) or call other functions which ultimately call the original function (indirect recursion).

It is currently possible to define procedures inside of procedures. This may change in the future, so you should not rely on that.

Global and local variables

Procedures are quite useful, but to write useful recursive ones, you either need a stack or local variables. All variables whose name does not start with g_ are local – every function call has private ones. Local variables from the main macro are not visible inside any procedure either and vice versa. The only way to pass information from caller to callee, except parameters, are global variables, which exist only once for all functions.

Reference passing

In the function declaration, you may prepend a variable name with an ampersand (like &var). In that case, this variable is treated as a reference variable; the value of the variable at the end of the function is assigned back to the expression which was used in the call's parameter list. All expressions that can be to the left of an equals sign (variables, lists and slices) can be used here. If another expression (like a calculation or a constant) is used for such a parameter, an error is signalled. Unlike C#, the ampersand sign is used only for defining the function, not for calling it.

Note that passing global variables by reference is not well-defined, as well as using global variable names for reference parameters. Especially when you access both the global variable and the reference from within a function, behaviour of the interpreted macro and an exported C# program may differ.

What about functions (with return values)?

Although there are no explicit user-defined functions available, you can achieve the same effect by making the first parameter of your procedure a reference parameter.