He escrito un intérprete de Brainfuck en Lua


Brainfuck es un lenguaje de programación esotérico (Esolang) muy simple, tanto que se puede crear intérpretes desde cualquier lenguaje de programación moderno, hasta en Lua. También es considerado un Turing Completo.

Si ya viste la película The Imitation Game (recomendadísima por cierto) entonces sabes a lo que me refiero con Máquina de Turing, pero en resumen, una máquina de Turing es una máquina automática que puede leer y escribir simbolos en una cinta y cambiar su comportamiento dependiendo de su estado.

Como funciona brainfuck




La idea de Brainfuck es imitar a la máquina de Turing así que con ella tenemos "una cinta" de memoria para trabajar, es mas bien un array de bytes, a cada item del array lo llamaremos celda. Aunque según el creador del lenguaje su límite debería ser 30, 000 bytes (celdas) esto solo es hipotético, en el caso de mi intérprete no he dejado un límite.

Digamos que las celdas representan la memoria RAM de esta máquina, a cada celda le asignamos un número entero, inicialmente cero, el equivalente a nulo o inexistente, cada celda puede asignarse hasta el número 255, ya que 256 es el número máximo de valores que podemos almacenar en un byte, aunque vuelvo a repetir, ésto es hipotético, queda en el programador respetar o no ésto, aunque según el intérprete podría estar restringido o no también.

Entonces Brainfuck tiene 8 instrucciones nada mas:

< Mueve el cabezal hacia la izquierda.
> Mueve el cabezal hacia la derecha.
+ Aumenta el byte hacia donde apunta el cabezal (suma 1)
- Disminuye el byte hacia donde apunta el cabezal (resta 1)
. Imprime el byte apuntado por el cabezal (normalmente en forma de caracter ascii)
, Lee un byte del usuario y lo almacena en la celda donde apunta el cabezal.
[ Inicio de un bucle infinito.
] Cierre del bucle, si el byte apuntado es cero continúa si no regresa al inicio del bucle.

Esto es suficiente para crear programas, desde el hola mundo hasta el juego de la vida y mas...

Como usar brainfuck.lua


++++++++++[>+++++++>++++++++++>+++>+<<<<->++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Este es el código fuente para imprimir el Hello World! en Brainfuck.

Puedes copiar el texto y guardarlo en un archivo de texto con extensión *.b o *.bf.

Para usar mi intérprete debes descargarlo de mi repositorio aquí.

Debes tener Lua 5.3 o superior instalado. Si tienes una versión anterior debes realizar un cambio que en el código está anotado como comentario.

Ejecutamos lo siguiente:

lua brainfuck.lua codigo-brainfuck.bf

Donde codigo-brainfuck.bf es sustituido por el nombre de tu archivo, debes tener el archivo brainfuck.lua en la misma carpeta de tu código brainfuck.

Como programar en brainfuck


Aunque explique la sintaxis sigue siendo complicado comprender la forma de programar en brainfuck, claro por algo se llama "jode cerebros", pero en realidad no es nada mas una forma "muy friki" de programar.

Variables


No hay variables como tal, pero podemos imaginar que cada celda es una variable, si deseamos que la celda 0 tenga el valor 4, entonces solo tenemos que escribir ++++, ya que éste aumenta el byte 4 veces, y al imprimir (.) el byte se convierte en un caracter ascii, por lo que es importante tener en cuenta la tabla ascii también para "almancenar caracteres".

Ejemplo:
>+>++>+++ 
Ahí lo que tenemos son 3 bytes en las celdas 1, 2, 3. con valor 1, 2, 3 respectivamente.

Bucle While


El bucle While se representa con los simbolos [] que al final del bucle si el byte donde está ubicado el cabezal vale 0 entonces rompe el bucle y continúa a la siguiente instrucción, pero es importante que lo que vale para romper el bucle es el byte que apunta en el momento del cierre por lo que podemos utilizar ese byte de muchas maneras.

Ejemplo:
+[]
Este ejemplo crea un bucle infinito, ya que al inicio sumamos al byte apuntado, por lo que daría uno pero nunca convertimos ese byte a 0.

For


No hay un ciclo for, pero podemos apañarlas con el bucle While con la siguiente estructura:

Escribimos en un byte la cantidad de repeticiones que deseamos realizar.
Escribimos el código que deseamos en el bucle.
Al final del bucle apuntamos al byte de las repeticiones y restamos.

Ejemplo:

++++++++++[>++++++++++<-]
Preparamos la celda 0 para tener valor de 10, luego en el bucle apuntamos a la celda 1, sumamos 10 y luego regresamos a la celda 0 y le restamos 1. Esto hace que la celda 1 sume 10, 10 veces, es decir, que adquiera el valor 100.

Ejemplo de programa en brainfuck


El siguiente ejemplo, es un código que escribí que imprime los números del 0 al 9:

++++++++++> almacenamos en la celda 0 el valor 10 (salto de linea)

++++[>++++++++++<-] en la celda 1 la sumamos hasta 4 luego en la celda 2 sumamos 10 veces restamos uno y el puntero regresa a la celda 1 como la celda vale 4 el bucle se repetira 4 veces

>++++++++. en la celda 2 sumamos 8 para llegar a 48 (caracter 0) e imprimimos
<+++++++++ nos devolvemos a la celda 1 y le asignamos el valor 9 para imprimir los demas numeros
[<.>>+.<-] nos vamos a la celda cero e imprimimos luego a la celda 2 sumamos 1 e imprimimos;
nos devolvemos a la celda 1 y restamos
<. imprimimos por ultima vez el salto de linea
Con esto el programa imprime los numeros del 0 al 9

Con esto ya tendrías todo lo necesario para practicar un poco.

Ahora te dejo una tarea, ¿Puedes escribir el código brainfuck para que imprima tu nombre?

Si lo logras, déjamelo en los comentarios!

Guinxü lang


Debido a que todo esto fue por un vídeo que publicó Guinxu sobre "lenguajes raros" me pareció curioso cambiar la sintaxis del brainfuck para crear el Guinxu lang, donde solo cambio los caracteres usados para las instrucciones con los caracteres de guinxu.

En comparación, la sintaxis es la siguiente:

> = g
< = u
+ = i
- = n
. = x
, = ü
[ = [
] = ]

Aquí tienes el mismo ejemplo de los números en guinxu lang:

iiiiiiiiiiu
iiii[uiiiiiiiiiign]
uiiiiiiiix
giiiiiiiii
[gxuuixgn]
gx


Si te gustaría probar mi intérprete brainfuck o el intérprete de guinxu lang puedes descargar el repositorio aquí.

Edit: He modificado el guinxu lang por un "pequeñito" fallo de diseño, Guinxu lleva dos letras "u", por lo que he decidido cambiar la segunda "u" por "ü", por suerte, esto no afecta al código de ejemplo.