4 puntos por GN⁺ 2024-04-25 | 1 comentarios | Compartir por WhatsApp
  • Piet es un lenguaje de programación esotérico diseñado para que el código parezca arte abstracto, y toma su nombre de Piet Mondrian, pionero del arte abstracto geométrico
  • Un programa es un gráfico hecho con 20 colores reconocidos; el ejecutor se mueve entre bloques de color e interpreta los cambios de color como comandos
  • Todos los datos existen solo como enteros y se almacenan en una pila; el tamaño de un bloque de color es un valor, pero no se sube automáticamente a la pila sin el comando push
  • El control de flujo se determina mediante Direction Pointer y Codel Chooser, además de reglas para bloques negros, bordes y bloques blancos; algunos comportamientos pueden variar según la implementación
  • Aunque existen ejemplos y un ecosistema de herramientas externas, no hay un intérprete oficial autoritativo, y el manejo de errores y la interpretación de colores no estándar siguen dependiendo de la implementación

La idea básica de Piet

  • Piet es un lenguaje de programación en el que el código del programa parece arte abstracto
  • Su nombre proviene de Piet Mondrian, pionero del arte abstracto geométrico
  • Se quería usar el nombre Mondrian, pero ya existía un lenguaje de scripting con ese nombre, así que se usó Piet
  • Después de escribirse la especificación, se formó una pequeña comunidad que ha creado programas, intérpretes, IDEs y compiladores
  • No existe un intérprete oficial autoritativo, y las implementaciones disponibles pueden interpretar la especificación de formas ligeramente distintas
  • Se han agregado algunas aclaraciones a la especificación, pero es posible que algunas implementaciones existentes no las sigan

Colores y unidades de código

  • Piet usa un total de 20 colores
    • 18 colores forman parte del ciclo de matiz y del ciclo de luminosidad
    • El blanco y el negro no forman parte de ninguno de los dos ciclos
  • El ciclo de matiz sigue el orden red -> yellow -> green -> cyan -> blue -> magenta -> red
  • El ciclo de luminosidad sigue el orden light -> normal -> dark -> light
    • light también se considera un paso más oscuro que dark, y viceversa
  • Se pueden usar colores no estándar como naranja o marrón, pero su efecto depende de la implementación
    • En el caso más simple, los colores no estándar se tratan como blanco
    • Otra posibilidad es que se traten como negro

Codels y bloques de color

  • El código Piet es un gráfico compuesto por colores reconocibles
  • Como cada píxel de código tiene significado en el lenguaje, en programas ampliados para verse mejor, un único píxel del código se llama codel
  • La unidad básica de ejecución es el bloque de color
    • Un bloque de color es un área donde codels del mismo color están conectados vertical u horizontalmente
    • Los bloques que solo se tocan en diagonal no se consideran conectados
    • Un bloque de color puede tener cualquier forma y puede contener huecos internos de otros colores
    • Los huecos internos no forman parte de ese bloque

Pila y representación de valores

  • Piet almacena todos los valores de datos en una pila
  • Los valores de datos solo existen como enteros
    • Según el comando, pueden ingresarse o imprimirse como valores de caracteres Unicode
  • Conceptualmente, la pila tiene profundidad infinita, pero una implementación puede imponer un tamaño máximo finito de pila
  • Si ocurre un desbordamiento en una pila finita, es un error en tiempo de ejecución, y su manejo depende de la implementación
  • Un bloque de color que no sea negro ni blanco representa un valor entero igual al número de codels de ese bloque
    • Los enteros no positivos no pueden representarse directamente
    • Sí pueden generarse mediante operadores
    • El valor de un bloque de color no se hace push automáticamente a la pila; se necesita un comando push explícito
  • Conceptualmente, el tamaño de los enteros también es infinito, pero una implementación puede imponer un tamaño máximo finito de entero
    • Un desbordamiento de entero es un error en tiempo de ejecución y su manejo depende de la implementación

