From Esolang
Jump to navigation Jump to search

Based on Minsky Swap. Neither Portable Minsky Machine Notation nor Szewczyk notation for Minsky machine are suited to directly implementing two register counter machines. PMMN requires significant restructuring of some algorithms to run with only two registers (PMMN is effectively a restricted subset of the hypothetical Minsky machine language),[citation needed] and SNMM is not TC with only two registers. This is an attempt at a somewhat usable two register counter machine. Accidentally became a Deadfish reference.

Token Description
i Increment current register
d If current register is not 0, decrement and skip the next token, otherwise NOP
s Swap registers
o Output current register (as an integer, or optionally as a list of integers or characters Gödel encoded using prime factorisation)
:{label} Program label - NOP
_{label} Jump to matching :{label}

:{label} tokens must be whitespace delimited. _{label} tokens must be whitespace terminated. idso tokens may be run together or separated by whitespace.

Multiple :{label}s are not an error. They could be useful for NOPs, comments, or other markers. However, the jump behaviour when multiple targets exist is undefined. Implementations may choose to pick first, closest, not yet visited, random, etc.

Use :{label}s (no whitespace) to document code.


An interpreter should provide a mechanism to set the first register to a user supplied value before starting the program. Ideally it should Gödel-encode user supplied lists or strings into a single register value.

An integer output mask should be optionally accepted to filter the results of the o command based on the prime factorisation of the mask to be applied to all instances of o encountered during a particular execution.


Truth Machine

d_zero i
:one o _one
:zero o

Copy (duplicate and add) a prime encoded 'virtual' register



  d_done i

:added s _dupe_add

  dd dd dd dd dd dd dd dd dd dd dd dd dd dd d_done siis


This program illustrates the exponential slowdown that such restricted machines are subject to. Duplicating 5 takes ~6secs on my laptop. Duplicating 6 takes 1.5 minutes.

Example output:

  • Input: 2**3 = 8 (vreg.2 = 3)
 R0: 8
 R1: 3375
    [0, 3, 3]
  • Input: 2**5 = 32 (vreg.2 = 5)
 R0: 32
 R1: 759375
    [0, 5, 5]
  • Input 2**3 * 3**4 = 648 (add to existing value)
 R0: 648
    [3, 4]
 R1: 273375
    [0, 7, 3]
  • Input: 2**3 * 7**2 = 392 (Leaving adjacent vregs untouched)
 R0: 392
    [3, 0, 0, 2]
 R1: 165375
    [0, 3, 3, 2]

Hello, World!

This is a terrible way to encode data in this language, using virtual registers as 'cells' to encode an entire string at once. It is meant to be a challenge for an optimising interpreter, and performance profiler, as well as a demonstration of a macro compiler extension. Since incrementing by a constant is accomplished by run length encoding instructions like Deadfish iiiiiiiiii or bf +++++++++, and for virtual registers this means repeating runs of loops to achieve the same thing. The repeat(constant) { code block } macro handles this (with auto label suffix incrementing). This program takes a stupid amount of time to execute. I haven't profiled it yet, but 1000s of years to heat-death-of-the-universe is what the example is aiming for. I'm hoping an optimising interpreter can take mathematical shortcuts and make this run from just the macro-expanded code (829 lines), but it's a WIP.


repeat(72)  { :H0 sd_H1 sii_H0 }
repeat(101) { :E0 sd_E1 siii_E0 }
repeat(108) { :L0 sd_L1 s repeat(1085) { i } _L0 }
repeat(111) { :O0 sd_O1 s repeat(253) { i } _O0 }
repeat(44)  { :COMMA0 sd_COMMA1 siiiiiiiiiiiii_COMMA0 }
repeat(32)  { :SPACE0 sd_SPACE1 siiiiiiiiiiiiiiiii_SPACE0 }
repeat(87)  { :W0 sd_W1 siiiiiiiiiiiiiiiiiii_W0 }
repeat(114) { :R0 sd_R1 repeat(29) { i } _R0 }
repeat(100) { :D0 sd_D1 repeat(37) { i } _D0 }
repeat(33)  { :EXCLAIM0 sd_EXCLAIM1 repeat(43) { i } _EXCLAIM0 }

External resources