,---------------. | Contributions | `---------------´ ,------------------------------------------ | 2025-08-09 15:54:10 JimPeterson wrote: | referenceImplementation - Possible Reference Implementation | see: https://forth-standard.org/standard/string/COMPARE#contribution-398 `------------------------------------------ I suggest the following as a reference implementation: ``` : _cmp ( x1 x2 -- -1|0|1 ) - DUP IF 0< 1 OR THEN ; : COMPARE ( addr1 u1 addr2 u2 -- -1|0|1 ) ROT 2DUP SWAP _cmp >R MIN ?DUP IF 0 DO COUNT >R SWAP COUNT R> _cmp ?DUP IF NIP NIP UNLOOP R> DROP EXIT THEN SWAP LOOP THEN 2DROP R> ; ``` ,---------. | Replies | `---------´ ,------------------------------------------ | 2025-08-08 14:00:22 JimPeterson replies: | comment - `?:`? | see: https://forth-standard.org/standard/core/Colon#reply-1485 `------------------------------------------ I suppose the concept is somewhat niche, in the sense that it addresses a concern for Forth coders who wish to write code that is not only portable across multiple (or really *all* Core-supporting) implementations, but also ekes out every ounce of efficiency possible. I imagine cross-implementation coding is likely currently achieved with stanzas like: ``` platform-is-X [IF] \ ... X-specific definitions [THEN] platform-is-Y [IF] \ ... Y-specific definitions [THEN] ``` where the specific optimizations and coverages are switched out based on known platform optimizations, whereas the `?:` concept is more focused on individual words needed, and would therefore adapt even to implementations unknown to the author and to improvements when some of the words are added to new versions of existing implementations. Moreover, `?:` is certainly not sufficient for words that work together, like `TO`/`VALUE` or `DEFER`/`IS`/etc. Such words would still require `[IF]`/`[THEN]` stanzas. I definitely prefer the Core-only implementation (although `:NONAME` is Core-ext and `VALUE`/`TO` would need to be changed to `VARIABLE`), as my main focus is tiny implementations used for custom hardware, which may not have a full suite of extensions, and for which every bit of memory and performance matters. While I understand that `MARKER` is likely a much more comprehensive manner of rewinding a definition, I'm not really proposing this particular implementation as much as I am the concept of a word like `?:`. The implementation I present is really more a proof-of-concept demonstration of behavior, and each Forth system would have whatever it considers most appropriate. That being said, besides rewinding `HERE`, I have no idea what other lasting effects a rewound `:NONAME` definition would have on the system (except as pertains to `IMMEDIATE` and other `IMMEDIATE`-like words). This Core-only focus, however, implies that the `?:` would only be of use if it was found in Core, itself. Otherwise, a stanza of the form `[UNDEFINED] ?: [IF] ... [THEN]` would be necessary, and not only that but, since `[UNDEFINED]`, etc. are not even in Core, it may become challenging to include an appropriate header that covered all possiblities... ``` \ poor man's Core-only [IF]/[THEN] (avoid using ')' in clauses): : ) ; : IF( 0= IF POSTPONE ( THEN ; \ Core-only... can't rely on [UNDEFINED]: BL WORD ?: FIND NIP 0= IF( \ make sure `IMMEDIATE` is ok \ to call even after a `:NONAME` CREATE IMMEDIATE-OK 0 , : : : -1 IMMEDIATE-OK ! ; : :NONAME :NONAME 0 IMMEDIATE-OK ! ; \ from Core-ext! : IMMEDIATE IMMEDIATE-OK @ IF IMMEDIATE THEN ; CREATE SKIP-DEF 0 , : ; POSTPONE ; SKIP-DEF @ IF DROP HERE - ALLOT 0 SKIP-DEF ! THEN ; IMMEDIATE \ usage: `?: -ROT ROT ROT ;`, for instance, will \ define `-ROT` only if it's not already defined. : ?: >IN @ BL WORD FIND NIP IF \ skip definition: DROP HERE -1 SKIP-DEF ! :NONAME \ from Core-ext! ELSE \ back up and define >IN ! : THEN ; ) ``` ,------------------------------------------ | 2025-08-08 17:51:25 EricBlake replies: | comment - `?:`? | see: https://forth-standard.org/standard/core/Colon#reply-1486 `------------------------------------------ ``` \ make sure `IMMEDIATE` is ok \ to call even after a `:NONAME` CREATE IMMEDIATE-OK 0 , : : : -1 IMMEDIATE-OK ! ; : :NONAME :NONAME 0 IMMEDIATE-OK ! ; \ from Core-ext! : IMMEDIATE IMMEDIATE-OK @ IF IMMEDIATE THEN ; ``` As written, this does not pass the testsuite. For a simple example: ``` :NONAME ; DROP 1 CONSTANT one IMMEDIATE ``` fails to make `one` immediate, because it was defined with `CONSTANT`, yet the most recent `:NONAME` has not been countermanded by `:`. One way to fix it is wrapping ALL the defining words (CONSTANT, VARIABLE, VALUE, BUFFER:, CREATE, 2VARIABLE, ...), but that doesn't scale (how do you portably learn which defining words a system natively supports, since some like 2VARIABLE are optional, and since the user can create more defining words, as you have just done with `?:`). So I tried a different approach: https://github.com/ForthHub/discussion/discussions/197 By making IMMEDIATE immediate, you can write: ``` : name IMMEDIATE body... ; ``` as syntax sugar for the standard `: name body... ; IMMEDIATE`, but more importantly, if you then use: ``` ?: RDROP IMMEDIATE POSTPONE R> POSTPONE DROP ; ``` you either get a definition for RDROP that is immediate, or you get a :NONAME whose body is compiled to perform the effects of immediate at whatever future time(s) the xt is executed, in addition to its other semantics. You really don't want an RDROP that has the side effect of marking random words immediate; but on the other hand, your only use of :NONAME is for something you plan to throw away by rewinding HERE, so it will never be executed, and thus you never have an opportunity to see that subtle change in semantics between `:` and `:NONAME` for a leading immediate IMMEDIATE. Plus, once you switch to that style, you no longer have to implement IMMEDIATE-OK, and thus you manage to correctly support IMMEDIATE after all named defining words, without having to wrap every one of them. ,------------------------------------------ | 2025-08-08 18:15:40 AntonErtl replies: | proposal - minimalistic core API for recognizers | see: https://forth-standard.org/proposals/minimalistic-core-api-for-recognizers#reply-1487 `------------------------------------------ Another point that I missed up to now and that others may have missed, too, is the order of recognizers in when using `recognizer-sequence:`: As currently specified, you use this word as follows ```` ' rec-float ` rec-num ` rec-nt 3 recognizer-sequence: tradforth ```` And `tradforth` will first invoke `rec-nt`, then `rec-num`, and then `rec-float`. I find this order counterintuitive, but an argument for it is that it agrees with the order in `get-order` and `set-order`. In any case, I think we should discuss this. ,------------------------------------------ | 2025-08-08 18:37:48 EricBlake replies: | proposal - Pronounciations | see: https://forth-standard.org/proposals/pronounciations#reply-1488 `------------------------------------------ It would be helpful to use the proper spelling "Pronunciation" rather than "Pronounciation". ,------------------------------------------ | 2025-08-09 15:30:12 JimPeterson replies: | referenceImplementation - Possible Reference Implementation | see: https://forth-standard.org/standard/string/SEARCH#reply-1489 `------------------------------------------ I'm not sure your version works (assuming `4TH` means `3 PICK`), as towards the end of the string, `COMPARE` may be accessing characters at caddr1+u1 and beyond. I think if you changed the `DUP` to `2 PICK OVER <=` it may work better. I think this also points to a missing test(s) of this sort: ``` T{ : s8 S" xyz" ; -> }T T{ s1 2 - s8 SEARCH -> s1 2 - }T ``` which tries to ensure that the code does not access characters that it shouldn't. The corrected version is: ``` : SEARCH ( caddr1 u1 caddr2 u2 -- caddr3 u3 flag ) 2OVER \ retain a copy of 1st string BEGIN 2 PICK OVER <= WHILE 2OVER 3 PICK OVER COMPARE WHILE 1 /STRING REPEAT 2NIP 2NIP TRUE EXIT \ string found THEN 2DROP 2DROP FALSE \ string not found ; ``` ,------------------------------------------ | 2025-08-09 15:46:15 JimPeterson replies: | referenceImplementation - Possible Reference Implementation | see: https://forth-standard.org/standard/string/SEARCH#reply-1490 `------------------------------------------ ... apparently, `<=` is not standard, so maybe `> 0=` instead? ,------------------------------------------ | 2025-08-09 16:13:21 JimPeterson replies: | comment - `?:`? | see: https://forth-standard.org/standard/core/Colon#reply-1491 `------------------------------------------ This is interesting, and my original Forth implementation had `IMMEDIATE` as an immediate word (mostly because I didn't know Forth well enough... coincidentally, my first introduction being via JonesForth, as well). Unfortunately, I have the following: ``` create _to 0 , : TO 1 _to ! ; immediate : VALUE create , immediate does> STATE @ if _to @ if postpone literal postpone ! else postpone literal postpone @ then else _to @ if ! else @ then then 0 _to ! ; ``` where `VALUE` creates a word and then makes the created word immediate. I think that's one of the main capabilities intended by `IMMEDIATE` not being immediate, is that you can define words that define other words which themselves are immediate. Of course, you could always use `POSTPONE` in such situations, but unfortunately the die is cast. Of course, again, all of this is just a rough draft at how it could work. If `?:` was included, an implementation could just simply ignore an `IMMEDIATE` that occurs after a `:NONAME`. ,------------------------------------------ | 2025-08-09 17:17:51 JimPeterson replies: | comment - `?:`? | see: https://forth-standard.org/standard/core/Colon#reply-1492 `------------------------------------------ hmm... I see you actually handle the `DOES>` case in your implementation. Still, all of this could be avoided if the standard simply said "Using `IMMEDIATE` after a `:NONAME` definition is a no-op", or something.