ByteByteFork

From Esolang
Jump to navigation Jump to search

ByteByteFork

ByteByteFork is ByteByteJump with (pseudo) multithreading.

Compared to ByteByteJump, I believe it doesn't bring anything special to the table, in terms of computation. But, with a little love, it could probably look like the famous green digital rain effect seen in The Matrix, which would be pretty cool.

Then, making a MUD or an Interactive Fiction out of it would be quite challenging.


Overview

Each instruction consists of 3 addresses A B C.

A is the source address, B is the destination address, and C is the fork address.

There are several execution threads. It works like ByteByteJump, except that instead of jumping, threads fork themselves. After copying the content of address A to address B, the parent thread jumps to the next instruction, while a new thread appears at the fork address C.


Terminate a thread

If A and B point to the same address, the thread is terminated.


Inhibit forking

If C is pointing to the address of the next instruction (where the parent thread will jump), then no forking happens.


Reading conflicts

There are several options.

If one thread reads a cell while other ones are writing it, the value-before-writing could be read, so the order in which threads are actually executed wouldn't matter much. Of course, this is ok for a high level implementation. In a low level implementation, copy operations would rather be applied one by one, and the threads order of execution would matter.

I think the low level "straight" version is fine.


Writing conflicts

There are several options.

If several threads are supposed to write different things at the same place at the same time, which one should be written? One way of doing it would be to choose the oldest writing thread. This would require keeping track of the order of creation of threads. Another way would be to make a random choice, which would introduce non-determinism into the recipe. Finally, in a low level implementation, we could just write as we go.

I think the low level "straight" version is fine.


I/O

Could be something like:

  • If zero is used as copy address A, then one byte is read from input and written to the destination address B.
  • If zero is used as destination address B, then the byte the copy address A points to is sent to output.

(not implemented)


Implementation

A Freepascal implementation is given here:

https://github.com/dissolvd-E/rainline/blob/master/rainline.pp

This version uses byte addressing, with 3-bytes addresses, and a 16MiB memory. The threads' Instruction Pointers are stored at the beginning of the memory (the first thread's IP must be located at address 3), followed by a zero value which marks the end of the IP zone and the beginning of the data/code zone. When the source address and the destination address of an instruction are the same, the thread is marked as being terminated, by making its IP point to its own address. When the fork address is the address of the next instruction, no forking happens.

This implementation is minimal and CLI based. Its purpose is to clarify the definition of the language.


Session sample

   Rainline
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > i
   Enter: Address (aligned) > 9
   Enter: Source Destination Fork (space-separated) > 27 30 18
   [9]  Source:27  Destination:30  Fork:18
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > w
   Enter: Address Content (space-separated) > 27 55
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > w
   Enter: Address Content (space-separated) > 3 9
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > o
   Enter: Start (aligned) > 0
   Enter: Length > 5
   [0]  Source:0  Destination:9  Fork:0
   [9]  Source:27  Destination:30  Fork:18
   [18]  Source:0  Destination:0  Fork:0
   [27]  Source:55  Destination:0  Fork:0
   [36]  Source:0  Destination:0  Fork:0
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > s
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > o
   Enter: Start (aligned) > 0
   Enter: Length > 5
   [0]  Source:0  Destination:18  Fork:0
   [9]  Source:27  Destination:30  Fork:18
   [18]  Source:0  Destination:0  Fork:0
   [27]  Source:55  Destination:55  Fork:0
   [36]  Source:0  Destination:0  Fork:0
   (w)ord-input  (i)nstruction-input  (d)ump-words  (o)utput-instructions  (s)tep  (q)uit  > q


Variant

Instead of simply copying a byte from A to B, we could add 1 to the copied byte.


See also