Scoping – Crunch CRiSP File Editor 6 User Manual

Page 17

Advertising
background image

Page 17

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

Scoping

All variables created have a scope of visibility. CRiSP supports a number of scopes of visibility: static, local,
global and buffer-local. Global variables are always available to macros and retain their values from one
function to another. Local variables exist from the point at which they are defined to the end of the current
block
. The current block is defined as the current level of curly brackets. Static variables are variables which
are local to a function but which maintain their value across calls to the function. (This is identical to the C
mechanism). For example:

int fred = 99;
main()
{
string fred = "hello mum";
int i;

for (i = 0; i < 99; i++) {
list fred = quote_list(1, 2, 3);
}
}

In this example, there are three occurrences of the variable fred. The first one is a global variable, and is
assigned the value 99 when the macro is loaded. When the function main() is called, the global fred is
saved, and a new variable is created, of type string. The for loop demonstrates a new occurrence of fred
being defined purely for the scope of the loop. Within the loop, fred is a list. When the loop exits, the string
version of fred is accessible. Eventually when the function terminates, the integer value for fred is
accessible.

Internally, scoping is implemented by associating a block level with the definition of each variable. Global
variables are defined in block 0, which is never exited. Conceptually, each time an open curly bracket is
seen, a new level is entered. In the example above, the string version of fred is defined at block level 1.
When the close curly bracket is seen the block level is decremented and variables defined in that scope are
removed from the symbol table.

Because CRiSP is an interpreter, certain features of the language become available for very little interpretive
overhead. One of these features is dynamic scoping. Dynamic scoping is similar to the scoping rules of
Pascal rather than C. It is easiest to explain dynamic scoping together with an example:

int
func1()
{ int a = 1,
b = 2;

func2();
}
void
func2()
{
extern int a, b;

message("a=%d b=%d", a, b);
}

In this example, the function func2() is called from func1(). The declaration:

extern int a, b;

is used to tell the crunch compiler that the variables a and b will be accessible at run-time, even if there is no
definition of a and b within the current scope. Essentially, it just tells the compiler to not complain about
undefined variable references.

When the line:

message("a=%d b=%d", a, b);

is executed, CRiSP searches the current block level for a definition of the variables a and b. Since these are

Advertising