Tag

Tag is an implementation of a variable Post tag system as a simple, but inscrutable, programming language by Mark C. Chu-Carroll.

Post tag systems
The Post tag machine is simple to the point of triviality. The system is a queue of characters (with one character designated as "Halt"), and a set of rules. Each rule has a different character that selects the rule, and a string of characters. Each step, the machine looks at the first character of the queue, and selects the rule associated with that character. If the character is "Halt", the system just stops, and whatever is left on the queue is the result of the computation. Otherwise, it appends the selected rule's string of characters to the end of the queue, and then removes a fixed number of characters from the front of the queue. The systems are called N-Tag systems where N is number of character dropped each step.

That's it. Look at the front of the queue, use it to pick a set of characters to append, and then remove and discard the first N characters from the queue.

For any N>=2, a Post N-tag system is Turing equivalent.

The Tag language
Tag is an implementation of a Post-tag system with a variable drop length: each rule specifies how many characters should be removed from the queue when that rule is selected.

The syntax is very simple: It's a list of rules. Each rule has the format:

name ":" triggerchar numbertodrop "("characters to append")"

For example,  is a rule named. It will run when the first character on the queue is, and it will drop the first two characters from the queue, and append.

For output, if the number to drop is followed by, then it will print out the dropped characters except for the one that triggered the command.

Sample programs
The classic Hello World program:

fillQueue:a2(pHpeplplpop pWpoprplpd#) printChar:p2!(#)

Simple conditional:

ifA:A2(sss) ifB:B2(ss) ifS:s2(cd) ifC:c2(pA#) ifD:d2(pB#) print:p2!

What this does is: if the first character is an, it inserts 3  s; if it's  , it inserts two  s. On an  , it appends. A  causes it to print   and then halt;   causes it to print   and halt.

So suppose we started with  on the queue. It would pick the rule, drop the two  s, and the queue would be. Then it would pick rule, which drops two, and appends   - so the queue would be. It would run  again, which would append another , leaving. The  appends , so the queue becomes  ; the   appends  , leaving. And then  gets printed, and the program halts.

Let's look at the other cases:  on the queue. Rule  runs, leaving   on the queue. appends, leaving   on the queue. The  appends   onto the queue, leaving the queue as. So it prints, and halts.

Add
Takes a list of digits terminated with an 'x', and outputs the sum of the digits in Unary format: zero :01 one :11(p1) two :21(p1p1) three:31(p1p1p1) four :41(p1p1p1p1) five :51(p1p1p1p1p1) six :61(p1p1p1p1p1p1) seven:71(p1p1p1p1p1p1p1) eight:81(p1p1p1p1p1p1p1p1) nine :91(p1p1p1p1p1p1p1p1p1) end :x1(#) print:p2!

An initial queue of  would produce the output

Factorial
Takes a digit (followed by !) and outputs the factorial, in unary. one :12(p1) two :22(p1p1) three:32(2 2 2 ) four :42(3 3 3 3 ) five :52(4 4 4 4 4 ) six :62(5 5 5 5 5 5 ) seven:72(6 6 6 6 6 6 6 ) eight:82(7 7 7 7 7 7 7 7 ) nine :92(8 8 8 8 8 8 8 8 8 ) print:p2!(#)'

External resources

 * The original presentation of Tag at the Good Math, Bad Math Blog, with links to a Haskell implementation.