Implementation of prototypes of interacting Forth clock generator engines

WILD

Administrator
Staff member
ADMIN
SELLER
SUPREME
MEMBER
Joined
Jan 21, 2025
Messages
219
Reaction score
637
Deposit
0$
1. BackgroundA month ago, I implemented a Forth interpreter in Elixir, which I described on Habr. This hybrid was given the compound name Forth-ibE in honor of its parents (Forth in-build Elixir).The next step in development was defining a messaging API for a distributed Forth developer team to collaborate.The reader will likely have questions like "why" and "why?" Therefore, it is now necessary to describe the solution to several initial difficulties.First, [1] states that"Along with single-task Forth systems, there are also multitask Forth systems. They can handle any number of tasks. A task can be either a terminal task, in which all interactive Forth power is transferred to an operator sitting at a terminal, or a control system, which provides control over equipment without a terminal.A control task has a pair of stacks and a small set of user variables. Since a terminal is not used when executing a control task, it does not require
This signal output cycle requires more preparation. The system timer must be started.:

SysTimer.start_link(nil)

Then auxiliary variables are generated and loaded with values.:

ForthIbE.execute:)e7, "VARIABLE ENDPOINT")

ForthIbE.execute:)e7, "VARIABLE OFFSET")

ForthIbE.execute:)e7, "18000000!")

ForthIbE.execute:)e7, "\"2026-02-18 15:26:22.000\" text-to-unix OFFSET @ THE- END-MARK ! ")

What is OFFSET? This is a variable for converting the local time stamp to the UTC time stamp. For the Asia/Yekaterinburg time zone, it is 5x60x60x1000 milliseconds. It would be possible to perform the cast using some calendar library in Elixir, but I thought that this was not in the spirit of Forth. Please note that all timestamps are linked to UTC [00:00].

Then we load the CLOCK definition into the interpreter.

script = ": CLOCK BEGIN END-MARK @ receive-time > WHILE 500 delay REPEAT tick to-atom END-MARK @ eng-name @ stocks forward .\"LET'S GO! \" ; "

ForthIbE.execute:)e7, script)

In a loop, the engine requests a timestamp from the server using the word receive_time and compares it with the set value of the END-TIMESTAMP variable.

In the cycle, the trigger accuracy is set to 500ms before the word delay. The signal generator starts as usual:

ForthIbE.execute:)e7, "CLOCK")

After exceeding the received timestamp over the final one, the clock generator, in addition to transmitting the timestamp {:tick 24379824 :e7}, outputs a message to the console for ease of debugging.:

Let's go!

Attention is drawn to the periodic request of the current time from the system timer. There may be a critical situation related to the processing time of messages in the mailbox, but there is no other mechanism in Elixir.
7. Two practical examples
7.1. Joint operation of two generators

Now we will program the joint operation of two clock generators: the first signal generator will transmit a signal about the occurrence of a specific date and time, and the second one will then output 10 ticks with an interval of 10 seconds. As a matter of fact, we have already sorted out the relevant templates, we just need to combine them.

{:eek:k, pid_timer} = SysTimer.start_link(nil)

{:eek:k, pid_e7} = ForthIbE.start({:e7, [:e1]})

ForthIbE.add_var:)e7, "eng-name", :e7)

ForthIbE.execute:)e7, "VARIABLE ENDPOINT")

ForthIbE.execute:)e7, "VARIABLE OFFSET")

ForthIbE.execute:)e7, "18000000 OFFSET !")

ForthIbE.execute:)e7, "\"2026-02-20 10:35:22.000\" text-to-unix OFFSET @ THE- END-MARK ! ")

script = ": START BEGIN END-MARK @ receive-time > WHILE 250 delay REPEAT CLOCK pass-next .\"LET'S GO! \" ; "

ForthIbE.execute:)e7, script)



{:eek:k, pid_e1} = ForthIbE.start({:e1, [self()]})

ForthIbE.add_var:)e1, "eng-name", :e1)

script = ": CLOCK 10 0 DO tick TO-ATOM TIMESTAMP eng-name @ stocks FORWARD 1000 DELAY LOOP ;"

ForthIbE.execute:)e1, script)



# everything is ready to launch

ForthIbE.execute:)e7, "START")

The difference between the signal cycle of the process :e7 is the use of the word pass-next, which forcibly starts processing the script on the drains, in this case on the engine :e1.

The output to the console of the operation of two generators in combination is shown on the article's splash screen.
 
Top Bottom