January 30 2016 Saturday at 04:14 PM

brainfuck in liquid

It can be shown that Shopify's templating language (Liquid) is Turing-complete. An easy way to prove this is to implement an interpreter for another Turing-complete language, such as brainfuck.

Try posting a comment with the email "brainfuck" and some code as the body. It will run on Shopify's servers and output the value directly into the HTML.

For example, ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. is a good place to start.

This one will take several seconds to run:

+++++++++++
>+>>>>++++++++++++++++++++++++++++++++++++++++++++
>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>
+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-
<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<
-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]
>[<<+>>[-]]<<<<<<<]>>>>>[+++++++++++++++++++++++++
+++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++
++++++++++++++++++++++++++++++++++++++++++++.[-]<<
<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<
[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]

 

The horrendous Liquid template:

{% assign memory = 0 | reverse %}{% assign stack = "" | split: "" %}{% assign program = program | split: "" %}{% assign ptr = 0 %}{% assign ip = 0 %}{% for i in (1..2000000) %}{% assign op = program[ip] %}{% case op %}{% when '+' %}{% assign next_ptr = ptr | plus: 1 %}{% assign rest = memory | slice: next_ptr, memory.size %}{% if memory[ptr] == 255 %}{% assign cell = 0 | reverse %}{% else %}{% assign cell = memory[ptr] | plus: 1 | reverse %}{% endif %}{% assign memory = memory | slice: 0, ptr | concat: cell | concat: rest %}{% when '-' %}{% assign next_ptr = ptr | plus: 1 %}{% assign rest = memory | slice: next_ptr, memory.size %}{% if memory[ptr] == 0 or memory[ptr] == nil %}{% assign cell = 255 | reverse %}{% else %}{% assign cell = memory[ptr] | minus: 1 | reverse %}{% endif %}{% assign memory = memory | slice: 0, ptr | concat: cell | concat: rest %}{% when '>' %}{% assign ptr = ptr | plus: 1 %}{% if memory.size <= ptr %}{% assign cell = 0 | reverse %}{% assign memory = memory | concat: cell %}{% endif %}{% when '<' %}{% assign ptr = ptr | minus: 1 %}{% when '[' %}{% if memory[ptr] == 0 or memory[ptr] == nil %}{% assign depth = 1 %}{% for i in (ip..program.size) %}{% assign ip = ip | plus: 1 %}{% if program[ip] == ']' %}{% assign depth = depth | minus: 1 %}{% elsif program[ip] == '[' %}{% assign depth = depth | plus: 1 %}{% endif %}{% if depth == 0 %}{% break %}{% endif %}{% endfor %}{% else %}{% assign target_instruction = ip | reverse %}{% assign stack = stack | concat: target_instruction %}{% endif %}{% when ']' %}{% assign stack_last = stack.size | minus: 1 %}{% if memory[ptr] > 0 %}{% assign ip = stack[stack_last] %}{% else %}{% assign stack = stack | slice: 0, stack_last %}{% endif %}{% when '.' %}{% case memory[ptr] %}{% when 10 %}
{% when 32 %} {% when 33 %}!{% when 34 %}"{% when 35 %}#{% when 36 %}${% when 37 %}%{% when 38 %}&{% when 39 %}'{% when 40 %}({% when 41 %}){% when 42 %}*{% when 43 %}+{% when 44 %},{% when 45 %}-{% when 46 %}.{% when 47 %}/{% when 48 %}0{% when 49 %}1{% when 50 %}2{% when 51 %}3{% when 52 %}4{% when 53 %}5{% when 54 %}6{% when 55 %}7{% when 56 %}8{% when 57 %}9{% when 58 %}:{% when 59 %};{% when 60 %}<{% when 61 %}={% when 62 %}>{% when 63 %}?{% when 64 %}@{% when 65 %}A{% when 66 %}B{% when 67 %}C{% when 68 %}D{% when 69 %}E{% when 70 %}F{% when 71 %}G{% when 72 %}H{% when 73 %}I{% when 74 %}J{% when 75 %}K{% when 76 %}L{% when 77 %}M{% when 78 %}N{% when 79 %}O{% when 80 %}P{% when 81 %}Q{% when 82 %}R{% when 83 %}S{% when 84 %}T{% when 85 %}U{% when 86 %}V{% when 87 %}W{% when 88 %}X{% when 89 %}Y{% when 90 %}Z{% when 91 %}[{% when 92 %}\{% when 93 %}]{% when 94 %}^{% when 95 %}_{% when 96 %}`{% when 97 %}a{% when 98 %}b{% when 99 %}c{% when 100 %}d{% when 101 %}e{% when 102 %}f{% when 103 %}g{% when 104 %}h{% when 105 %}i{% when 106 %}j{% when 107 %}k{% when 108 %}l{% when 109 %}m{% when 110 %}n{% when 111 %}o{% when 112 %}p{% when 113 %}q{% when 114 %}r{% when 115 %}s{% when 116 %}t{% when 117 %}u{% when 118 %}v{% when 119 %}w{% when 120 %}x{% when 121 %}y{% when 122 %}z{% when 123 %}{{"{"}}{% when 124 %}|{% when 125 %}}{% when 126 %}~{% endcase %}{% when ',' %}{% assign next_ptr = ptr | plus: 1 %}{% assign rest = memory | slice: next_ptr, memory.size %}{% assign cell = input | first | default: 0 | reverse %}{% assign input = input | slice: 1, input.size %}{% assign memory = memory | slice: 0, ptr | concat: cell | concat: rest %}{% endcase %}{% assign ip = ip | plus: 1 %}{% if ip >= program.size %}{% break %}{% endif %}{% endfor %}