Flujo de ejecución

  • El intérprete comienza la ejecución en el bloque de color que contiene el codel de la esquina superior izquierda del programa
  • Durante la ejecución se mantienen dos estados
    • Direction Pointer (DP): al principio apunta a la derecha, y puede apuntar a derecha, izquierda, abajo o arriba
    • Codel Chooser (CC): al principio apunta a la izquierda, y puede apuntar a la izquierda o a la derecha
  • El siguiente destino de movimiento se decide por el borde del bloque de color actual y la combinación de DP y CC
    • Se encuentra el borde del bloque de color actual que está más lejos en la dirección del DP
    • En ese borde, se elige el codel más alejado en la dirección del CC respecto de la dirección de avance del DP
    • Desde ese codel se avanza en la dirección del DP al bloque de color al que pertenece el codel inmediatamente siguiente
  • Este proceso se repite hasta que se alcanza una condición de terminación, momento en el que el programa finaliza

Bloques negros, bordes y bloques blancos

  • Los bloques de color negro y los bordes del programa actúan como barreras que bloquean el flujo de ejecución
  • Si el intérprete intenta moverse a un bloque negro o salir fuera de un borde, se detiene y alterna el CC
  • Si el segundo intento también falla, rota el DP un paso en sentido horario
  • Después de alternar CC y DP e intentarlo un total de 8 veces, si no puede salir del bloque de color actual, el programa termina
  • Movimiento por bloques blancos

    • Los bloques de color blanco son áreas libres que el intérprete atraviesa sin obstáculos
    • Si se mueve desde un bloque de color a una zona blanca, el intérprete avanza en línea recta en la dirección del DP hasta llegar a un bloque de color que no sea blanco
    • Al moverse a un nuevo color atravesando un bloque blanco, no se ejecuta ningún comando
    • Por esta característica, los bloques blancos permiten cambiar el color actual sin ejecutar comandos, lo que resulta útil para escribir bucles
    • El movimiento por bloques blancos no usa el procedimiento de elegir una salida desde un bloque de color no blanco; solo realiza movimiento en línea recta
  • Cuando queda bloqueado dentro de un bloque blanco

    • Si al atravesar un bloque blanco en línea recta encuentra un bloque negro o un borde, se trata como una restricción
    • En ese caso se alterna el CC, pero como la posición a la que intenta moverse no cambia, el DP rota inmediatamente un paso en sentido horario
    • Luego vuelve a avanzar en línea recta desde el codel blanco actual en la nueva dirección del DP
    • Cada vez que se encuentra una restricción dentro de un bloque blanco, se repite la alternancia del CC y la rotación del DP
    • Si entra a un bloque de color, la ejecución continúa; si dentro del bloque blanco empieza a desandar su camino, no hay salida y la ejecución termina

Sistema de comandos

  • Los comandos de Piet se determinan por el cambio de color al moverse de un bloque de color al siguiente
  • La cantidad de pasos avanzados en el ciclo de matiz y en el ciclo de luminosidad determina el comando
  • En una transición de color realizada a través de un bloque blanco, no se ejecuta ningún comando
  • Comandos de pila y aritmética

    • push: sube a la pila el valor del bloque de color que se acaba de abandonar
    • pop: saca y descarta el valor superior de la pila
    • add: suma los dos valores superiores y sube el resultado de vuelta a la pila
    • subtract: sube a la pila el resultado de restar el valor superior al segundo valor
    • multiply: multiplica los dos valores superiores
    • divide: divide el segundo valor entre el valor superior usando división entera
    • La división por cero es un error dependiente de la implementación, y se recomienda ignorar el comando
    • mod: sube a la pila el resto de dividir el segundo valor entre el valor superior
    • El resultado tiene el mismo signo que el divisor, es decir, el valor superior de la pila
    • Si el valor superior es 0, es un error de división por cero, y se recomienda ignorar el comando
    • mod con un dividendo negativo equivale a la floored division descrita en Wikipedia para la operación módulo
  • Comandos de comparación, punteros y entrada/salida

    • not: cambia el valor superior de la pila a 0 si no es 0, o a 1 si es 0
    • greater: sube 1 a la pila si el segundo valor es mayor que el valor superior; si no, sube 0
    • pointer: saca el valor superior de la pila y rota el DP en sentido horario esa cantidad de veces
    • Si es negativo, rota en sentido antihorario
    • switch: saca el valor superior de la pila y alterna el CC esa cantidad de veces
    • Si es negativo, alterna tantas veces como su valor absoluto
    • duplicate: sube a la pila una copia del valor superior
    • roll: saca los dos valores superiores y rota una parte de la pila restante según la profundidad y la cantidad indicadas
    • Si la profundidad es negativa, es un error y el comando se ignora
    • Un roll que supere la profundidad máxima de pila dependiente de la implementación es un error dependiente de la implementación, y se recomienda ignorar el comando
    • in: lee un número o un carácter desde STDIN y lo sube a la pila
    • Si no hay entrada o, para entrada entera, no se recibe un entero, es un error y el comando se ignora
    • out: imprime en STDOUT el valor superior de la pila como número o carácter
    • Las operaciones que no puedan realizarse por falta de valores en la pila se ignoran y se pasa al siguiente comando

