From Esolang
Jump to navigation Jump to search

Vein is a minimal esolanguage based on one boundless execution stack and one unbounded counter, designed in 2017 by Keymaker. The language is a fusion of User:ais523's Countercall, an unreleased language of Keymaker's, and new ideas altogether. Vein came to existence when the author was trying to find a proof of Turing-completeness for Countercall, and instead started having ideas for a new language and a method for proving its Turing-completeness. Because of the language's roots in Countercall, terminology from it was respectfully borrowed.

Program and execution

A program consist of at least one procedure, and each line that is not empty (not counting spaces) is a procedure. A procedure definition begins with the identifier of the procedure. Then the (0 or more) commands belonging to it. Commands are either '+' or other identifiers (which must exist defined somewhere in the program). An identifier cannot be named '+'.

Initially, the contents of the execution stack are the first identifier's commands. The counter is 0. The program never terminates. Every cycle, the execution stack is popped twice. (If it at that point has 0 or 1 items, it is undefined behaviour and an error, and not something that can happen in a valid program.) The first popped item is ignored, while the second is inspected:

  • If the item is '+', the counter is increased by one.
  • If the item is not '+', it is therefore an identifier. If the counter is larger than 0, it is decreased by one and the commands belonging to the identifier are pushed into the execution stack, starting from the right-most defined item, moving to the left, so that in the end the first/left-most command in the procedure is placed to the execution stack last (and thus top-most). If the counter was 0 instead, nothing happens (no pushing items, no decreasing counter).

Then the next cycle begins.

Here is an example program, a simple MM program translated to Vein:

i1 . + . a . i2
i2 . + . a . i3
i3 . + . . . i3n . + . i4
i3n . + . + n b1 i3s i4
i3s . d . i4
i4 . + n a1 i4e i6
i4e . c . i5
i5 . + . b . i4
i6 . + . i6
n + +
e + + n
a . a . + . +
b . b . + . + . +
a1 n a2 n + + n
a2 n e n + n a1 a1 n + + n
c . . c c + +
b1 n b2 n + + n
b2 n b3 n + + n
b3 n e n + n b1 b1 n + + n
d . . . . d d + +

The MM program of which the above is a translation:

1 inc A 2
2 inc A 3
3 dec B 4 4
4 dec A 5 6
5 inc B 4
6 halt

Differences from Countercall

While the languages might look similar, their core mechanisms are quite different. To begin with syntax, procedures in Vein do not feature a colon after the identifier. A procedure called 'main' has no special importance. There is no run length encoding of '+'. '-' does not exist as an individual command.

Most importantly, Vein does not have a looping system. Popping an item from the execution stack (in Countercall the call stack is popped after a procedure ends, in Vein the execution stack is popped twice on every cycle before a command executes) does nothing but either increases the counter (with '+') or places more items into the execution stack (in case of identifier, assuming the counter is larger than zero). In Vein the counter cannot go below 0. In Vein, the program never ends.

Computational class

The language is shown Turing-complete with a method of translating Minsky machine to it. See the page linked below.

External resources

  • Vein page (explanation of the language in detail, MM-to-Vein translator, Vein-to-Markov0, interpreter in Python)