Argument passing – Crunch CRiSP File Editor 6 User Manual

Page 18

Advertising
background image

Page 18

not found, CRiSP then searches the current block level - 1. At this block level, the definitions are found.

When a variable is accessed, CRiSP needs to locate the symbol definition dynamically. The order of
processing is as follows:

1.

First a check is made for a static variable definition in the current function.

2.

If no value is found as a buffer local variable, then CRiSP will try the current local variables of a
function.

3.

If no value is found as a static variable then CRiSP will try a buffer local variable.

4.

If no value is found in the current stack frame then CRiSP will search all the nested stack frames, back
to the outermost function call.

5.

If no value is found then CRiSP will try for a global variable.

Note that it is possible to confuse CRiSP by declaring static variables inside local blocks (i.e. instead of at
the top of a function definition). This confusion can arise when a nested block and an outer block define
variables with the same name but with different attributes inside the nested block. Generally it is advisable
not to redefine variables within nested blocks with the same name as an existing variable in an outer block
to avoid any surprising results. (Note that this is only applicable to within a function; across function calls,
symbols may have the same name, so you do not need to know how a calling function is implemented).
These problems can arise because CRiSP is an interpretive language and doesn't necessarily assign unique
addresses to variables as might happen with a compiled language.

{button See Also, ALink(crunch,,,)}

Argument Passing

CRiSP supports a special form of argument passing, known as lazy evaluation. The arguments to a function
are not evaluated at the time a function is called (as it is in C). Instead they are evaluated at the time they
are referenced in the called function. This can lead to some difficult to understand code and hard to find
bugs, so it is important that the user understand this concept. This feature offers a lot of flexibility.

Before showing an example of this lazy evaluation scheme, it is necessary to discuss the mechanism used
to implement argument passing. Writing a function which takes parameters, and calling that function looks
and mostly feels like 'C'. For example, to define a function which takes three parameters, the first an integer,
the second a string, and the third a list would look like this:

int
func(int arg1, string arg2, list arg3)
{
...
}

The code above is treated as if the function was implemented as follows:

int func()
{
int arg1;
string arg2;
list arg3;

get_parm(0, arg1);
get_parm(1, arg2);
get_parm(2, arg3);

...
}

The user can pick either form for functions. Normally it is best to use the pure C style for function definitions,
and use the get_parm() primitive when a non-C compatible calling sequence is required, or for varargs
support.

For example, consider a macro which adds up all the integer parameters passed to it:

Advertising