,---------------. | Contributions | `---------------´ ,------------------------------------------ | 2024-08-05 11:19:09 ruv wrote: | requestClarification - Temporary removing system-compilation items | see: https://forth-standard.org/standard/usage#contribution-355 `------------------------------------------ [3.1.5.1 System-compilation types](https://forth-standard.org/standard/usage#subsubsection.3.1.5.1) says: > These data types denote zero or more items on the control-flow stack (see 3.2.3.2). The possible presence of such items on the data stack means that any items already there shall be unavailable to a program until the control-flow-stack items are consumed. In the following definition I temporary consume the system-compilation items from the data stack using `n>r`, to access the item _x_ already there: ``` : const ( x "name" -- ) depth >r ( x ) ( R: n.depth ) : ( x colon-sys ) ( R: n.depth ) depth r> - ( x colon-sys n.colon-sys-size ) ( R: ) n>r ( x ) ( R: i*x n.colon-sys-size ) postpone literal ( ) ( R: i*x n.colon-sys-size ) nr> ( colon-sys n.colon-sys-size ) ( R: ) drop ( colon-sys ) postpone ; ( ) ; ``` I think it's compliant with 3.1.5.1, because the item _x_ is really "unavailable to a program until the control-flow-stack items are consumed" by `n>r`. But in the message [r1281](https://forth-standard.org/standard/core/Colon#reply-1281) Anton says that it is non-standard. It's unclear, why a standard program is not allowed to temporary remove system-compilation items from the data stack? Does "consume" have a special meaning other than "remove from the stack"? For example, this term is informally used in phrases like "Forth words consume their arguments". It this approach is non-standard, what changes to the wording of the section 3.1.5.1 could make it standard, theoretically? ----- BTW, I saw many case when this approach is used to access _xt_ that `:noname ( x colon-sys )` leaves on the data stack, under _colon-sys_. Typical usage: ``` : :foo depth >r :noname depth r> - 1- roll ( colon-sys xt ) ... \ consume xt ; :foo ... ; ``` A real example: [gforth/minos2/md-viewer.fs](https://github.com/forthy42/gforth/blob/master/minos2/md-viewer.fs#L356) ``` : md-char: ( "char" -- ) depth >r :noname depth r> - 1- roll md-char ; ``` ,---------. | Replies | `---------´ ,------------------------------------------ | 2024-08-05 02:18:50 ruv replies: | requestClarification - Unspecified ambiguous condition in /STRING | see: https://forth-standard.org/standard/string/DivSTRING#reply-1278 `------------------------------------------ The rationale says: "`/STRING` is used to remove or add characters relative to the current position in the character string. Positive values of _n_ will exclude characters from the string while negative values of _n_ will include characters to the left of the string." The specification says that resulting character string has length "**_u1_ minus _n_ characters**". **It's impossible to remove any character from a string whose length is zero**. Therefore, if If _n_ is greater than _u1_, the operation cannot be interpreted as removing characters from the string, and the result cannot be interpreted as a character string, despite the specification says that it's a character string. So, I think, the case when _n_ is greater than _u1_ should be somehow described to eliminate this confusion. For example: > Note: if _n_ is greater than _u1_, _u2_ is the result of wraparound on underflow, and _c-addr2 u2_ does not represent a character string. ,------------------------------------------ | 2024-08-05 03:28:07 ruv replies: | requestClarification - definion and use of colon-sys and nest-sys | see: https://forth-standard.org/standard/core/Colon#reply-1279 `------------------------------------------ > I couldn't find any rule or requisite relative to _colon-sys_ or _nest-sys_ wich has sense since it is implementation dependent but then why to mention? They are mentioned to relax systems and tighten programs. Namely, **to allow** Forth systems to use the data stack and return stack in the certain cases, and **to restrict** programs from direct access their data on a stack (if any) in these cases. For example, due to _nest-sys_ you know why it's incorrect to pass parameters via the return stack as: ``` \ incorrect example : foo r> . ; : bar 123 >r foo ; ``` And due to _colon-sys_ you know that this definition is incorrect: ``` \ incorrect example : const ( x "name" -- ) : postpone literal postpone ; ; ``` And this is correct: ``` : const ( x "name" -- ) >r : r> postpone literal postpone ; ; ``` A program can also use `depth` before and after a _colon-sys_ is placed on the data stack to calculate its size and access data on the data stack via `roll`, `pick`, and between `n>r` and `nr>`. For example: ```forth : const ( x "name" -- ) depth >r : depth r> - n>r postpone literal nr> drop postpone ; ; ``` Also, due to the system-compilation types _colon-sys_ and _orig_ you know why the following program is incorrect ``` : foo if ; ``` Because "An ambiguous condition exists if an incorrectly typed data object is encountered", and in this case: ``` \ stack diagrams for compilation-time : foo ( colon-sys ) if ( colon-sys orig ) \ expected top value by ";" ( colon-sys ) \ actual top value ( orig ) ; ( colon-sys -- ) ``` ,------------------------------------------ | 2024-08-05 04:56:59 ruv replies: | requestClarification - definion and use of colon-sys and nest-sys | see: https://forth-standard.org/standard/core/Colon#reply-1280 `------------------------------------------ > But reading carefully I think **C:** really means control-flow stack Yes, it's described in [2.2.2 Stack notation](https://forth-standard.org/standard/notation#subsection.2.2.2). > there's no Compilation section because word colon has no compilation semantics. No. If "Compilation" section is absent in a glossary entry, the word has default compilation semantics, see [3.4.3.3 Compilation semantics](https://forth-standard.org/standard/usage#usage:compile). > I think it shoud be interpretation semantics Formally, it's execution semantics for `:` (Colon). When it's only one section, the label "Execution" is omitted (see [3.4.3.1](https://forth-standard.org/standard/usage#subsubsection.3.4.3.1)). And the interpretation semantics for `:` (Colon) are the same as the execution semantics (because "Interpretation" section is absent, and the execution semantics does not depend on state). See also [3.4.3.2](https://forth-standard.org/standard/usage#subsubsection.3.4.3.2). > you should see the initiation semantics in the definition list when you perform a `see` on the defined word, It is not necessary, it may show just the source code, see [15.6.1.2194 `SEE`](https://forth-standard.org/standard/tools/SEE). ----- ### Example Let's look at an example: ``` : foo 123 . ; ``` Formally, `:` (Colon) does the following steps in this case: 1. Skip leading space delimiters. Parse "foo" delimited by a space. 2. Start compilation for the new definition `foo` (so `foo` is now the _current definition_). 3. Enter compilation state and produce _colon-sys_. 4. Append the Initiation semantics (specified in [6.1.0450 `:`](https://forth-standard.org/standard/core/Colon)) to the execution semantics of `foo`. NB: The section "Initiation" is not a part of execution semantics of `:` (Colon). It does not matter what the Forth system actually does, as long as a standard program cannot detect the difference. So the order of these steps may be different, and some steps may be missed. Usually, the Initiation semantics are not actually appended into `foo`, but are performed as a part of `execute` and appended by `compile,` (as a part of an internal `call` instruction or the address interpreter), when they are applied to the _xt_ of `foo`. A standard program cannot detect this difference, so it does not matter. Formally, `;` (Semicolon) does the following steps in this case: 1. Append the Run-time semantics specified in [6.1.0460 `;`](https://forth-standard.org/standard/core/Semi) to the execution semantics of `foo`. 2. End compilation of `foo` (so `foo` is not the _current definition_ anymore). 3. Place `foo` into the _compilation word list_ ([16.2](https://forth-standard.org/standard/search#section.16.2)). 4. Enter interpretation state, consuming _colon-sys_. 5. Align the data-space pointer. The order of these steps does not matter as long as a standard program cannot detect that. ,------------------------------------------ | 2024-08-05 08:31:13 AntonErtl replies: | requestClarification - definion and use of colon-sys and nest-sys | see: https://forth-standard.org/standard/core/Colon#reply-1281 `------------------------------------------ 1. Colon-sys is described in more detail in 3.1.5.1: > The implementation-dependent data generated upon beginning to compile a definition and consumed at its close is represented by the symbol colon-sys throughout this standard. Nest-sys is described in more detail in 3.1.5.2: > The implementation-dependent data generated upon beginning to execute a definition and consumed upon exiting it is represented by the symbol nest-sys throughout this standard. Furthermore, both are used in the definitions of `:`, `;`, `does>` and nest-sys is used in the definition of `exit`, and for nest-sys some of the uses in `;` and `exit` clarify their role. 2. Colon-sys is mentioned so that standard systems are allowed to push something on the data stack when starting to compile a colon definition (and standard programs must be written to deal with this situation), and also to specify that every executed `:` must be closed with a `;`, possibly with a `does>` in between. Nest-sys is also mentioned to allow standard systems to push something at run-time on the return stack and to prevent standard programs from accessing return stack entries from before the call. In addition it is needed to describe where `exit` and the run-time semantics of `;` return to. As described in 3.1.5.1, colon-sys is on the control-flow stack, which may be the same as the data stack. Note also that 3.1.5.1 says: > The possible presence of such items on the data stack means that any items already there shall be unavailable to a program until the control-flow-stack items are consumed. Which means that ruv's third definition of `const` is non-standard; his second definition is standard and simpler anyway. So, yes, a standard program always has to assume that `:` puts a colon-sys on the data stack even if it can determine with `depth` that on this particular system the colon-sys has 0 items on the data stack. As described in 3.1.5.2, nest-sys is on the return stack. System types like colon-sys and nest-sys are not first-class types. E.g., there is no way to store them to buffers in memory. 3. Exactly, the standard defines colon-sys and nest-sys in order to allow standard systems to push something to the data stack (colon-sys) and return stack (nest-sys), so that standard programs must deal with this possibility. They are also there to specify the closing of colon definitions (colon-sys) and nesting of calls (nest-sys). 4. The stack comment for the execution semantics of `:` could actually be specified as ``` ( input-stream: "name" -- ; control-flow stack: -- colon-sys ) ``` where "control-flow stack" is ususally writteh as "C". Concerning the input stream, the standard document never produces a separate part of the stack effect description for that, but always lets it run with some other stack effect description, this time the control-flow stack effect. Yes, when you text-interpret `:`, its interpretation semantics are executed, which for `:` is the same as the execution semantics, which is the part that you are citing. The part about appending the initiation semantics means, in a classical indirect-threaded implementation, that you store the address of the machine-code routine docol in the CFA of the new word, and docol then performs the initiation semantics. Various other implementation techniques inline the initiation semantics into the caller in some or all cases. E.g., Gforth inlines it into the caller when you `compile,` the colon definition, but still uses docol when you `execute` the colon definition. Many native-code systems on IA-32 and AMD64 CPUs always `call` (or inline) all kinds of words, both in `compile,`d code and with `execute`, so they always inline all of the initiation semantics in the caller. I have not seen the code that native-code compilers for RISC architectures produce, but I expect that they put a part of the initiation semantics (the part that stores the return address on the return stack) at the start of the native code of the colon definition. The initiation semantics is the first part of the execution semantics (and therefore also of the interpretation semantics) of a colon definition. The newly defined colon definition also has compilation semantics (by default, to append the execution semantics to the definition current at the time when the compilation semantics are performed). `:` itself also has default compilation semantics. I think we answered all the questions, so I am closing this request. If you think that anything is unclear, please reopen it.