Digest #76 2019-08-26
Contributions
requestClarification - description of "nt" in the standard
Background
In the optional Programming Tools wordset the following description is given in 15.3.1 for the data type "name token":
"A name token is a single-cell value that identifies a named word."
Following this description, the stack diagram abbreviation "nt" is assigned to "name token" in Table 15.1.
Problem
The description "name token" is not a good match for a value which identifies a named word. "Name token" suggests a value associated with the name data of the word, i.e. the string representation of the word name, rather than a value which may be used more generally to obtain available information in the dictionary about a named word. Often this information is called the header data, or simply the header, for a word. The intent of the description in 15.3.1 is to make an association between a "name token" and a named-word, in contrast to an unnamed-word, rather than to restrict which header data may be obtained from the token.
Proposal
Replace use of the term "name token" with "named-word token" to represent more precisely the quantity abbreviated as "nt" throughout the text of the standard. Also include a definition of the term, "named-word token," in section 2.1, "Definition of terms".
Replies
requestClarification - Does LIST transfer data to any buffer?
7.2 says:
The current block buffer is the block buffer most recently accessed by BLOCK, BUFFER, LOAD, LIST, or THRU.
This implies that LIST loads the block into a buffer if it is not there already. Also, if you consider that these words were devised for use on bare metal where you have to transfer a complete sector, it is clear that you need to load at least one sector into a buffer.
Interestingly, 7.3.2 mentions conditions that can invalidate a block buffer, but does not mention LOAD, LIST, and THRU. The committee may have considered that these words implicitly call BLOCK, but given that this is not mentioned for these words, this is probably an unintentional omission.
Yes, given section 7.2, it is clear that LOAD loads into a block buffer. This can invalidate the address returned by an earlier BLOCK or BUFFER, but that is not mentioned for LOAD (nor LIST nor THRU) in 7.3.2. It should.
requestClarification - Does LIST transfer data to any buffer?
I also don't see any requirement that a system have more than one buffer, so that a straight block-to-block transfer would be guaranteed to work
e.g : BCOPY ( blk1 blk2 -- copy contents of block1 to block2 ) SWAP BLOCK SWAP BLOCK 1024 MOVE UPDATE ;
If there is only one buffer, the second call to BLOCK will overwrite the first.
requestClarification - Does LIST transfer data to any buffer?
The intention was that BLOCK works in the historical way. In historical systems, LOAD, LIST, THRU, and in fact everything that accesses blocks in any way used BLOCK and hence changed the block buffer cache. It has always been a usage requirement that you can't depend on holding pointers to previous calls to BLOCK "for long". To the extent that the standard fails to make all that explicit and misses some invalidation cases, it is an omission.
The committee didn't spend much time on BLOCK; it was seen as a "dead horse" and we had much to do on other fronts. So I'm not surprised that we missed some stuff. The new stuff was argued and nit-picked until we were exhausted, but the BLOCK stuff just sorta slid in with the expectation that anybody using it was already so familiar with it that they knew what to expect, and then it would die a gradual death.
Regarding the number of buffers: I don't recall ever having seen a system with only one block buffer. The need to copy one to another pretty much makes a one-buffer implementation impractical. The standard should make that explicit. Or better yet, get rid of BLOCK entirely, which was my preference during the initial deliberations. The "lifetime of a block pointer" issue is just too problematic for modern systems. (That said, I did actually use BLOCK as a factor inside some of my filesystem implementations - but it was a private implementation that was used only inside the filesystem, so the characteristics and usage patterns were controlled.)
requestClarification - Environment dependence of test cases
First of all, thank you very much for clarifying the history of this test and providing a workable 16-bit version!!
Second, I was making a mistake using these tests.
Every other test that I've run here -- and I do not have the test harness, so I just copy the code between T{ and -> and paste it into my Forth, then look at the stack -- every other test works doing that. But these two are special in that they require the T{ at the beginning of the line because they manipulate the >IN variable and rely on having T{ at the beginning.
Furthermore, the second test also relies on "GCD calculation" at the end, and for some reason, when I first read this and tried it, I thought that was a comment, but I see now it's needed for this to work.
Now I have both these tests working.
Thanks again.
requestClarification - Does LIST transfer data to any buffer?
A block-to-block copy is not guaranteed to work even if more than one buffer exists, because the second call to BLOCK (or one would rather use BUFFER) invalidates the address returned by the first call to BLOCK; and I don't see a way to do it as a standard program without copying to an intermediate place. In practice, one would probably do it in a zero-copy way by writing back the buffer to its original block if it was updated, then changing its number to the new block, and marking it as modified with UPDATE. This is not possible in the standard, though.
Concerning a one-buffer implementation: My original implementation of the block wordset for Gforth was a minimal implementation and used just one buffer. It has been replaced with a more sophisticated multi-buffer implementation later.
Right, autofocus added to searchbox.