As in intermixing arrays and stacks. In the example register a is used both as an array and a as a stack.
1 0:a
0 Sa
2 0:a
La
0;a p
- First
:a - register a is treated as an array.
- Then
Sa - register a is treated as a stack. In effect pushing the array from from pt 1. down and creating a new array. As by man: Note that each stacked instance of a register has its own array associated with it.
- Then
:a - register a is treated as an array. Pushing the prior value and the first array value down.
- Then
La - register a is treated as a stack. To get to the fist stacked array throws away the a[0]=2 as it is an array.
- Then
;a - register a is treated as an array. Now there is only one value left, the first array value added to a which is 1.
Se bottom of answer for some more examples.
As per comment:
«How many arrays and stacks are there per register? I thought one register has one stack and one separate array.»
A Stack:
The stack in dc is a push-down-stack or LIFO (Last In First Out). Same as plates in a restaurant.
,------ pop / push - take / leave
/
|
v
[-----] top
[-----] ... ... .
[-----] [-----] [-----] ..
(main) (register-a) (register-b) ...
We have a main stack or work stack which is the one used unless a operation demanding a register is specified. Each register has it's own stack.'
Basic register operations:
Sr: pop one value from main stack and push it onto stack specified by register r. Both stacks modified.
Lr: pop one value from register stack specified by r and push it onto main stack. Both stacks modified.
sr: pop one value from main stack and write it to register r. In effect change topmost value in stack specified by register r. If no value in that stack – add it. main stack modified. Register stack preserved beside changed value.
lr: read value from register r. In effect the topmost value if there are several. main changed. Register stack preserved.
:r: pop two values from main stack and use first, topmost, as index for where to store second value in array at register r. main changed. Register stack preserved.
;r: pop one value from main stack and use it as index from where to read from current array in register specified by r. main changed. Register stack preserved.
Stack and arrays intermingled
One way to look at is in pairs. When you start out all the registers are empty. When you add an element to the stack by Sr, you hide any underlying elements in that stack. Say you do:
1 Sx
2 Sx
4 Sx
x = (S) 4 VISIBLE
(S) 2 HIDDEN
(S) 1 HIDDEN
Now you can change the value in register x, that is; change the topmost element, by sx, and you can read by lx – without altering the number of elements in the stack:
lx p # Read value in register x - in effect read topmost element from stack.
4 # Printed value by p.
3 sx # Change value in register x - in effect change topmost element in stack.
x = (S) 3 VISIBLE
(S) 2 HIDDEN
(S) 1 HIDDEN
If you decide to add array elements things start to go in a more complex direction.
4 1:x
5 2:x
x = [A]
[2]=5 VISIBLE
[1]=4 VISIBLE
(S) 3 VISIBLE
(S) 2 HIDDEN
(S) 1 HIDDEN
Now we have added values to the current array in the stack. We can read and modify any VISIBLE elements.
44 1:x
55 2:x
33 sx
1;x p # Read and print index 1
44
lx p # Read and print stack top.
33
x = [A]
[2]=55 VISIBLE
[1]=44 VISIBLE
(S) 33 VISIBLE
(S) 2 HIDDEN
(S) 1 HIDDEN
If we then add a stack element one way can say that the stack frame is non-expandable as we have added values to the array above it. Thus a new stack frame is added.
6 Sx
7 Sx
x = (S) 7 VISIBLE
(S) 6 HIDDEN
[A]
[2]=55 HIDDEN
[1]=44 HIDDEN
(S) 33 HIDDEN
(S) 2 HIDDEN
(S) 1 HIDDEN
If we now try to acces the last array it is hidden. In effect we read from an empty array and the result is the default value 0. We can modify the register value 7 by sr, but not access the array two levels down unless we get rid of the two stack elements above.
If we now decide to add some array elements, they are added to a new array positioned (as a paired array) with the top stack element.
8 1:x
9 2:x
x = [A]
[2]=9 VISIBLE
[1]=8 VISIBLE
(S) 7 VISIBLE
(S) 6 HIDDEN
[A]
[2]=55 HIDDEN
[1]=44 HIDDEN
(S) 33 HIDDEN
(S) 2 HIDDEN
(S) 1 HIDDEN
Now if we do a pop of the stack we pop of 7 but as there is an array in between (so to speak) it is also removed.
Lx p # Pop + print top stack element.
7 # Value printed.
x = (S) 6 VISIBLE
[A]
[2]=55 HIDDEN
[1]=44 HIDDEN
(S) 33 HIDDEN
(S) 2 HIDDEN
(S) 1 HIDDEN
The array with 8 and 9 is gone. The stack element with value 6 is visible. But the underlying array is blocked. A read by 1;x p yield 0.
In a way we can say the stack elements are blocking, whilst the arrays are opaque. The arrays are sort of hanging on to the stack elements.
We need to do yet another pop from the stack to reveal the underlying stack element + array.
Lx p # Pop + print top stack element.
6 # Value printed.
x = [A]
[2]=55 VISIBLE
[1]=44 VISIBLE
(S) 33 VISIBLE
(S) 2 HIDDEN
(S) 1 HIDDEN
In conclusion one can say that the number of arrays and stack are not limited to one per register.
– How many arrays and stacks are there per register?
– Depends on how many alternating Sr and :r operations you do on that register.
Another way of looking at it is that there is only one stack but multiple arrays iff we add stack elements between adding array elements ...
Yet another way is to say that at any given moment the current array is not
[register][array]
but
[register][stack-element][array]
which gives:
[register][stack-element][array][...]
[register][stack-element][array][1]
[register][stack-element][array][0]
and that the stack-element part is opaque, read only, etc. Though in that case we also have to remember that we do not need a value for stack element. It is OK to only add array values to a register.
Or each stack element has is paired with a zero filled array that we can modify:
1 Sx
2 Sx
3 Sx
4 1:x
5 2:x
6 Sx
7 Sx
8 1:x
9 2:x
x = (S) 7 + A[0]=0 A[1]=8 A[2]=9 A[3]=0 ... A[2048]=0
(S) 6 + A[0]=0 ... A[2048]=0
(S) 33 + A[0]=0 A[1]=4 A[2]=5 A[3]=0 ... A[2048]=0
(S) 2 + A[0]=0 ... A[2048]=0
(S) 1 + A[0]=0 ... A[2048]=0
Hope it made it a bit more clear.
Some examples
$ dc
[ein] 0:a
[zwei] Sa
[drei] 0:a
0;ap # Copy + print index 0 of topmost array in register a
drei
Lap # Throws away [drei] and pops+prints first element in stack*
zwei
0;ap # Copy + print index 0 of first array
ein
$ dc
[uno] 0:a # Array a(1)
[dos] 1:a # Array a(1)
[tres] 2:a # Array a(1)
[cuatro] Sa # Array a(2)
[cinco] Sa # Array a(2)
[seis] Sa # Array a(2)
[siete] 0:a # Array a(3)
[ocho] 1:a # Array a(3)
[nueve] 2:a # Array a(3)
Laf # Throws away Array 3 to get to first stack array, Array 2.
seis
Laf
cinco
seis
Laf
cuatro
cinco
seis
2;af # Now we're at the first array, Array 1.
tres
cuatro
cinco
seis
1;af
dos
tres
cuatro
cinco
seis
0;af
uno
dos
tres
cuatro
cinco
seis