Saturday, September 3, 2022

Non sequential computing environment and Forth -2-

In part -1- of this series this table was presented to to show some Forth words.
The header part of the table is in bold.

Table 1
  TOS n1  n2 n3 
 SWAP  TOS n2 n1 n3
 DROP TOS - 1 
 n2  n3
  + TOS - 1
 n1 + n2  n3

This table is not (yet) a real Forth table and also can be simplified.
Calculations in this table are 'normal algebra' and not in Forth RPN calculations.
'Normal algebra' n1 + n2 becomes in RPN  n1 n2 + 
As already mentioned in my previous post the change of TOS depends on the amount of bits. The TOS should perhaps should be decremented by 2 or another value depending on the amount of bits in each stack item and the memory width.  It is a system constant depending on the implementation.
In this article series i will use SWDTH (stack width). In the RPN table  TOS - 1 should be written as TOS  SWDTH -

Table 2
  TOS n1  n2 n3 
 SWAP  TOS n2 n1 n3
 DROP TOS SWDTH -
 n2  n3
  + TOS SWDTH - 
 n1 n2 +   n3

Some things in this table are still confusing (however it looks already more Forth).
For example a 'strange historical convention' of n1 n2 n3 where
n1 is the item on top of the stack,  n2 is the item just below it and n3 is two steps below. Another way is to see n1 n2 n3 as memory locations where values calculated are stored.  n1 is TOS @ and n2 is TOS SWDTH - @

Table 3
  TOS n1  n2  n3 
  TOS TOS @  TOS SWDTH - @  TOS SWDTH 2* - @ 
 SWAP  TOS n2 n1 n3
 DROP TOS SWDTH -
 n2  n3
  + TOS SWDTH - 
 n1 n2 + n3

In a real 'physical' implementation of the table it would be needed to include items above the TOS (Top Of the Stack) in case items are added or pushed to the stack. Also it would be strange to represent the first items above the stack using n0 . It would be more systematic if the item on top of stack was referenced as n0 and use n+1 and n-1 for the items just above or below. However in Forth for many years items on the stack where called n1 n2 n3 and breaking with this convention would cause a lot of confusion. Also we do not want tot use complicated difficult to read terms as TOS @ or TOS SWDTH - @  So i decided (temporary) to use p0 and not n1 see tabel below.

Table 4

TOS ( n0 ? )n1n2n3

TOSp1p0p-1p-2

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPTOS
n2n1n3
DROPTOS SWDTH -

n2n3
+TOS SWDTH -

n1 n2 +n3

In the next evolution of the table i added an example of a Forth word that pushes a value to the stack.
It is the Forth word 0 . It is a number implemented in this Forth table where the value 0 is pushed to the stack.
In the table header a new Forth word PA is introduced ( shorthand for ParameterStackAddress ).
The location is described using Forth word  PA to avoid using n1 n2 n3 or p0 p1 p2 notations, 

 : PA SWDTH * TOS @ + ;

Table 5

TOS ( n0 ? )n1n2n3


p1p0p-1p-2
Location TOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPTOS
n2n1n3
DROPTOS SWDTH -

n2n3
+TOS SWDTH -

n1 n2 +n3
0TOS SWDTH +0n1n2n3

We now have almost everything described in Forth and RPN
To evolve the table further we need to do something with the gaps (empty spaces).

In fact there are several options to handle these gaps.
A) Handle a gap as something that not needs to be changed  ( "Ignore" or "don't change" )

Table 6a

TOS ( n0 ? )n1n2n3


p1p0p-1p-2
LocationTOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPTOSIgnoren2n1Ignore
DROPTOS SWDTH -IgnoreIgnoreIgnoreIgnore
+TOS SWDTH -IgnoreIgnoren1 n2 +Ignore
0TOS SWDTH +0IgnoreIgnoreIgnore

B) Fill gap with a "Null" value
"Null" is a special marker and keyword indicating that something has no value (in SQL )
Using  option 2 ( Null) the small table the table would look as below.

Table 6b

TOS ( n0 ? )n1n2n3


p1p0p-1p-2

TOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPTOSNulln2n1n3
DROPTOS SWDTH -NullNulln2n3
+TOS SWDTH -NullNulln1 n2 +n3
0TOS SWDTH +0n1n2n3

