brains

From Esolang
Jump to navigation Jump to search

The brains language is a concurrent dialect of brainfuck whose specification was first written by Thomas DiModica in 2011. It takes elements from brainfork, Toadskin, L00P, and Weave, in addition to adding its own constructs to better support concurrency.

Specification

+ increment current cell
- decrement current cell
> move one cell to the right
< move one cell to the left
. print the value of the current cell as a character
, input a character and place its value into the current cell
[ if the current cell is zero, jump past the matching ]
] if the current cell is not zero, jump back to the matching [
( if the current cell is zero, jump past the matching ) or |, if present, as in L00P
| jump past the matching ), as in L00P
) no operation: this is a placeholder for ( and |, as in L00P
: bind the next character to the function occurring after the next character to before the matching ;, as in Toadskin
; ends a function definition, a placeholder for :, can be thought of as a return statement, as in Toadskin
@ separates concurrent programs in a source file, like Weave's ;
~ swap data tapes, as in Weave
% fork the process, like brainfork's Y
& spawn a new thread, semantically like %
{ if the current cell is not zero, jump past the matching }
} if the current cell is zero, jump back to the matching {
= no operation
$ return from a function, or end the program if not in a function
' break out of the current loop: jump past the first unmatched ] or }
` continue: jump to the first unmatched ] or }
* yield the processor
^ V, or up, the current cell, unblocking a thread, if any, blocked on the cell
_ P, or down, the current cell, blocking if its value is zero

Fork/spawn work in a nearly identical way. First, the current cell is set to zero and the next cell to the right is set to one. Then, the fork/spawn takes place. In a fork, the new process gets a copy of the parent thread's current data tape as its new private data tape, and it swaps between this private data tape and its parent's private data tape. If the forking process has multiple threads, the new process has only one thread, a copy of the forking thread. For both fork/spawn, the new thread has its data pointer set to the cell that was set to one, one right to the parent's data pointer. If the fork/spawn should fail, the cell to the right is set to zero, replacing the one. If the new data space cannot be created, the fork fails.

The commands ^ and _ treat the current cell as a semaphore. They guarantee atomicity and proper semaphore behavior. While ^ could have been removed in favor of + being atomic, having ^ removes the need for + to check if it is unblocking any threads.

External resources