15.6.2.1908 N>R n-to-r TOOLS EXT

Interpretation:

Interpretation semantics for this word are undefined.

Execution:

( i * n +n -- ) ( R: -- j * x +n )

Remove n+1 items from the data stack and store them for later retrieval by NR>. The return stack may be used to store the data. Until this data has been retrieved by NR>:

  • this data will not be overwritten by a subsequent invocation of N>R and
  • a program may not access data placed on the return stack before the invocation of N>R.

See:

Rationale:

An implementation may store the stack items in any manner. It may store them on the return stack, in any order. A stack-constrained system may prefer to use a buffer to store the items and place a reference to the buffer on the return stack.

Implementation:

This implementation depends on the return address being on the return stack.

: N>R \ xn .. x1 N -- ; R: -- x1 .. xn n
\ Transfer N items and count to the return stack.
   DUP                        \ xn .. x1 N N --
   BEGIN
      DUP
   WHILE
      ROT R> SWAP >R >R      \ xn .. N N -- ; R: .. x1 --
      1-                      \ xn .. N 'N -- ; R: .. x1 --
   REPEAT
   DROP                       \ N -- ; R: x1 .. xn --
   R> SWAP >R >R
;

Testing:

: TNR1 N>R SWAP NR> ;
T{ 1 2 10 20 30 3 TNR1 -> 2 1 10 20 30 3 }T

: TNR2 N>R N>R SWAP NR> NR> ;
T{ 1 2 10 20 30 3 40 50 2 TNR2 -> 2 1 10 20 30 3 40 50 2 }T

ContributeContributions

JimPetersonavatar of JimPeterson [281] Bad Stack Notation?Comment2023-02-13 15:22:04

Given that "A stack-constrained system may prefer to use a buffer to store the items and place a reference to the buffer on the return stack.", I think a better stack notation for execution semantics would be "( i * x +n -- ) ( R: -- strg-sys )" (or some other "*-sys"), to indicate pretty clearly that: 1) the user can not rely on what data format gets pushed onto the return stack, and 2) something gets pushed on to the return stack and should not be meddled with.

ruvavatar of ruv

  1. the user can not rely on what data format gets pushed onto the return stack, and 2) something gets pushed on to the return stack and should not be meddled with.

When i is unknown, the data type symbol i*x already meets these both goals.

What is wrong in the diagram is that it assumes to take i*n from the data stack.

A correct variant: ( i*x +n -- ) ( R: -- j*x +n )

AntonErtlavatar of AntonErtl

The ( in +n -- ) part is wrong. It's either ( nx +n -- ) or, if we say that i*x just means an arbitrary number of (i.e., not necessarily i) stack items, then it should be ( x1 ... xn +n -- ).

ruvavatar of ruv

I suppose that i=n follows from the statement "Remove n+1 items from the data stack".

The diagram ( x1 ... xn +n -- ) seems incorrect for the case n=0, since it starts from 1, and implies at least one x. Although, the diagrams for GET-ORDER and SET-ORDER have the same problem.

Concerning order of numbering, in other similar cases it's ascending towards the bottom of the stack (see ROLL or GET-ORDER).

So, taking into account that in all other cases, if the number of items is known beforehand in run-time then the notation ( x_[n] x_[n-1] ... is used (i.e., not i*x), a better variant could be:

  • N>R ( x_n ... x_1 n | 0 -- )
  • NR> ( -- x_n ... x_1 n | 0 )

It's obvious that n>1, so it's not necessary to indicate that n>0 via +n data type. Maybe it's even better to use the data type u instead of n for these words.

And then a correction for GET-ORDER and SET-ORDER:

  • GET-ORDER ( -- wid_n ... wid_1 n | 0 )
  • SET-ORDER ( wid_n ... wid_1 n | 0 | -1 -- )

ruvavatar of ruv

that n>0 via +n data type.

Correction:

that n 0 via +n data type.

ruvavatar of ruv

And n ≥ 1, correspondingly.

ruvavatar of ruv

Including a diagram for the return stack, and using u instead of n, we get:

  • N>R ( x_n ... x_1 u | 0 -- ) ( R: -- j*x u | 0 )
  • NR> ( -- x_n ... x_1 u | 0 ) ( R: j*x u | 0 -- )

I still think that a variant based on i*x is correct too, and far better readable:

  • N>R ( i*x u -- ) ( R: -- j*x u )
  • NR> ( -- i*x u ) ( R: j*x u -- )

And from the specification should be clear that i=u, but j is unknown.

JimPetersonavatar of JimPeterson

I think what I mean to say is if, as a stack-constrained system, I choose to use a buffer to store the items and place a reference to the buffer on the return stack, my stack notation would be:

N>R ( i*n +n -- ) ( R: -- pBuf )

Given that the rationale says that I can do that, I don't think the documentation should imply anything about the format of the data on the return stack after the call except that some opaque data exists there, much like what the stack notation for DO and LOOP say.

ruvavatar of ruv

Even when a buffer is used, the spec requires to put the number of items on the top of the return stack. I.e., only the part j*x may vary. So a possible variant for actual implementation is: N>R ( i*x +n -- ) ( R: -- addr.buf +n ) NB: add.buf is a subtype of j*x, given that j is undetermined.


Of course, a new implementation-dependent data type nr-sys can be introduced into the specification, so the stack diagrams will be:

  • N>R ( u*x u -- ) ( R: -- nr-sys u )
  • NR> ( -- u*x u ) ( R: nr-sys u -- )

But you have to provide another rationale for that — since the data type j*r already meets the goals you mentioned before.

With enough reason, the spec can be even changed in a backward-incompatible way as:

  • N>R ( u*x u -- ) ( R: -- nr-sys )
  • NR> ( -- u*x u ) ( R: nr-sys -- )

JimPetersonavatar of JimPeterson

Ah! Now I understand what you were saying. It was not immediately clear to me that j*x could mean nr-sys, or that the rationale was saying that just pushing nr-sys was not an option. I read the statement to mean that it was an option. I definitely think that:

( x<sup>n ... x<sup>1 +n -- ) ( R: -- nr-sys +n )

would be a much clearer stack notation, for what it's worth. It also feels like there should be some mention of an ambiguous condition if n<0.

AidanPitt-Brookeavatar of AidanPitt-Brooke

It also feels like there should be some mention of an ambiguous condition if n<0.

This part is already made clear in the stack effect: the symbol +n means "non-negative number". Giving any word a value of an inappropriate type always results in an ambiguous condition, so I don't think it needs to be re-stated in the prose. (It would probably be wise for standard systems to declare how they handle this particular case, but standard programs will respect the type constraints of the standard.)

Reply New Version