We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
Crochet
Crochet is an esolang invented by User:Stareye. It is designed to have an extremely minimal, highly structured syntax, as well as a consistent modal of computation, based on a high degree of parallelism.
Language
Below is an example of a Crochet program which calculates the 20th fibonacci number.
# Crochet demo
origin
spawn
_ -> 20 fib
pop
_ -> @ ! 0
fib
spawn
0 -> 0
1 -> 1
_ -> @ -1 fib -1 fib 0
pop
_ -> +@
Syntax
The individual code blocks are referred to as "nodes". The first line of a node is its name, which can be referenced elsewhere. The only reserved keywords in Crochet are spawn and pop, so any other word is valid. Names must begin with an alphabetic character, but can contain any characters otherwise.
Every node must have a spawn block and a pop block. The lines in the spawn and pop blocks are referred to as "rules". Each rule dictates the node's behaviour under some condition.
Comments begin with a #, and are only permitted outside of nodes.
Behaviour
A node is essentially a wrapper around a single internal value, stored as a 64 bit unsigned integer. This value is always 0 initially. When a node is created, it looks at the rules in the spawn block, and applies the rule based on the current value of the node that instantiated it. That is to say, if the node that created it had an internal value of 3, the created node would apply the spawn rule corresponding to the number 3.
The first component of a rule is the match, which is the number required for it to be invoked. This can be a number, or a wildcard _, which matches if none of the other rules do. There must be exactly one wildcard rule for every spawn and pop block.
The actual content of the rule is a series of actions. A number on its own sets the internal value of the node to that number. For example, in the line _ -> 20 fib, The first action sets the node's value to 20. An operation preceding a number applies that operation between the node's internal value and the constant. For example, on the line _ -> @ -1 fib -1 fib, each -1 subtracts 1 from the node's value.
There are also two special numbers that can be operated on. @ represents the value of the rule that was applied. This is especially useful with _ wildcard rules. & represents user input, and reads a single byte from stdin.
There are two further actions that can be taken. The first is !, which prints the internal value of the node to stdout. The second is to spawn a child node, simply by invoking its name.
Execution always begins at the node called origin. The order in which nodes are declared is irrelevant, they can always be executed from anywhere.
Pop rules are invoked when any child of a given node finishes executing. When this happens, the rule corresponding to the internal value of the child node when it finished is executed. For example, In the rule _ -> +@, the internal value of the child is simply added to the parent, regardless of what it is.
Every node executes on its own thread. This means that the order in which pop rules are invoked is not guaranteed, and that memoization of node invocations is impossible. A node simply keeps track of the number of currently active children it has spawned, and returns its value to its parent when that number reaches 0. Below is a silly example
origin
spawn
_ -> random
pop
_ -> @ ! 0
random
spawn
_ -> one two
pop
_ -> @
one
spawn
_ -> 1
pop
_ -> @
two
spawn
_ -> 2
pop
_ -> @
This program's behaviour is impossible to determine, because the order of execution is not guaranteed (although in practice, this is not the case due to the specific behaviour of the implementation).
Truth Machine
(running this spawns a new system thread for every invocation of act. Probably a bad idea)
origin
spawn
_ -> & act
pop
_ -> 0
act
spawn
48 -> 0 !
_ -> 1 ! act
pop
_ -> @