Quite often, you will load the parameters passed into a definition into local variables at the start of the definition. In previous versions of the local variables library, it was necessary to use SET to load them, like this:
: example ( a b c d )
locals{ a b c d }
set d set c set b set a
... ... ... ;
Note that the locals are set "in reverse order" because (obviously) d is on the top of the stack, so it needs to be loaded first.
However, in version 1.2 of the library, there is a word provided to load the local variables for you:
: example ( n1 n2 n3 n4 )
>locals{ a b c d }
... ... ... ;
The word >LOCALS{ (which is pronounced "to locals") declares the local variables with the names provided, and loads them from the stack at run-time. In this case, four locals are declared (a, b, c & d) so at run-time four cells will be popped off the stack into the locals for you, in the order you would expect; specifically top of stack would go to d, next would go to c, and so on.
If you want to automatically load some locals from the stack and have some general-purpose locals for use in your definition then you need to use a trick. Let's say you are computing the area of a square and a triangle from the same two dimensions. You want to pass in the width and the height from the stack, but you want the local variables areaSq and areaTri to be available as general purpose local variables (they are going to receive the results of the area computations).
Here's how you do it:
: areaSqTri ( w h -- sq tri )
0 0
>locals{ width height areaSq areaTri }
width height * set areaSq
areaSq 2/ set areaTri
areaSq . areaTri . ;
You can probably see what's going on here. >LOCALS{ is going to compile code to initialise four locals from the stack because we've declared four locals, even though the stack signature (which is just a comment and has no run-time effect at all) says the code takes two parameters from the stack. So, we simply get around this by placing two dummy zeros on the stack prior to the generation of the local variables so that areaTri is loaded with the blue 0 and areaSq is loaded with the red 0.
If you run areaSqTri using 10 9 as input, you'll correctly see 90 and 45 reported as the areas of a square and a triangle, respectively.
|