Ejemplos y herramientas

1 comentarios

 
GN⁺ 2024-04-25
Comentarios en Hacker News
  • El último programa de la página de ejemplos es realmente asombroso: una persona llamada Piet vio una obra de arte que le recordó al lenguaje Piet y decidió probar a ejecutarla
    Funcionó, y quizá sea el primer caso en la historia en que un artista gráfico dibujó por accidente un programa de computadora funcional
    https://www.dangermouse.net/esoteric/piet/samples.html
    https://gitlab.fabcity.hamburg/hofalab/piet-get-together

    • Si se afloja lo suficiente la definición de “funcional”, ya se ha mostrado que la mayoría de los salpicones de pintura son programas válidos de Perl
      https://www.mcmillen.dev/sigbovik/
    • Piet J. estaba viendo obras en una pequeña galería y sintió que una de ellas parecía un programa de Piet; el artista dijo que no conocía el lenguaje en absoluto
      Piet tomó una foto de la obra, la convirtió en un archivo de imagen acomodado a colores cercanos a la paleta de Piet y luego la ejecutó; de hecho funcionó, y el código era un bucle infinito que leía caracteres ASCII e imprimía su valor numérico ASCII
      De verdad cuesta creerlo
    • También estuvo bueno el ejemplo que calcula π
      La explicación de que “por supuesto, si escribes un programa más grande puedes obtener un valor más preciso” me sonó a un tipo de chiste que nunca había visto
    • Por desgracia, eso depende de una diferencia entre npiet y la especificación actual de Piet
      Según la especificación, el intérprete debe empezar a deslizarse desde el codel blanco actual en la nueva dirección del DP y seguir hasta entrar en un bloque de color o encontrarse con otra restricción
      Pero el intérprete npiet mira dentro del espacio en blanco y luego retrocede hasta la posición del último codel de color. Algún día quisiera añadir ese comportamiento como opción al lexer de mi compilador de Piet, pero todavía no lo he tocado
      Si se sigue la especificación, ese programa se convierte en un simple bucle no terminante porque las esquinas extremas de casi todos los bloques son adyacentes al blanco. Es bastante difícil escribir programas complejos de Piet que apunten a varios intérpretes y compiladores, porque todos tienen diferencias sutiles de interpretación no documentadas
      Creo que la salida de mi backend de Piet depende menos del intérprete en general, pero solo he investigado a fondo otras tres o cuatro implementaciones
      https://github.com/boothby/repiet/
    • Me pregunto qué probabilidad hay de que dibujos tan simples, es decir, con unos pocos bloques rectangulares grandes, sean programas válidos
      Hojeando la documentación, por la condición de que “las operaciones que no pueden realizarse, como una operación pop cuando no hay suficientes valores en la pila, simplemente se ignoran y se continúa con la siguiente instrucción”, parecería que todas esas imágenes podrían ejecutarse sin errores
      Aun así, cuántas de esas imágenes aleatorias llegan a hacer algo realmente “significativo” es otra cuestión
  • Piet es un experimento emblemático incluso entre los lenguajes de programación esotéricos, pero creo que no alcanza la meta de hacer que un programa se vea como una pintura de Mondrian a menos que el desarrollador realmente se lo proponga
    Me gustaría que la propia estructura del lenguaje estuviera diseñada para que, sin importar lo que “escribas”, se vea como una pintura de Mondrian

    • Aunque bueno, Mondrian en realidad usaba principalmente colores primarios, así que habría sido bastante limitante
  • Siempre me surge esta pregunta: ¿cómo se ve un algoritmo?
    ¿Se podrá hacer en la realidad algo parecido a lo que aparece en la novela de Herman Hesse The Glass Bead Game? El título original es Magister Ludi
    Como alguien orientado a lo visual, quiero creer que sí, y de hecho he usado herramientas así
    https://community.carbide3d.com/uploads/default/original/3X/5/b/5b0872a5666fec9b7bb6fd623c431de03263372d.jpeg
    Pero si no hay una respuesta clara a la pregunta anterior, estas herramientas siempre corren el riesgo de terminar así
    https://blueprintsfromhell.tumblr.com/
    https://scriptsofanotherdimension.tumblr.com/
    También es difícil equilibrar la expresividad visual y la modularidad, y si empujas demasiado la modularidad, es muy fácil volver a la barrera del texto que querías evitar

    • Si escribes Piet a mano, tiene su encanto explorar “cómo se ve un algoritmo”
      Sergei Lewis y yo hicimos cada uno herramientas para generar código Piet. El ensamblador de Sergei produce código mucho más agradable a la vista que mi backend de Piet
      Lo único que realmente se nota en la salida de mi compilador es que usé trampolines con una flojera impresionante
      http://www.toothycat.net/wiki/wiki.pl?MoonShadow/Piet
      https://github.com/boothby/repiet/
      https://en.wikipedia.org/wiki/Trampoline_(computing)
    • Creo que cualquier algoritmo, e incluso cualquier concepto mental, tiene una relación 1:1 con una representación visual
      Es una idea que saqué al leer un libro de Steven Pinker: las palabras abstractas pueden descomponerse en términos más simples y al final terminan describiendo alguna relación espacial. Por ejemplo, “rekindle” puede verse como “volver a juntar dos cosas”
      De forma parecida, un bucle for también es un concepto mental de “una cosa que pasa sobre muchas otras”, y eso tiene una representación visual como “100” -> “010” -> “001”
      Entonces me pregunto si se podrá crear un lenguaje que defina estos componentes como puras transformaciones visuales
    • Para programas simples, hasta podría imaginarse implementar una máquina de Turing donde los símbolos sean colores
  • Esto queda perfecto para una escena de thriller criminal donde bloquea al protagonista o a los investigadores hasta que alguien se da cuenta de que es código
    Y yo que pensaba que solo los códigos QR eran útiles

  • Alguien hizo un quine en Piet: http://mamememo.blogspot.com/2009/10/piet-quine.html?m=1
    La imagen de esa entrada está rota, pero aquí hay una copia: https://codegolf.stackexchange.com/a/23255/103045

  • El momento de descubrir Piet es algo especial, una mezcla de asombro, confusión y sorpresa
    En mi caso, quedó registrado en esta conversación del pódcast de informática “The CS Primer Show” que hago con mi amigo Oz: https://show.csprimer.com/episodes/e2-dont-let-a-gpt-have-all-the-fun

  • En la universidad hubo una clase pequeña sobre lenguajes de programación esotéricos
    Cada quien tenía que elegir uno de entre Brainfuck, Piet y otros para jugar un poco con él, y yo escogí Piet y la pasé bastante bien
    Si soy sincero, la app de ejemplo que hice no era gran cosa en lo estético, y siento que para hacer arte con Piet hay que volverse experto en Piet

  • La página de ejemplos es excelente
    Puedes ver cómo el lienzo va evolucionando hasta volverse cada vez más sofisticado y agradable a la vista
    https://www.dangermouse.net/esoteric/piet/samples.html

  • Eso de que “light se considera un paso más oscuro que dark” está bastante profundo

  • Estaría genial poder crear un autoencoder que aprenda a tomar código de Python o de otros lenguajes menos esotéricos y producirlo en Piet
    Entonces quizá también se podrían generar algoritmos aleatorios, algo parecido a Stable Diffusion