Added tests for stdlib stack functions. Fixed some small bugs.
[vvhitespace] / stdlib / stack.pvvs
#ifndef VVS_STDLIB_STACK
#define VVS_STDLIB_STACK
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ Name:
@ stackrotate
@ Description:
@ Maximum rotation depth is 14. Stomps on heap[1]-heap[15].
@ Assumes rotation depth is at least 2.
@ Call Stack:
@ stack word n
@ ...
@ stack word 1
@ rotation depth (rd) <-- TOS
@ Return Stack (n>rd=3):
@ stack word n
@ ...
@ stack word 1
@ stack word 3
@ stack word 2 <-- TOS
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
NSSVTSTSN | Mark: 1010 (stackrotate)
@ For the convenience of other functions, modulo the
@ rotation depth by the available registers.
SSSTTTTN | PUSH 15
TSTT | MODULO
@ Use heap[15] for generating register addresses.
@ TODO: Switch to using heap[1] so number of registers is limited only by user.
SSSTTTTN | PUSH 15 (ptr)
SSSSN | PUSH 0
TTS | STORE
@ Dump one word from stack to heap each pass through the loop.
NSSVSSSSTSTSSSSSSSSSN | Mark: 00001010 00000000
SNT | SWAP
SSSTN | PUSH 1 (starting register)
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
TSSS | ADD
SNT | SWAP
TTS | STORE
@ See if the loop is complete.
SNS | DUP
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSSS | ADD
TSST | SUBTRACT
NTSSSSSTSTSSSSSSSSTN | BRZ > 00001010 00000001
@ Increment the loop counter
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSSS | ADD
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
NSNSSSSTSTSSSSSSSSSN | JMP > 00001010 00000000
@ The correct number of words have been stored to registers.
@ Time to read them back in rotated order.
@ First, prepare the counter in heap[15] again.
@ This consumes 'rd' from the stack.
NSSVSSSSTSTSSSSSSSSTN | Mark: 00001010 00000001
SSSTN | PUSH 1
TSST | SUBTRACT
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
@ Second, read in the old TOS manually.
SSSTN | PUSH 1 (starting register)
TTT | LOAD
@ Read one word per pass through this loop.
NSSVSSSSTSTSSSSSSSTSN | Mark: 00001010 00000010
SSSTN | PUSH 1 (starting register)
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
TSSS | ADD
TTT | LOAD
@ See if the loop is complete.
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSST | SUBTRACT
NTSSSSSTSTSSSSSSSTTN | BRZ > 00001010 00000011
@ Decrement the loop counter and loop again.
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSST | SUBTRACT
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
NSNSSSSTSTSSSSSSSTSN | JMP > 00001010 00000010
@ Return
NSSVSSSSTSTSSSSSSSTTN | Mark: 00001010 00000011
NTN | RTS
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ Name:
@ stackrotatereverse
@ Description:
@ Maximum rotation depth is 14. Stomps on heap[1]-heap[15].
@ Assumes rotation depth is at least 2.
@ Call Stack:
@ stack word n
@ ...
@ stack word 1
@ rotation depth (rd) <-- TOS
@ Return Stack (n>rd=3):
@ stack word n
@ ...
@ stack word 2
@ stack word 1
@ stack word 3 <-- TOS
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
NSSVTSTTN | Mark: 1011 (stackrotatereverse)
@ For the convenience of other functions, modulo the
@ rotation depth by the available registers.
SSSTTTTN | PUSH 15
TSTT | MODULO
@ Use heap[15] for generating register addresses.
@ TODO: Switch to using heap[1] so number of registers is limited only by user.
SSSTTTTN | PUSH 15 (ptr)
SSSSN | PUSH 0
TTS | STORE
@ Dump one word from stack to heap each pass through the loop.
NSSVSSSSTSTTSSSSSSSSN | Mark: 00001011 00000000
SNT | SWAP
SSSTN | PUSH 1 (starting register)
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
TSSS | ADD
SNT | SWAP
TTS | STORE
@ See if the loop is complete.
SNS | DUP
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSSS | ADD
TSST | SUBTRACT
NTSSSSSTSTTSSSSSSSTN | BRZ > 00001011 00000001
@ Increment the loop counter
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSSS | ADD
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
NSNSSSSTSTTSSSSSSSSN | JMP > 00001011 00000000
@ The correct number of words have been stored to registers.
@ Time to read them back in rotated order.
@ First, prepare the counter in heap[15] again.
NSSVSSSSTSTTSSSSSSSTN | Mark: 00001011 00000001
SSSTN | PUSH 1
TSST | SUBTRACT
SNS | DUP
SSSTN | PUSH 1
TSST | SUBTRACT
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
@ Read one word per pass through this loop.
@ Store it behind 'rd' on the stack.
NSSVSSSSTSTTSSSSSSTSN | Mark: 00001011 00000010
SSSTN | PUSH 1 (starting register)
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
TSSS | ADD
TTT | LOAD
SNT | SWAP
@ See if the loop is complete.
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
NTSSSSSTSTTSSSSSSTTN | BRZ > 00001011 00000011
@ Decrement the loop counter and loop again.
SSSTTTTN | PUSH 15 (ptr)
TTT | LOAD
SSSTN | PUSH 1
TSST | SUBTRACT
SSSTTTTN | PUSH 15 (ptr)
SNT | SWAP
TTS | STORE
NSNSSSSTSTTSSSSSSTSN | JMP > 00001011 00000010
@ Read in the final value manually and return.
NSSVSSSSTSTTSSSSSSTTN | Mark: 00001011 00000011
SSSTN | PUSH 1 (starting register)
TSSS | ADD
TTT | LOAD
NTN | RTS
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ Name:
@ deepdup
@ Description:
@ Duplicates an item deep on the stack, placing the duplicate on TOS.
@ By default, maximum depth is 11.
@ True maximum depth is (max depth of stackrotate & stackrotatereverse)-3.
@ Call Stack:
@ stack word n
@ ...
@ stack word 1
@ dupdepth <-- TOS
@ Return Stack:
@ stack word n
@ ...
@ stack word 1
@ copy of stack word 3 <-- TOS
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
NSSVTTSSN | Mark: 1100 (deepdup)
@ Copy 'dupdepth' and use it to bring forth the desired stack word.
SNS | DUP
SSSTN | PUSH 1
TSSS | ADD
NSTTSTTN | JSR > 1011 (stackrotatereverse)
@ Copy the desired stack word and return it back into the stack.
SNS | DUP
SSSTTN | PUSH 3
NSTTSTTN | JSR > 1011 (stackrotatereverse)
SSSTN | PUSH 1
TSSS | ADD
NSTTSTSN | JSR > 1010 (stackrotate)
NTN | RTS
#endif