Both representations have advantages and disadvantages.
I like option B) using Null as this removes garbage (data that is no longer needed) from the system. Keeping items in a system that are no longer needed can introduce errors and vulnerabilities,

C) A third option could be using Null and, when no changes are needed use some kind of Noop  (no operation, do nothing) indicator.

Table 6c

TOS ( n0 ? )n1n2n3


p1p0p-1p-2

TOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPNoopNulln2n1Noop
DROPTOS SWDTH -NullNullNoopNoop
+TOS SWDTH -NullNulln1 n2 +Noop
0TOS SWDTH +0NoopNoopNoop

If Null and Noop are Forth words a table can be created that describes Forth words in Forth code. The Noop has as disadvantage that just rewriting the old value perhaps is as fast or even faster then  evaluating that something is a Noop and not changing a value.

Table 7

TOS ( n0 ? )n1n2n3


p1p0p-1p-2

TOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPNoopNull-1 PA0 PANoop
DROPTOS SWDTH -NullNullNoopNoop
+TOS SWDTH -NullNull0 PA -1 PA +Noop
0TOS SWDTH +0NoopNoopNoop

Extending the table with more Forth words gives the next table (Table 8)

Table 8

TOS ( n0 ? )n1n2n3


p1p0p-1p-2

TOS1 PA0 PA-1 PA-2 PA

TOSTOS SWDTH + @TOS @TOS SWDTH - @TOS SWDTH 2* - @
SWAPNoopNull-1 PA0 PANoop
DROPTOS SWDTH -NullNullNoopNoop
+TOS SWDTH -NullNull0 PA -1 PA +Noop
0TOS SWDTH +0NoopNoopNoop
1TOS SWDTH +1NoopNoopNoop
2TOS SWDTH +2NoopNoopNoop
3TOS SWDTH +3NoopNoopNoop
4TOS SWDTH +4NoopNoopNoop
-1TOS SWDTH +-1NoopNoopNoop
-2TOS SWDTH +-2NoopNoopNoop
NoopNoopNoopNoopNoopNoop
-TOS SWDTH -NullNull0 PA -1 PA -Noop
*TOS SWDTH -NullNull0 PA -1 PA *Noop
/TOS SWDTH -NullNull0 PA -1 PA /Noop
=TOS SWDTH -NullNull0 PA -1 PA =Noop
@NoopNull@NoopNoop
!TOS SWDTH -NullNullNullNoop
2*NoopNull2 *NoopNoop
2*NoopNull2*NoopNoop
TOSTOS SWDTH +TOSNoopNoopNoop
TOSTOS SWDTH +"Value"NoopNoopNoop
SWDTHTOS SWDTH +"Value"NoopNoopNoop
SWDTH+NoopNullNoopNoopNoop
SWDTH-NoopNullNoopNoopNoop

In the last part of table 8 some issues can be seen that need (and can) be solved.  Therefor i did write it in Italics and some words i described in multiple ways.

! Can't be full described in this table.The result of ! will be that 2 items are removed from the stack. An address and a value. The value will be stored at the address. However it is not easy to extend the lookup table so it will include all addresses in memory. ( @ can be described in the table. However there must be some kind of low level implementation!)

2* multiplies the value that is on top of stack by two. It can be described as just doing 2 *
Written in Forth code : 2* 2 * ;  
However in some Forth systems this is implemented in low level code as it can be executed fast,  This is just one example, however in general this creates a dilemma when trying to make a table like this. Many Forth words can easy be defined as itself, However that does not explain what these Forth words do. Also sometimes these words can be implemented in another way using other Forth words or should  call low level code.  

TOS ( Top Of Stack) is a variable. It it can be put in the table just calling some implementation of itself. However an easy implementation is pushing 'the value of the address' on the stack.

 SWDTH is a (system) constant, as described in the beginning of this article. A constant can be described in this table as it self, Or just put the value on the stack comparable to TOS

Some sequences of operations appear very often in this table. Examples are
TOS SWDTH + and TOS SWDTH + and also my new Forth word PA
  : PA SWDTH * TOS @ + ;
This indicates that speeding up these sequences can speed up the Forth system. 

We have seen that we can put the descriptions of (several) Forth words in a table.
Can that help us in a new Forth implementation and what about a 'Non sequential computing environment'? Yes, if we can describe Forth words in a table we can describe Forth in a table. This not only makes Forth portable, it also makes it possible we can create Forth in a table environment, e.g. a relational database.

No comments: