Digest #191 2022-08-13

Contributions

[248] 2022-08-12 10:21:25 ruv wrote:

referenceImplementation - Implementing COMPILE, via EXECUTE

compile, can be implemented in the following way:

: compile, ( xt -- )  postpone literal  postpone execute ;

It's not an efficient implementation, but a correct and portable one.


[249] 2022-08-12 14:18:35 ruv wrote:

proposal - Revert rewording the term "execution token"

Author

Ruv

Change Log:

  • 2022-08-12 Initial version
  • 2021-09-14 Formulation of the problems in a comment

Problem

The proposal Reword the term "execution token" suggests to change the definition for the term "execution token".

The original variant:

execution token: A value that identifies the execution semantics of a definition.

The new variant:

execution token: A value that can be passed to EXECUTE (6.1.1370)

It has the following issues.

  1. This changing was suggested to solve a problem that this definition allegedly does not match its usage in FIND, ', ['], NAME>INTERPRET, NAME>COMPILE. But this problem does not exist, as I shown in a comment. Anton (the proponent) had not answer to my reasoning.

  2. The accepted variant of the definition doesn't solve anything, but it introduces a number of new problems, as I shown in a comment.

    • Now the fundamental term definition is based on a Forth word (terms should be used in the Forth words specifications, but not Forth words in terms).

    • Now a new lacuna is introduced into the normative text — it's unclear what a data object of "execution token" data type means (see 3.1 Data types, 3.1.3.5 Execution tokens, 15.3.1 Data types for name token, as an example).

    • Other normative parts (for example, 6.1.1370 EXECUTE) still assume that an execution token identifies execution semantics, but now groundlessly.

    • The accepted definition is recursive, since it's based on the word EXECUTE, which in turn is based on "execution token" data type (via xt data type symbol, see also 2.2.2 Stack notation). So it says that "execution token" is a value that is an execution token.

Solution

Don't introduce the changes of the proposal «Reword the term "execution token"», or revert the definition for the term "execution token" as it was in Forth-2012.

Proposal

In Section 2.1, change:

execution token: A value that can be passed to EXECUTE (6.1.1370)

into

execution token: A value that identifies the execution semantics of a definition.


[250] 2022-08-12 15:04:29 ruv wrote:

proposal - Formatting: spaces in data type symbols

Author

Ruv

Change Log

  • 2022-08-12 Initial version

Problem

In Forth-94 no data type symbol contain a space. In Forth-2012 some data type symbols contain spaces, so stack diagrams are worse read.

Some examples

Forth-94

( i*x xt -- j*x )
( n1|u1 n2|u2 -- n3|u3 ) 

Forth-2012

( i * x xt -- j * x )
( n1 | u1 n2 | u2 -- n3 | u3 ) 

Solution

Remove spaces from data type symbols.

Proposal

Everywhere in the text of the standard replace u | n, u_ | n_, i * x, j * x, k * x by u|n, u_|n_, i*x, j*x, k*x correspondingly.

Replies

[r840] 2022-07-31 01:40:24 kc5tja replies:

example - Interactions with MARKER and KILL-TASK

<blockquote>This solution is harmful, since users would rely on this solution as if it is a reliable solution, and probably will not think whether a marker will remove some data or code that is used by some running thread, if the corresponding task is defined before the marker.

This paragraph does not make any sense to me. Can you rephrase this to be more clear?


[r841] 2022-07-31 01:46:14 kc5tja replies:

example - Stack Sizes?

<blockquote>This problem already exists for a standard program: how does one ensure the data and return stacks are large enough to allow the program to run? There is no a standard API for that at the moment.

Yes, of course; this is patent. The question was, <b>how, using the proposed API, do we specify these extents? Explicit stack sizes are required for MMU-less systems, but the API proposed above lacks any means of specifying how big a data or return stack is to be. SwiftForth, for example, uses a version of TASK which accepts these parameters on the data stack, allowing a programmer to specify them explicitly.


[r842] 2022-07-31 14:41:20 ruv replies:

example - Interactions with MARKER and KILL-TASK

it would be necessary to bring those tasks down cleanly (even if rudely) before reverting HERE to somewhere ahead of their task records.

Since rewriting the task record of a running task (when you load something into the dictionary after HERE was reverted) can lead to crash, can't it?

But if HERE is reverted ahead of any data or code that is used by some other running task, it can lead to crash as well.

So, when you take into account only task records, you make false impression of reliability. But it's impossible to take into account all data or code.

An example:

task t2
defer t2.core
:  t2.proc ( -- ) begin t2.core 1000 pause-ms again ;


marker end-program

task t1

:noname 123 . cr ; is t2.core

:  t1.proc ( -- ) ['] t2.proc t2 start-task  ;

' t1.proc t1 start-task

end-program

Even if end-program kills t1, t2 is still running. And it doesn't matter in what way t2 was started, the only important thing that the code which is used in t2 was removed by end-program (and this code will be overwritten when you load something into the dictionary).

So, the marker words (i.e., the definitions created by marker) should not take into account the running tasks/threads. But the corresponding ambiguous condition should be probably explicitly mentioned for marker (see my comment).


[r843] 2022-08-01 05:14:30 kc5tja replies:

example - Interactions with MARKER and KILL-TASK

<blockquote>Even if end-program kills t1, t2 is still running.

Ahh! That's a good catch! I didn't think about that case. Thank you for pointing it out.


[r844] 2022-08-11 19:10:15 ruv replies:

example - Stack Sizes?

The question was, how, using the proposed API, do we specify these extents?

Obviously, the proposed API doesn't provide any way for that.

A standard system may have many stacks. Among them: the data stack, return stack, floating-point stack, control-flow stack, exception stack, local variables stack. All the stacks should be local for a thread.

But a standard program (that is portable) doesn't know what stacks are employed in the system (as separate stacks), and how many cells of each stack are used in the system routines. Hence the program cannot reliably set the absolute size for the stacks at all.

What a program can do is inform the system what size for a stack is required for the program's needs — so, the system can free unneeded memory of the stack, or reserve smaller space for the stack, or reserve a bigger space for the stack, or throw an exception (or return a throw code) if the required space cannot be allocated (taking into account the system's own needs) — but it's up to the system whether the stack will be actually reduced or not.

I think, this capability is most wanted for the data stack and return stack, so we might not consider other stacks for a while.

The next question: what thread is the subject for stack changing?

  • the current thread (then the API will be capable for single-thread systems too);
  • the new thread, before creating;
  • any other thread.

In the first option, the API can be like the following:

need-data-stack ( u -- ior ) \ inform the system that the program needs u cells of the data stack for the program's needs
need-return-stack ( u -- ior )  \ inform the system that the program needs u cells of the return stack for the program's needs

ior should be a special nonzero value if the system cannot provide at least u cells of the stack for the program's needs. An ambiguous condition exists if the operation was success and the program will use more than u cells of the stack after that.


[r845] 2022-08-11 19:26:40 ruv replies:

example - Stack Sizes?

This solution it not well adequate when a program uses third party libraries, since it could be unaware what stack size is required for the library's routines.