Brat is now on its third, and hopefully final, scope/environment implementation. Since scope in Brat is different than in Neko, it is necessary to work around it.
Neko has both global and local variables, and Neko functions work as closures which copy local functions from the environment. This copying is the main problem for Brat, because inner scopes always have access to variables in enclosing scopes. Let’s say you are implementing a while loop, like this:
Now you might want to use it like this:
If this used Neko scoping rules, the
x variable in the outer scope would not be incremented, and the two closures would have separate copies of
x, so the block inside the loop would never modify the variable in the conditional.
The first method for implementing scope the Brat way was to make all variables global. That solved the problem above, but there were other problems. Besides being inefficient and inelegant, it was not entirely correct, either. Local variables inside recursive functions, for example, did not behave properly.
One way to allow functions to modify outer variables in Neko without using globals is to put them inside an array. The array is copied into the function, but modifications to the contents of the array are reflected in the outer variable.
Knowing this, we can simply put all our variables into arrays and they will be properly modified by inner functions and all will be right with the world inside our programs.
But there is still a problem. Why construct an array to hold variables that may never be used in an inner scope? Not only is it a waste of memory, we are performing pointless array index look-ups rather than just straight variables.
The latest version of Brat now does a scan of the program and determines which variables will be used by inner scopes. Variables which are will be stored inside an array, while those that do not will be left as local variables. This saves memory and time when running the program, for a small increase in both when compiling.
Implementing this was something of a chore (it requires a second pass when ‘compiling,’ when before everything was accomplished in a single pass), which is why there have been few updates recently. However, now that it is done, Brat is more efficient and, in my opinion, proper.