Previous:#declare vs. #local Main Index Next:Destroying Identifiers with #undef

#### Identifier Name Collisions

Local identifiers may have the same names as previously declared identifiers. In this instance, the most recent, most local identifier takes precedence. Upon entering an include file or invoking a macro, a new symbol table is created. When referencing identifiers, the most recently created symbol table is searched first, then the next most recent and so on back to the global table of the main scene file. As each macro or include file is exited, its table and identifiers are destroyed. Parameters passed by value reside in the same symbol table as the one used for identifiers local to the macro.

The rules for duplicate identifiers may seem complicated when multiply-nested includes and macros are involved, but in actual practice the results are generally what you intended.

Consider this example: You have a main scene file called `myscene.pov` and it contains

     #declare A = 123;

     #declare B = rgb<1,2,3>;

     #declare C = 0;

     #include "myinc.inc"

Inside the include file you invoke a macro called `MyMacro(J,K,L)`. Note it isn't important where `MyMacro` is defined as long as it is defined before it is invoked. In this example, it is important that the macro is invoked from within `myinc.inc`.

The identifiers `A`, `B`, and `C` are generally available at all levels. If either `myinc.inc` or `MyMacro` contain a line such as `#declare C=C+1;` then the value `C` is changed everywhere as you might expect.

Now suppose inside `myinc.inc` you do...

     #local A = 546;

The main version of `A` is hidden and a new `A` is created. This new `A` is also available inside `MyMacro` because `MyMacro` is nested inside `myinc.inc`. Once you exit `myinc.inc`, the local `A` is destroyed and the original `A` with its value of `123` is now in effect. Once you have created the local `A` inside `myinc.inc`, there is no way to reference the original global `A` unless you `#undef A` or exit the include file. Using `#undef` always undefines the most local version of an identifier.

Similarly if `MyMacro` contained...

     #local B = box{0,1}

then a new identifier `B` is created local to the macro only. The original value of `B` remains hidden but is restored when the macro is finished. Note that the local `B` need not have the same type as the original.

The complication comes when trying to assign a new value to an identifier at one level that was declared local at an earlier level. Suppose inside `myinc.inc` you do...

     #local D = 789;

If you are inside `myinc.inc` and you want to increment `D` by one, you might try to do...

     #local D = D + 1;

but if you try to do that inside `MyMacro` you'll create a new `D` which is local to `MyMacro` and not the `D` which is external to `MyMacro` but local to `myinc.inc`. Therefore you've said "create a `MyMacro D` from the value of `myinc.inc`'s `D` plus one". That's probably not what you wanted. Instead you should do...

     #declare D = D + 1;

You might think this creates a new `D` that is global but it actually increments the myinc.inc version of `D`. Confusing isn't it? Here are the rules:

1.) When referencing an identifier, you always get the most recent, most local version. By "referencing" we mean using the value of the identifier in a POV-Ray statement or using it on the right of an equals sign in either a `#declare` or `#local`.

2.) When declaring an identifier using the `#local` keyword, the identifier which is created or has a new value assigned, is ALWAYS created at the current nesting level of macros or include files.

3.) When declaring a NEW, NON-EXISTANT identifier using `#declare`, it is created as fully global. It is put in the symbol table of the main scene file.

4.) When ASSIGNING A VALUE TO AN EXISTING identifier using `#declare`, it assigns it to the most recent, most local version at the time.

In summary, `#local` always means "the current level", and `#declare` means "global" for new identifiers and "most recent" for existing identifiers.

Previous:#declare vs. #local Main Index Next:Destroying Identifiers with #undef