VALUEs and Lexically Scoped Local Variables - tabemann/zeptoforth GitHub Wiki
Full builds of zeptoforth have support for value
, 2value
, and lexically-scoped local variables. All of these may be set with to
and added to/subtracted from with +to
.
Values declared with value
and 2value
, along with setting these values with to
, are shown below:
2 value foo ok
2,5 2value bar ok
foo . 2 ok
bar f. 2,5 ok
3 to foo ok
3,75 to bar ok
foo . 3 ok
bar f. 3,75 ok
: foo! ( x -- ) to foo ; ok
: bar! ( d -- ) to bar ; ok
4 foo! ok
4,875 bar! ok
foo . 4 ok
bar f. 4,875 ok
Here we see that the word foo
declared with value
returns a single-cell value when called, and to
when setting it takes a single-cell value. Similarly the word bar
declared with 2value
returns a double-cell value when called, and to
when setting it takes a double-cell value. Hence to
takes both single-cell and double-cell values depending on what it is called against
Words compiled with value
and 2value
can be compiled to flash and are initialized with the values specified when they are created on bootup. Afterwards, their values can be changed, unlike with constant
and 2constant
, but are reset to their initial values after rebooting. This can be seen in the following:
compile-to-flash ok
3 value foo ok
3,25 2value bar ok
reboot
Welcome to zeptoforth
Built for rp2040, version 0.48.2, on Sat Nov 19 06:46:41 PM CST 2022
zeptoforth comes with ABSOLUTELY NO WARRANTY: for details type `license'
ok
foo . 3 ok
bar f. 3,25 ok
4 to foo ok
4,5 to bar ok
foo . 4 ok
bar f. 4,5 ok
: foo! ( x -- ) to foo ; ok
: bar! ( d -- ) to bar ; ok
5 foo! ok
5,75 bar! ok
foo . 5 ok
bar f. 5,75 ok
reboot
Welcome to zeptoforth
Built for rp2040, version 0.48.2, on Sat Nov 19 06:46:41 PM CST 2022
zeptoforth comes with ABSOLUTELY NO WARRANTY: for details type `license'
ok
foo . 3 ok
bar f. 3,25 ok
Adding to/subtracting from value
s and 2value
s with +to
is shown below:
1 value foo ok
1,25 2value bar ok
2 +to foo ok
1,5 +to bar ok
foo . 3 ok
bar f. 2,75 ok
: +foo! ( x -- ) +to foo ; ok
: +bar! ( d -- ) +to bar ; ok
2 +foo! ok
1,75 +bar! ok
foo . 5 ok
bar f. 4,5 ok
Here we see that +to
functions like to
except that it adds to/subtracts from the value
or 2value
rather than setting it.
For a simple example of local variables in action in zeptoforth consider the following:
: foo { x -- x' } x x * 2 x * + 1 + ;
Afterwards, execute:
0 foo . 1 ok
1 foo . 4 ok
2 foo . 9 ok
3 foo . 16 ok
Here foo
defines a polynomial f(x) = x^2 + 2x + 1, and we evaluate f(0), f(1), f(2), and f(3). Note that the contents between {
and }
, which may cross multiple input lines, defines local variables to be taken off the data stack, starting from the last local variable defined, which is taken off the top of the data stack. Note that the text after --
and before }
is a comment intended for documenting the return value(s) of word and has no actual effect upon the code.
For an example of a simple loop using local variables, consider the following:
: foo { limit i -- } begin i limit < while i . 1 +to i repeat ;
Afterwards, execute:
10 0 foo 0 1 2 3 4 5 6 7 8 9 ok
Here we pull the loop counter i
, which shadows the standard do
loop
variable i
, and the loop limit limit
off the data stack and place them in the so-named local variables. Then we loop until i
is greater than or equal to limit
, printing the current value of i
and incrementing i
with +to
for each iteration. Note that local variables may also be set with to
.
For a more elaborate example of using local variables combined with begin
... until
loops, consider the following:
: foo { multiplier limit i -- } 0 { acc } begin i multiplier * { im } 1 +to i im +to acc im limit >= until acc ;
Afterwards, execute:
3 100 1 foo . 1785 ok
Here we create local variables both outside and inside the loop and access them both inside the loop and outside the loop, after the loop has completed, showing that local variables created before the loop began can be accessed after the end of the loop.
For an example of using local variables together with do
loop
s, consider the following:
: foo ( increment limit i -- ) rot { increment } ?do i . increment +loop ;
Afterwards, execute:
2 20 0 foo 0 2 4 6 8 10 12 14 16 18 ok
Here we create a local variable increment
and execute a do
loop
, where we use the value of increment
to increment the do loop counter.
For another example of using local variables together with do
loop
s, consider the following:
: foo ( multiplier limit i ) rot { multiplier } ?do i multiplier * { xi } i xi + . loop ;
Afterwards, execute:
3 10 0 foo 0 4 8 12 16 20 24 28 32 36 ok
Here we create local variables both outside and inside the do
loop
and refer to them both within the do
loop
while simultaneously accessing i
.
Currently local variables are always single cell, so if one wants to place a multi-cell value in local variables one will need separate local variables for each cell.