15.6.2.1940 NR> n-r-from TOOLS EXT
Interpretation:
Execution:
Retrieve the items previously stored by an invocation of N>R. n is the number of items placed on the data stack. It is an ambiguous condition if NR> is used with data not stored by N>R.
See:
Implementation:
ContributeContributions
EricBlake
[393] Reference implementation should not use -ROTSuggested reference implementation2025-08-04 13:11:17
-rot
is not part of the standard; the reference implementation should be written using only other words in the standard. A working replacement, although not necessarily the most efficient, would be rot rot
. (A future version of the standard should consider standardizing -rot.)
For that matter, the reference implementations for n>r and nr> use an atypical style of using \ rather than ( ) for giving the comment listing stack effects. And both examples document that they have a dependency on a non-standard use of r> on a value that was not previously placed on the return stack by r> by assuming that the return stack has exactly one cell occupied by the return pointer to get back to the caller of n>r and nr>. It's not entirely wrong to have a reference that is not portable to all implementations since that limitation is documented.
However, it would be possible to rewrite these examples as immediates in order to be entirely portable, although no longer as compact (every caller duplicates code, rather than being a single call into shared code). That said, such a rewrite still matches with the fact that the standard documents only that its reference implementations demonstrate how the word can work, not that they are the most efficient:
VARIABLE nr-scratch \ scratch space for N>R and NR>
: N>R ( xn .. x1 n -- ; R: -- x1 .. xn n )
\ Transfer N items and count to the return stack.
POSTPONE DUP POSTPONE nr-scratch POSTPONE !
POSTPONE BEGIN
POSTPONE DUP
POSTPONE WHILE
POSTPONE SWAP POSTPONE >R
POSTPONE 1-
POSTPONE REPEAT
POSTPONE DROP
POSTPONE nr-scratch POSTPONE @ POSTPONE >R
; IMMEDIATE
: NR> ( -- xn .. x1 n ; R: x1 .. xn n -- )
\ Pull N items and count off the return stack.
POSTPONE R>
POSTPONE DUP POSTPONE nr-scratch POSTPONE !
POSTPONE BEGIN
POSTPONE DUP
POSTPONE WHILE
POSTPONE R> POSTPONE SWAP
POSTPONE 1-
POSTPONE REPEAT
POSTPONE DROP
POSTPONE nr-scratch POSTPONE @
; IMMEDIATE
Or, we could go the route of documenting the use of a buffer, by depending on the memory-allocation word set; again, using immediate so that the example does not depend on non-portable use of r> on a return value not placed by >r:
: N>R ( xn .. x1 n -- ; R: -- buf-sys n )
\ Transfer N items and count to the return stack.
\ This version throws ior if ALLOCATE fails
POSTPONE DUP POSTPONE >R
POSTPONE DUP POSTPONE ALLOCATE POSTPONE THROW ( xn .. x1 n a-addr ; R: n )
POSTPONE BEGIN
POSTPONE OVER
POSTPONE WHILE
POSTPONE ROT POSTPONE OVER POSTPONE !
POSTPONE CELL+ POSTPONE SWAP POSTPONE 1- POSTPONE SWAP ( xn .. x2 n-1 a-addr+1 ; R: n )
POSTPONE REPEAT ( 0 a-addr+n ; R: n )
POSTPONE R> POSTPONE SWAP POSTPONE 2>R POSTPONE DROP
; IMMEDIATE
: NR> ( -- buf-sys n ; R: x1 .. xn n -- )
\ Pull N items and count off the return stack.
\ This version throws ior if FREE fails
POSTPONE 2R> POSTPONE OVER POSTPONE >R ( n a-addr+n ; R: n )
POSTPONE BEGIN
POSTPONE OVER
POSTPONE WHILE
-1 POSTPONE LITERAL POSTPONE CELLS POSTPONE + POSTPONE DUP POSTPONE @ ( n a-addr+n-1 xn )
POSTPONE ROT POSTPONE 1- POSTPONE ROT ( xn n-1 a-addr+n-1 ; R: n )
POSTPONE REPEAT ( xn .. x1 0 a-addr ; R: n )
POSTPONE FREE POSTPONE THROW POSTPONE DROP POSTPONE R>
; IMMEDIATE