Digest #303 2025-08-02

Contributions

[391] 2025-08-01 16:01:48 EricBlake wrote:

referenceImplementation - Cross-reference to the suggested implementation

The standard already includes a reference implementation for CASE OF ENDOF ENDCASE, but it it tucked away in annex A Rationale instead of the more traditional annex E used by most other reference implementations; hence it does not show up when browsing to this page online. So maybe that makes this more of a web page request than yet another reference implementation - but to make life easier for the next reader: https://forth-standard.org/standard/rationale#paragraph.A.3.2.3.2


[392] 2025-08-01 21:33:04 EricBlake wrote:

requestClarification - May OF modify the enclosing case-sys on the control stack?

The stack diagram for OF compilation, ( C: -- of-sys ), implies that it can only add an of-sys, even though presumably the intent is that OF should never be called outside of a CASE/ENDCASE structure and thus there should always be a case-sys somewhere higher on the control stack (whether or not that is also part of the data stack). On the other hand, ENDOF is clear that the case-sys must be adjacent to the of-sys (at least in terms of the control stack), and that it can be modified, since it specifies ( C: case-sys1 of-sys -- case-sys2 ).

And yet, the standard also includes a sample implementation of OF that does modify the enclosing case-sys: https://forth-standard.org/standard/rationale#paragraph.A.3.2.3.2, when it gives : OF ( #of -- orig #of+1 / x -- ). Viewing the reference in context, it is clear that it implements case-sys as a variable length structure consisting of 0 or more orig and one u (and in fact, where the representation may be split across the data stack for u and the control stack for the array of orig). If OF is permitted to modify the case-sys, then one could view that implementation as having an of-sys that occupies zero cells. And the entire reason that the reference implementation modifies case-sys in OF is because it is careful to use >R and R> to move #of out of the was so before doing any work that manipulates the control stack, in case the POSTPONE ELSE of ENDOF is using 1 CS_ROLL, and regardless of whether the control stack shares the data stack.

See also the enlightening discussion on whether LEAVE may modify its enclosing do-sys; https://forth-standard.org/standard/core/LEAVE#contribution-185; to which the committee replied that it is not compliant for LEAVE to modify the control stack (because there, the standard mandated ( -- ) rather than permitting ( C: do-sys1 i*x -- do-sys2 i*x ), even though such an implementation would be unlikely to trip up any production program.

I'm left scratching my head as to how to portably implement an OF that only appends an of-sys, and then ENDOF that merges the of-sys into the adjacent case-sys, without requiring carnal knowledge of whether the control stack shares the data stack. Trying to use of CS_PICK and CS_ROLL, even with the addition of CS_DROP https://forth-standard.org/proposals/cs-drop-revised-2019-08-22-#reply-1370, doesn't help; those are specified to operate on dest and orig without any correlation to how they might fare on case-sys or of-sys in the mix. That said, on a simple a system where orig and dest are one cell each, and where the control stack resides on the data stack, a solution with the same variable-length case-sys (namely, orig*n n) is trivial: Just move the +1 out of OF and into ENDOF; and at that point you might as well rely on SWAP instead of >R and R>:

: OF ( C: -- of-sys ) ( runtime: x1 x2 -- | x1 )
  POSTPONE OVER POSTPONE  = ( runtime: x1 flag )
  POSTPONE IF ( C: of-sys ) ( runtime: x1 ) \ where of-sys and orig are identical
  POSTPONE DROP ( runtime: -- )
; IMMEDIATE
: ENDOF ( C: case-sys1 of-sys -- case-sys2 )
  POSTPONE ELSE ( C: orig*n n orig1 -- orig*n n orig2 ) \ convert of-sys to orig2, where case-sys is a variable-length orig*n n
  SWAP ( C: orig*n orig2 n ) \ abuse carnal knowledge of relation between n and orig2
  1+ ( C: orig*[n+1] n+1 ) \ case-sys2 is now one cell larger than case-sys1
; IMMEDIATE

Replies

[r1464] 2025-07-31 09:43:47 AntonErtl replies:

requestClarification - Must the xt returned by DEFER@ have the same value as the one passed to DEFER!, or merely the same behavior?

About "encode the difference between interpretation and compilation semantics". For immediate words, there is no difference. If a Forth system supports arbitrary combinations of interpretation and compilation semantics (e.g., with Gforth's interpet/compile:), the same xt can represent the interpretation semantics of one word and the compilation semantics of another word. E.g.:

: foo ." foo" ;
: bar ." bar" ;
' foo ' bar interpret/compile: foobar

Here the interpretation semantics of bar has the same behaviour as the compilation semantics of foobar. But actually, when you use s" foobar" find-name name>compile to access the compilation semantics of foobar, the result is the same as you get from ' bar ' execute.

So, I don't see a point in encoding "the difference between interpretation and compilation semantics". Any behaviour of a word can be both.


[r1465] 2025-07-31 10:31:50 AntonErtl replies:

requestClarification - 3.2.1.1 vs. Double-cell integer behavior on unusual integer architectures

The question is what the goal of the next Forth standard should be. 1) Should it make it easy to implement Forth on the most exotic platforms? 2) Should it standardize common practice among mainstream systems? 3) Should it standardize common practice used by Forth programs?

My take is that 3 is the most important of these goals.

In the present case we have the common practice among mainstream systems that all bits in one cell (for singles) and, for doubles, two cells are used. Which properties that such an implementation has are used by how many programs? I don't know, and I actually don't have an easy way to test existing programs for determining such questions. In any case, when I write a program using doubles, that's the mental model I use, so the program could acquire an environmental dependency on such an implementation at any point. Given this situation, I don't see a good reason not to standardize such a model.

Concerning supporting Forth systems for exotic platforms, Forth-94 has aimed at that, and Forth-2012 still contains the same rules as far as number representations are concerned. So Forth-2012 may be the right standard for exotic platforms.


[r1466] 2025-07-31 16:50:19 GerryJackson replies:

testcase - Compilation of a VALUE child word should not inline its current value

While it would be easy to add the tests you suggest I don't think it's a good idea. You made an error with your 'optimisation' which such tests would have detected, but there are many possibilities that Forth implementations and optimisation of compiled code can actually give the wrong answer (not just for the case you report). It would not be cost effective, if not impossible, to predict what code compiler developers could generate incorrectly other than the behaviour specified in the standard.


[r1467] 2025-08-01 05:49:00 AntonErtl replies:

testcase - Compilation of a VALUE child word should not inline its current value

Yes, it's not possible to test for everything. In this case the test is against a bug that has actually existed. Such bugs have a tendency to reappear (known as regression), and therefore such tests are added to test suites as regression tests.

Also, system implementors can implement the same bug independently: Just two years ago Francois Laagel discovered the same bug (IIRC incorrect handling of counted-loop parameters upon throw) in the 64-bit versions of two major Forth systems that did not have this bug in their 32-bit versions.


[r1468] 2025-08-01 11:39:15 GerryJackson replies:

testcase - Compilation of a VALUE child word should not inline its current value

OK, I've added the suggested tests to file coreexttest.fth


[r1469] 2025-08-01 11:48:07 GerryJackson replies:

testcase - Compilation of a VALUE child word should not inline its current value

I meant to add I've modified the file on the GitHub repository only. Presumably the person responsible for the forth-standard.org website will have to update the 'Testing' section of the VALUE specification. For their information the tests I've added are: After the existing T{ VAL1 -> 222 }T Add: T{ 444 TO VAL1 -> }T T{ VD1 -> 444 }T